summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2020-03-02 17:05:09 +0000
committerRichard van der Hoff <richard@matrix.org>2020-03-02 17:05:09 +0000
commitb68041df3dcbcf3ca04c500d1712aa22a3c2580c (patch)
treeaaeddfbbe7f6349b79ff1af844dd78a9a343f2a9 /synapse
parentMerge remote-tracking branch 'origin/release-v1.11.1' into release-v1.11.1 (diff)
downloadsynapse-b68041df3dcbcf3ca04c500d1712aa22a3c2580c.tar.xz
Add a whitelist for the SSO confirmation step.
Diffstat (limited to 'synapse')
-rw-r--r--synapse/config/sso.py18
-rw-r--r--synapse/rest/client/v1/login.py26
2 files changed, 36 insertions, 8 deletions
diff --git a/synapse/config/sso.py b/synapse/config/sso.py
index f426b65b4f..56299bd4e4 100644
--- a/synapse/config/sso.py
+++ b/synapse/config/sso.py
@@ -37,11 +37,29 @@ class SSOConfig(Config):
 
         self.sso_redirect_confirm_template_dir = template_dir
 
+        self.sso_client_whitelist = sso_config.get("client_whitelist") or []
+
     def generate_config_section(self, **kwargs):
         return """\
         # Additional settings to use with single-sign on systems such as SAML2 and CAS.
         #
         sso:
+            # A list of client URLs which are whitelisted so that the user does not
+            # have to confirm giving access to their account to the URL. Any client
+            # whose URL starts with an entry in the following list will not be subject
+            # to an additional confirmation step after the SSO login is completed.
+            #
+            # WARNING: An entry such as "https://my.client" is insecure, because it
+            # will also match "https://my.client.evil.site", exposing your users to
+            # phishing attacks from evil.site. To avoid this, include a slash after the
+            # hostname: "https://my.client/".
+            #
+            # By default, this list is empty.
+            #
+            #client_whitelist:
+            #  - https://riot.im/develop
+            #  - https://my.custom.client/
+
             # Directory in which Synapse will try to find the template files below.
             # If not set, default templates from within the Synapse package will be used.
             #
diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py
index 1acfd01d8e..b2bc7537db 100644
--- a/synapse/rest/client/v1/login.py
+++ b/synapse/rest/client/v1/login.py
@@ -556,6 +556,9 @@ class SSOAuthHandler(object):
 
         self._server_name = hs.config.server_name
 
+        # cast to tuple for use with str.startswith
+        self._whitelisted_sso_clients = tuple(hs.config.sso_client_whitelist)
+
     async def on_successful_auth(
         self, username, request, client_redirect_url, user_display_name=None
     ):
@@ -605,11 +608,6 @@ class SSOAuthHandler(object):
             registered_user_id
         )
 
-        # Remove the query parameters from the redirect URL to get a shorter version of
-        # it. This is only to display a human-readable URL in the template, but not the
-        # URL we redirect users to.
-        redirect_url_no_params = client_redirect_url.split("?")[0]
-
         # Append the login token to the original redirect URL (i.e. with its query
         # parameters kept intact) to build the URL to which the template needs to
         # redirect the users once they have clicked on the confirmation link.
@@ -617,17 +615,29 @@ class SSOAuthHandler(object):
             client_redirect_url, "loginToken", login_token
         )
 
-        # Serve the redirect confirmation page
+        # if the client is whitelisted, we can redirect straight to it
+        if client_redirect_url.startswith(self._whitelisted_sso_clients):
+            request.redirect(redirect_url)
+            finish_request(request)
+            return
+
+        # Otherwise, serve the redirect confirmation page.
+
+        # Remove the query parameters from the redirect URL to get a shorter version of
+        # it. This is only to display a human-readable URL in the template, but not the
+        # URL we redirect users to.
+        redirect_url_no_params = client_redirect_url.split("?")[0]
+
         html = self._template.render(
             display_url=redirect_url_no_params,
             redirect_url=redirect_url,
             server_name=self._server_name,
-        )
+        ).encode("utf-8")
 
         request.setResponseCode(200)
         request.setHeader(b"Content-Type", b"text/html; charset=utf-8")
         request.setHeader(b"Content-Length", b"%d" % (len(html),))
-        request.write(html.encode("utf8"))
+        request.write(html)
         finish_request(request)
 
     @staticmethod