summary refs log tree commit diff
path: root/webclient
diff options
context:
space:
mode:
authorKegan Dougal <kegan@matrix.org>2014-09-05 23:32:51 -0700
committerKegan Dougal <kegan@matrix.org>2014-09-05 23:32:51 -0700
commit1a298aad9c3bbc1f0c80c40a1518c29c511f9fb4 (patch)
tree8c27ca9b59021a5f9211cfb2c167ceaf083987d2 /webclient
parentFix generation of event ids so that they are consistent between local and rem... (diff)
parentAdded instructions for setting up captcha in an obviously named file. (diff)
downloadsynapse-1a298aad9c3bbc1f0c80c40a1518c29c511f9fb4.tar.xz
Added captcha support on both the HS and web client.
Merge branch 'captcha' of github.com:matrix-org/synapse into develop
Diffstat (limited to 'webclient')
-rw-r--r--webclient/CAPTCHA_SETUP46
-rw-r--r--webclient/README7
-rw-r--r--webclient/components/matrix/matrix-service.js25
-rw-r--r--webclient/index.html4
-rw-r--r--webclient/login/register-controller.js48
-rw-r--r--webclient/login/register.html6
6 files changed, 125 insertions, 11 deletions
diff --git a/webclient/CAPTCHA_SETUP b/webclient/CAPTCHA_SETUP
new file mode 100644
index 0000000000..ebc8a5f3b0
--- /dev/null
+++ b/webclient/CAPTCHA_SETUP
@@ -0,0 +1,46 @@
+Captcha can be enabled for this web client / home server. This file explains how to do that.
+The captcha mechanism used is Google's ReCaptcha. This requires API keys from Google.
+
+Getting keys
+------------
+Requires a public/private key pair from:
+
+https://developers.google.com/recaptcha/
+
+
+Setting Private ReCaptcha Key
+-----------------------------
+The private key is a config option on the home server config. If it is not 
+visible, you can generate it via --generate-config. Set the following value:
+
+  recaptcha_private_key: YOUR_PRIVATE_KEY
+  
+In addition, you MUST enable captchas via:
+
+  enable_registration_captcha: true
+
+Setting Public ReCaptcha Key
+----------------------------
+The web client will look for the global variable webClientConfig for config 
+options. You should put your ReCaptcha public key there like so:
+
+webClientConfig = {
+    useCaptcha: true,
+    recaptcha_public_key: "YOUR_PUBLIC_KEY"
+}
+
+This should be put in webclient/config.js which is already .gitignored, rather 
+than in the web client source files. You MUST set useCaptcha to true else a
+ReCaptcha widget will not be generated.
+
+Configuring IP used for auth
+----------------------------
+The ReCaptcha API requires that the IP address of the user who solved the
+captcha is sent. If the client is connecting through a proxy or load balancer,
+it may be required to use the X-Forwarded-For (XFF) header instead of the origin
+IP address. This can be configured as an option on the home server like so:
+
+  captcha_ip_origin_is_x_forwarded: true
+
+
+
diff --git a/webclient/README b/webclient/README
index 0f893b1712..13224c3d07 100644
--- a/webclient/README
+++ b/webclient/README
@@ -1,12 +1,13 @@
 Basic Usage
 -----------
 
-The Synapse web client needs to be hosted by a basic HTTP server.
-
-You can use the Python simple HTTP server::
+The web client should automatically run when running the home server. Alternatively, you can run
+it stand-alone:
 
     $ python -m SimpleHTTPServer
 
 Then, open this URL in a WEB browser::
 
     http://127.0.0.1:8000/
+
+
diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js
index 55cbd4bc14..b7e03657f0 100644
--- a/webclient/components/matrix/matrix-service.js
+++ b/webclient/components/matrix/matrix-service.js
@@ -84,15 +84,32 @@ angular.module('matrixService', [])
         prefix: prefixPath,
 
         // Register an user
