summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorreivilibre <oliverw@matrix.org>2021-12-03 16:42:44 +0000
committerGitHub <noreply@github.com>2021-12-03 16:42:44 +0000
commit637df95de63196033a6da4a6e286e1d58ea517b6 (patch)
treeb60658f55d52fadf145feeb7999c5c89c873650f /synapse
parentAdd type hints to `synapse/tests/rest/admin` (#11501) (diff)
downloadsynapse-637df95de63196033a6da4a6e286e1d58ea517b6.tar.xz
Support configuring the lifetime of non-refreshable access tokens separately to refreshable access tokens. (#11445)
Diffstat (limited to 'synapse')
-rw-r--r--synapse/config/registration.py49
-rw-r--r--synapse/handlers/register.py20
2 files changed, 66 insertions, 3 deletions
diff --git a/synapse/config/registration.py b/synapse/config/registration.py
index 47853199f4..68a4985398 100644
--- a/synapse/config/registration.py
+++ b/synapse/config/registration.py
@@ -130,11 +130,60 @@ class RegistrationConfig(Config):
             int
         ] = refreshable_access_token_lifetime
 
+        if (
+            self.session_lifetime is not None
+            and "refreshable_access_token_lifetime" in config
+        ):
+            if self.session_lifetime < self.refreshable_access_token_lifetime:
+                raise ConfigError(
+                    "Both `session_lifetime` and `refreshable_access_token_lifetime` "
+                    "configuration options have been set, but `refreshable_access_token_lifetime` "
+                    " exceeds `session_lifetime`!"
+                )
+
+        # The `nonrefreshable_access_token_lifetime` applies for tokens that can NOT be
+        # refreshed using a refresh token.
+        # If it is None, then these tokens last for the entire length of the session,
+        # which is infinite by default.
+        # The intention behind this configuration option is to help with requiring
+        # all clients to use refresh tokens, if the homeserver administrator requires.
+        nonrefreshable_access_token_lifetime = config.get(
+            "nonrefreshable_access_token_lifetime",
+            None,
+        )
+        if nonrefreshable_access_token_lifetime is not None:
+            nonrefreshable_access_token_lifetime = self.parse_duration(
+                nonrefreshable_access_token_lifetime
+            )
+        self.nonrefreshable_access_token_lifetime = nonrefreshable_access_token_lifetime
+
+        if (
+            self.session_lifetime is not None
+            and self.nonrefreshable_access_token_lifetime is not None
+        ):
+            if self.session_lifetime < self.nonrefreshable_access_token_lifetime:
+                raise ConfigError(
+                    "Both `session_lifetime` and `nonrefreshable_access_token_lifetime` "
+                    "configuration options have been set, but `nonrefreshable_access_token_lifetime` "
+                    " exceeds `session_lifetime`!"
+                )
+
         refresh_token_lifetime = config.get("refresh_token_lifetime")
         if refresh_token_lifetime is not None:
             refresh_token_lifetime = self.parse_duration(refresh_token_lifetime)
         self.refresh_token_lifetime: Optional[int] = refresh_token_lifetime
 
+        if (
+            self.session_lifetime is not None
+            and self.refresh_token_lifetime is not None
+        ):
+            if self.session_lifetime < self.refresh_token_lifetime:
+                raise ConfigError(
+                    "Both `session_lifetime` and `refresh_token_lifetime` "
+                    "configuration options have been set, but `refresh_token_lifetime` "
+                    " exceeds `session_lifetime`!"
+                )
+
         # The fallback template used for authenticating using a registration token
         self.registration_token_template = self.read_template("registration_token.html")
 
diff --git a/synapse/handlers/register.py b/synapse/handlers/register.py
index 24ca11b924..b14ddd8267 100644
--- a/synapse/handlers/register.py
+++ b/synapse/handlers/register.py
@@ -1,4 +1,5 @@
 # Copyright 2014 - 2016 OpenMarket Ltd
+# Copyright 2021 The Matrix.org Foundation C.I.C.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -116,6 +117,9 @@ class RegistrationHandler:
             self.pusher_pool = hs.get_pusherpool()
 
         self.session_lifetime = hs.config.registration.session_lifetime
+        self.nonrefreshable_access_token_lifetime = (
+            hs.config.registration.nonrefreshable_access_token_lifetime
+        )
         self.refreshable_access_token_lifetime = (
             hs.config.registration.refreshable_access_token_lifetime
         )
@@ -794,13 +798,25 @@ class RegistrationHandler:
         class and RegisterDeviceReplicationServlet.
         """
         assert not self.hs.config.worker.worker_app
+        now_ms = self.clock.time_msec()
         access_token_expiry = None
         if self.session_lifetime is not None:
             if is_guest:
                 raise Exception(
                     "session_lifetime is not currently implemented for guest access"
                 )
-            access_token_expiry = self.clock.time_msec() + self.session_lifetime
+            access_token_expiry = now_ms + self.session_lifetime
+
+        if self.nonrefreshable_access_token_lifetime is not None:
+            if access_token_expiry is not None:
+                # Don't allow the non-refreshable access token to outlive the
+                # session.
+                access_token_expiry = min(
+                    now_ms + self.nonrefreshable_access_token_lifetime,
+                    access_token_expiry,
+                )
+            else:
+                access_token_expiry = now_ms + self.nonrefreshable_access_token_lifetime
 
         refresh_token = None
         refresh_token_id = None
@@ -818,8 +834,6 @@ class RegistrationHandler:
                 # that this value is set before setting this flag).
                 assert self.refreshable_access_token_lifetime is not None
 
-                now_ms = self.clock.time_msec()
-
                 # Set the expiry time of the refreshable access token
                 access_token_expiry = now_ms + self.refreshable_access_token_lifetime