-        register: function(user_name, password, threepidCreds) {
+        register: function(user_name, password, threepidCreds, useCaptcha) {         
             // The REST path spec
             var path = "/register";
-
-            return doRequest("POST", path, undefined, {
+            
+            var data = {
                  user_id: user_name,
                  password: password,
                  threepidCreds: threepidCreds
-            });
+            };
+            
+            if (useCaptcha) {
+                // Not all home servers will require captcha on signup, but if this flag is checked,
+                // send captcha information.
+                // TODO: Might be nice to make this a bit more flexible..
+                var challengeToken = Recaptcha.get_challenge();
+                var captchaEntry = Recaptcha.get_response();
+                var captchaType = "m.login.recaptcha";
+                
+                data.captcha = {
+                    type: captchaType,
+                    challenge: challengeToken,
+                    response: captchaEntry
+                };
+            }   
+
+            return doRequest("POST", path, undefined, data);
         },
 
         // Create a room
diff --git a/webclient/index.html b/webclient/index.html
index a7ed9aa15f..baaaa8cef8 100644
--- a/webclient/index.html
+++ b/webclient/index.html
@@ -10,12 +10,14 @@
    
     <meta name="viewport" content="width=device-width">
    
-    <script type='text/javascript' src='js/jquery-1.8.3.min.js'></script> 
+    <script type='text/javascript' src='js/jquery-1.8.3.min.js'></script>
+    <script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script> 
     <script src="js/angular.min.js"></script>
     <script src="js/angular-route.min.js"></script>
     <script src="js/angular-sanitize.min.js"></script>
     <script type='text/javascript' src='js/ng-infinite-scroll-matrix.js'></script>
     <script src="app.js"></script>
+    <script src="config.js"></script>
     <script src="app-controller.js"></script>
     <script src="app-directive.js"></script>
     <script src="app-filter.js"></script>
diff --git a/webclient/login/register-controller.js b/webclient/login/register-controller.js
index 5a14964248..b3c0c21335 100644
--- a/webclient/login/register-controller.js
+++ b/webclient/login/register-controller.js
@@ -19,6 +19,12 @@ angular.module('RegisterController', ['matrixService'])
                                     function($scope, $rootScope, $location, matrixService, eventStreamService) {
     'use strict';
     
+    var config = window.webClientConfig;
+    var useCaptcha = true;
+    if (config !== undefined) {
+        useCaptcha = config.useCaptcha;
+    }
+    
     // FIXME: factor out duplication with login-controller.js
     
     // Assume that this is hosted on the home server, in which case the URL
@@ -87,9 +93,12 @@ angular.module('RegisterController', ['matrixService'])
     };
 
     $scope.registerWithMxidAndPassword = function(mxid, password, threepidCreds) {
-        matrixService.register(mxid, password, threepidCreds).then(
+        matrixService.register(mxid, password, threepidCreds, useCaptcha).then(
             function(response) {
                 $scope.feedback = "Success";
+                if (useCaptcha) {
+                    Recaptcha.destroy();
+                }
                 // Update the current config 
                 var config = matrixService.config();
                 angular.extend(config, {
@@ -116,11 +125,21 @@ angular.module('RegisterController', ['matrixService'])
             },
             function(error) {
                 console.trace("Registration error: "+error);
+                if (useCaptcha) {
+                    Recaptcha.reload();
+                }
                 if (error.data) {
                     if (error.data.errcode === "M_USER_IN_USE") {
                         $scope.feedback = "Username already taken.";
                         $scope.reenter_username = true;
                     }
+                    else if (error.data.errcode == "M_CAPTCHA_INVALID") {
+                        $scope.feedback = "Failed captcha.";
+                    }
+                    else if (error.data.errcode == "M_CAPTCHA_NEEDED") {
+                        $scope.feedback = "Captcha is required on this home " +
+                                          "server.";
+                    }
                 }
                 else if (error.status === 0) {
                     $scope.feedback = "Unable to talk to the server.";
@@ -142,6 +161,33 @@ angular.module('RegisterController', ['matrixService'])
             }
         );
     };
+	
+	var setupCaptcha = function() {
+	    console.log("Setting up ReCaptcha")
+        var config = window.webClientConfig;
+        var public_key = undefined;
+        if (config === undefined) {
+            console.error("Couldn't find webClientConfig. Cannot get public key for captcha.");
+        }
+        else {
+            public_key = webClientConfig.recaptcha_public_key;
+            if (public_key === undefined) {
+                console.error("No public key defined for captcha!")
+            }
+        }
+	    Recaptcha.create(public_key,
+	    "regcaptcha",
+	    {
+	      theme: "red",
+	      callback: Recaptcha.focus_response_field
+	    });
+	};
 
+	$scope.init = function() {
+        if (useCaptcha) {
+	        setupCaptcha();
+        }
+	};
+    
 }]);
 
diff --git a/webclient/login/register.html b/webclient/login/register.html
index 06a6526b70..a27f9ad4e8 100644
--- a/webclient/login/register.html
+++ b/webclient/login/register.html
@@ -12,7 +12,6 @@
                 
                 <div style="text-align: center">
                     <br/>
-
                     <input ng-show="!wait_3pid_code" id="email" size="32" type="text" ng-focus="true" ng-model="account.email" placeholder="Email address (optional)"/>
                     <div ng-show="!wait_3pid_code" class="smallPrint">Specifying an email address lets other users find you on Matrix more easily,<br/>
                         and will give you a way to reset your password in the future</div>
@@ -26,7 +25,10 @@
                     <input ng-show="!wait_3pid_code" id="displayName" size="32" type="text" ng-model="account.displayName" placeholder="Display name (e.g. Bob Obson)"/>
                     <br ng-show="!wait_3pid_code" />
                     <br ng-show="!wait_3pid_code" />
-                    
+
+
+                    <div id="regcaptcha" ng-init="init()" />
+
                     <button ng-show="!wait_3pid_code" ng-click="register()" ng-disabled="!account.desired_user_id || !account.homeserver || !account.pwd1 || !account.pwd2 || account.pwd1 !== account.pwd2">Sign up</button>
 
                     <div ng-show="wait_3pid_code">