From 7bd41fa631dae3b58075f6d5d107b3784206f79c Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Wed, 24 Feb 2021 15:34:26 +0100 Subject: [PATCH 01/11] Add option to normalize user ID for JWT logins Signed-off-by: Botond Horvath --- docs/sample_config.yaml | 6 ++++++ synapse/config/jwt_config.py | 8 ++++++++ synapse/rest/client/v1/login.py | 6 +++++- tests/rest/client/v1/test_login.py | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 4dbef41b7e80..d332009ef170 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -2162,6 +2162,12 @@ sso: # #secret: "provided-by-your-issuer" + # Perform normalization of the user ID and encode unsupported characters. + # + # Optional, defaults to false. + # + #normalize_user_id: true + # The algorithm used to sign the JSON web token. # # Supported algorithms are listed at diff --git a/synapse/config/jwt_config.py b/synapse/config/jwt_config.py index f30330abb6d5..6db093a753ee 100644 --- a/synapse/config/jwt_config.py +++ b/synapse/config/jwt_config.py @@ -34,6 +34,7 @@ def read_config(self, config, **kwargs): # The issuer and audiences are optional, if provided, it is asserted # that the claims exist on the JWT. + self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) self.jwt_issuer = jwt_config.get("issuer") self.jwt_audiences = jwt_config.get("audiences") @@ -46,6 +47,7 @@ def read_config(self, config, **kwargs): else: self.jwt_enabled = False self.jwt_secret = None + self.jwt_normalize_user_id = False self.jwt_algorithm = None self.jwt_issuer = None self.jwt_audiences = None @@ -80,6 +82,12 @@ def generate_config_section(self, **kwargs): # #secret: "provided-by-your-issuer" + # Perform normalization of the user ID and encode unsupported characters. + # + # Optional, defaults to false. + # + #normalize_user_id: true + # The algorithm used to sign the JSON web token. # # Supported algorithms are listed at diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index 6e2fbedd99bf..219e272a65ec 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -29,7 +29,7 @@ from synapse.http.site import SynapseRequest from synapse.rest.client.v2_alpha._base import client_patterns from synapse.rest.well_known import WellKnownBuilder -from synapse.types import JsonDict, UserID +from synapse.types import JsonDict, UserID, map_username_to_mxid_localpart if TYPE_CHECKING: from synapse.server import HomeServer @@ -53,6 +53,7 @@ def __init__(self, hs: "HomeServer"): # JWT configuration variables. self.jwt_enabled = hs.config.jwt_enabled self.jwt_secret = hs.config.jwt_secret + self.jwt_normalize_user_id = hs.config.jwt_normalize_user_id self.jwt_algorithm = hs.config.jwt_algorithm self.jwt_issuer = hs.config.jwt_issuer self.jwt_audiences = hs.config.jwt_audiences @@ -319,6 +320,9 @@ async def _do_jwt_login(self, login_submission: JsonDict) -> Dict[str, str]: if user is None: raise LoginError(403, "Invalid JWT", errcode=Codes.FORBIDDEN) + if self.jwt_normalize_user_id: + user = map_username_to_mxid_localpart(user) + user_id = UserID(user, self.hs.hostname).to_string() result = await self._complete_login( user_id, login_submission, create_non_existent_users=True diff --git a/tests/rest/client/v1/test_login.py b/tests/rest/client/v1/test_login.py index fb29eaed6f08..ccaaab8b3a4d 100644 --- a/tests/rest/client/v1/test_login.py +++ b/tests/rest/client/v1/test_login.py @@ -982,6 +982,32 @@ def test_login_aud_no_config(self): channel.json_body["error"], "JWT validation failed: Invalid audience" ) + def test_login_no_normalize_id(self): + """Test mapping user ID to Matrix ID without normalization""" + channel = self.jwt_login({"sub": "#kermit"}) + self.assertEqual(channel.result["code"], b"400", channel.result) + self.assertEqual(channel.json_body["errcode"], "M_INVALID_USERNAME") + self.assertEqual( + channel.json_body["error"], + "User ID can only contain characters a-z, 0-9, or '=_-./'", + ) + + @override_config( + { + "jwt_config": { + "jwt_enabled": True, + "secret": jwt_secret, + "algorithm": jwt_algorithm, + "normalize_user_id": True, + } + } + ) + def test_login_normalize_id(self): + """Test mapping user ID to Matrix ID with normalization""" + channel = self.jwt_login({"sub": "#kermit"}) + self.assertEqual(channel.result["code"], b"200", channel.result) + self.assertEqual(channel.json_body["user_id"], "@=23kermit:test") + def test_login_no_token(self): params = {"type": "org.matrix.login.jwt"} channel = self.make_request(b"POST", LOGIN_URL, params) From 4ab669d207df4c046491564f9cdd5a9375e350df Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Wed, 24 Feb 2021 15:35:45 +0100 Subject: [PATCH 02/11] Add option to customize the claim used for the local part of the user ID for JWT logins Signed-off-by: Botond Horvath --- docs/sample_config.yaml | 6 ++++++ synapse/config/jwt_config.py | 8 ++++++++ synapse/rest/client/v1/login.py | 4 +++- tests/rest/client/v1/test_login.py | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index d332009ef170..07d41a75877d 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -2162,6 +2162,12 @@ sso: # #secret: "provided-by-your-issuer" + # Name of the claim containing a unique identifier for the user. + # + # Optional, defaults to `sub`. + # + #subject_claim: "sub" + # Perform normalization of the user ID and encode unsupported characters. # # Optional, defaults to false. diff --git a/synapse/config/jwt_config.py b/synapse/config/jwt_config.py index 6db093a753ee..fb4b993c9857 100644 --- a/synapse/config/jwt_config.py +++ b/synapse/config/jwt_config.py @@ -34,6 +34,7 @@ def read_config(self, config, **kwargs): # The issuer and audiences are optional, if provided, it is asserted # that the claims exist on the JWT. + self.jwt_subject_claim = jwt_config.get("subject_claim") self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) self.jwt_issuer = jwt_config.get("issuer") self.jwt_audiences = jwt_config.get("audiences") @@ -47,6 +48,7 @@ def read_config(self, config, **kwargs): else: self.jwt_enabled = False self.jwt_secret = None + self.jwt_subject_claim = None self.jwt_normalize_user_id = False self.jwt_algorithm = None self.jwt_issuer = None @@ -82,6 +84,12 @@ def generate_config_section(self, **kwargs): # #secret: "provided-by-your-issuer" + # Name of the claim containing a unique identifier for the user. + # + # Optional, defaults to `sub`. + # + #subject_claim: "sub" + # Perform normalization of the user ID and encode unsupported characters. # # Optional, defaults to false. diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index 219e272a65ec..fa7744e5b9a3 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -53,6 +53,7 @@ def __init__(self, hs: "HomeServer"): # JWT configuration variables. self.jwt_enabled = hs.config.jwt_enabled self.jwt_secret = hs.config.jwt_secret + self.jwt_subject_claim = hs.config.jwt_subject_claim self.jwt_normalize_user_id = hs.config.jwt_normalize_user_id self.jwt_algorithm = hs.config.jwt_algorithm self.jwt_issuer = hs.config.jwt_issuer @@ -316,7 +317,8 @@ async def _do_jwt_login(self, login_submission: JsonDict) -> Dict[str, str]: errcode=Codes.FORBIDDEN, ) - user = payload.get("sub", None) + subject_claim = self.jwt_subject_claim or "sub" + user = payload.get(subject_claim, None) if user is None: raise LoginError(403, "Invalid JWT", errcode=Codes.FORBIDDEN) diff --git a/tests/rest/client/v1/test_login.py b/tests/rest/client/v1/test_login.py index ccaaab8b3a4d..1b9d67e33298 100644 --- a/tests/rest/client/v1/test_login.py +++ b/tests/rest/client/v1/test_login.py @@ -982,6 +982,28 @@ def test_login_aud_no_config(self): channel.json_body["error"], "JWT validation failed: Invalid audience" ) + def test_login_default_sub(self): + """Test reading user ID from the default subject claim.""" + channel = self.jwt_login({"sub": "kermit"}) + self.assertEqual(channel.result["code"], b"200", channel.result) + self.assertEqual(channel.json_body["user_id"], "@kermit:test") + + @override_config( + { + "jwt_config": { + "jwt_enabled": True, + "secret": jwt_secret, + "algorithm": jwt_algorithm, + "subject_claim": "username", + } + } + ) + def test_login_custom_sub(self): + """Test reading user ID from a custom subject claim.""" + channel = self.jwt_login({"username": "frog"}) + self.assertEqual(channel.result["code"], b"200", channel.result) + self.assertEqual(channel.json_body["user_id"], "@frog:test") + def test_login_no_normalize_id(self): """Test mapping user ID to Matrix ID without normalization""" channel = self.jwt_login({"sub": "#kermit"}) From da2bfb17587da2efac4d3dd8d7431487898b6aa3 Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Wed, 24 Feb 2021 15:36:10 +0100 Subject: [PATCH 03/11] Add option to retrieve RSA signing keys from a JWKS endpoint for JWT logins Signed-off-by: Botond Horvath --- docs/sample_config.yaml | 10 +++++++++- synapse/config/jwt_config.py | 14 ++++++++++++-- synapse/rest/client/v1/login.py | 11 ++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 07d41a75877d..5357d8a9979f 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -2158,10 +2158,18 @@ sso: # This is either the private shared secret or the public key used to # decode the contents of the JSON web token. # - # Required if 'enabled' is true. + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. # #secret: "provided-by-your-issuer" + # URI where to fetch the JWKS containing the public keys that + # should be used to verify the signature of the JSON web token. + # Only used if 'secret' is not provided. + # + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. + # + #jwks_uri: "provided-by-your-issuer" + # Name of the claim containing a unique identifier for the user. # # Optional, defaults to `sub`. diff --git a/synapse/config/jwt_config.py b/synapse/config/jwt_config.py index fb4b993c9857..9f4a9dc9b352 100644 --- a/synapse/config/jwt_config.py +++ b/synapse/config/jwt_config.py @@ -29,11 +29,12 @@ def read_config(self, config, **kwargs): jwt_config = config.get("jwt_config", None) if jwt_config: self.jwt_enabled = jwt_config.get("enabled", False) - self.jwt_secret = jwt_config["secret"] self.jwt_algorithm = jwt_config["algorithm"] # The issuer and audiences are optional, if provided, it is asserted # that the claims exist on the JWT. + self.jwt_secret = jwt_config.get("secret") + self.jwt_jwks_uri = jwt_config.get("jwks_uri") self.jwt_subject_claim = jwt_config.get("subject_claim") self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) self.jwt_issuer = jwt_config.get("issuer") @@ -48,6 +49,7 @@ def read_config(self, config, **kwargs): else: self.jwt_enabled = False self.jwt_secret = None + self.jwt_jwks_uri = None self.jwt_subject_claim = None self.jwt_normalize_user_id = False self.jwt_algorithm = None @@ -80,10 +82,18 @@ def generate_config_section(self, **kwargs): # This is either the private shared secret or the public key used to # decode the contents of the JSON web token. # - # Required if 'enabled' is true. + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. # #secret: "provided-by-your-issuer" + # URI where to fetch the JWKS containing the public keys that + # should be used to verify the signature of the JSON web token. + # Only used if 'secret' is not provided. + # + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. + # + #jwks_uri: "provided-by-your-issuer" + # Name of the claim containing a unique identifier for the user. # # Optional, defaults to `sub`. diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index fa7744e5b9a3..1cd60451f817 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -53,6 +53,7 @@ def __init__(self, hs: "HomeServer"): # JWT configuration variables. self.jwt_enabled = hs.config.jwt_enabled self.jwt_secret = hs.config.jwt_secret + self.jwt_jwks_uri = hs.config.jwt_jwks_uri self.jwt_subject_claim = hs.config.jwt_subject_claim self.jwt_normalize_user_id = hs.config.jwt_normalize_user_id self.jwt_algorithm = hs.config.jwt_algorithm @@ -300,11 +301,19 @@ async def _do_jwt_login(self, login_submission: JsonDict) -> Dict[str, str]: ) import jwt + from jwt import PyJWKClient + + key = self.jwt_secret + + if not key and self.jwt_jwks_uri: + jwks_client = PyJWKClient(self.jwt_jwks_uri) + signing_key = jwks_client.get_signing_key_from_jwt(token) + key = signing_key.key try: payload = jwt.decode( token, - self.jwt_secret, + key, algorithms=[self.jwt_algorithm], issuer=self.jwt_issuer, audience=self.jwt_audiences, From d8920fdc3490ba493e93d04eef31a5fd0f3148ee Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Thu, 25 Feb 2021 01:26:11 +0100 Subject: [PATCH 04/11] Add changelog entry Signed-off-by: Botond Horvath --- changelog.d/9493.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/9493.feature diff --git a/changelog.d/9493.feature b/changelog.d/9493.feature new file mode 100644 index 000000000000..fd467ddf0611 --- /dev/null +++ b/changelog.d/9493.feature @@ -0,0 +1 @@ +Update JWT login type to support JSON Web Key Sets (JWKS), custom sub claim, and option to encode unsupported characters in user ID. From 3d43b533191314fee91bc71c42d071d0ef1db7c5 Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Tue, 9 Mar 2021 12:50:40 +0100 Subject: [PATCH 05/11] Update docs/jwt.md --- docs/jwt.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/jwt.md b/docs/jwt.md index 5be9fd26e331..32f58cc0cbbf 100644 --- a/docs/jwt.md +++ b/docs/jwt.md @@ -22,8 +22,9 @@ will be removed in a future version of Synapse. The `token` field should include the JSON web token with the following claims: -* The `sub` (subject) claim is required and should encode the local part of the - user ID. +* A claim that encodes the local part of the user ID is required. By default, + the `sub` (subject) claim is used, or a custom claim can be set in the + configuration file. * The expiration time (`exp`), not before time (`nbf`), and issued at (`iat`) claims are optional, but validated if present. * The issuer (`iss`) claim is optional, but required and validated if configured. From a77ebc96a4525c76303977b9fd4041e6dcb35cff Mon Sep 17 00:00:00 2001 From: P Date: Thu, 17 Jun 2021 17:41:21 -0400 Subject: [PATCH 06/11] Rename jwt_config.py as done in 683d6f --- synapse/config/jwt.py | 32 ++++++++- synapse/config/jwt_config.py | 135 ----------------------------------- 2 files changed, 29 insertions(+), 138 deletions(-) delete mode 100644 synapse/config/jwt_config.py diff --git a/synapse/config/jwt.py b/synapse/config/jwt.py index 9e07e7300814..911131cdfc46 100644 --- a/synapse/config/jwt.py +++ b/synapse/config/jwt.py @@ -28,11 +28,14 @@ def read_config(self, config, **kwargs): jwt_config = config.get("jwt_config", None) if jwt_config: self.jwt_enabled = jwt_config.get("enabled", False) - self.jwt_secret = jwt_config["secret"] self.jwt_algorithm = jwt_config["algorithm"] # The issuer and audiences are optional, if provided, it is asserted # that the claims exist on the JWT. + self.jwt_secret = jwt_config.get("secret") + self.jwt_jwks_uri = jwt_config.get("jwks_uri") + self.jwt_subject_claim = jwt_config.get("subject_claim") + self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) self.jwt_issuer = jwt_config.get("issuer") self.jwt_audiences = jwt_config.get("audiences") @@ -45,9 +48,12 @@ def read_config(self, config, **kwargs): else: self.jwt_enabled = False self.jwt_secret = None - self.jwt_algorithm = None self.jwt_issuer = None self.jwt_audiences = None + self.jwt_jwks_uri = None + self.jwt_subject_claim = None + self.jwt_normalize_user_id = False + self.jwt_algorithm = None def generate_config_section(self, **kwargs): return """\ @@ -75,10 +81,30 @@ def generate_config_section(self, **kwargs): # This is either the private shared secret or the public key used to # decode the contents of the JSON web token. # - # Required if 'enabled' is true. + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. # #secret: "provided-by-your-issuer" + # URI where to fetch the JWKS containing the public keys that + # should be used to verify the signature of the JSON web token. + # Only used if 'secret' is not provided. + # + # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. + # + #jwks_uri: "provided-by-your-issuer" + + # Name of the claim containing a unique identifier for the user. + # + # Optional, defaults to `sub`. + # + #subject_claim: "sub" + + # Perform normalization of the user ID and encode unsupported characters. + # + # Optional, defaults to false. + # + #normalize_user_id: true + # The algorithm used to sign the JSON web token. # # Supported algorithms are listed at diff --git a/synapse/config/jwt_config.py b/synapse/config/jwt_config.py deleted file mode 100644 index 9f4a9dc9b352..000000000000 --- a/synapse/config/jwt_config.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2015 Niklas Riekenbrauck -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from ._base import Config, ConfigError - -MISSING_JWT = """Missing jwt library. This is required for jwt login. - - Install by running: - pip install pyjwt - """ - - -class JWTConfig(Config): - section = "jwt" - - def read_config(self, config, **kwargs): - jwt_config = config.get("jwt_config", None) - if jwt_config: - self.jwt_enabled = jwt_config.get("enabled", False) - self.jwt_algorithm = jwt_config["algorithm"] - - # The issuer and audiences are optional, if provided, it is asserted - # that the claims exist on the JWT. - self.jwt_secret = jwt_config.get("secret") - self.jwt_jwks_uri = jwt_config.get("jwks_uri") - self.jwt_subject_claim = jwt_config.get("subject_claim") - self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) - self.jwt_issuer = jwt_config.get("issuer") - self.jwt_audiences = jwt_config.get("audiences") - - try: - import jwt - - jwt # To stop unused lint. - except ImportError: - raise ConfigError(MISSING_JWT) - else: - self.jwt_enabled = False - self.jwt_secret = None - self.jwt_jwks_uri = None - self.jwt_subject_claim = None - self.jwt_normalize_user_id = False - self.jwt_algorithm = None - self.jwt_issuer = None - self.jwt_audiences = None - - def generate_config_section(self, **kwargs): - return """\ - # JSON web token integration. The following settings can be used to make - # Synapse JSON web tokens for authentication, instead of its internal - # password database. - # - # Each JSON Web Token needs to contain a "sub" (subject) claim, which is - # used as the localpart of the mxid. - # - # Additionally, the expiration time ("exp"), not before time ("nbf"), - # and issued at ("iat") claims are validated if present. - # - # Note that this is a non-standard login type and client support is - # expected to be non-existent. - # - # See https://github.com/matrix-org/synapse/blob/master/docs/jwt.md. - # - #jwt_config: - # Uncomment the following to enable authorization using JSON web - # tokens. Defaults to false. - # - #enabled: true - - # This is either the private shared secret or the public key used to - # decode the contents of the JSON web token. - # - # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. - # - #secret: "provided-by-your-issuer" - - # URI where to fetch the JWKS containing the public keys that - # should be used to verify the signature of the JSON web token. - # Only used if 'secret' is not provided. - # - # Either 'secret' or 'jwks_uri' is required if 'enabled' is true. - # - #jwks_uri: "provided-by-your-issuer" - - # Name of the claim containing a unique identifier for the user. - # - # Optional, defaults to `sub`. - # - #subject_claim: "sub" - - # Perform normalization of the user ID and encode unsupported characters. - # - # Optional, defaults to false. - # - #normalize_user_id: true - - # The algorithm used to sign the JSON web token. - # - # Supported algorithms are listed at - # https://pyjwt.readthedocs.io/en/latest/algorithms.html - # - # Required if 'enabled' is true. - # - #algorithm: "provided-by-your-issuer" - - # The issuer to validate the "iss" claim against. - # - # Optional, if provided the "iss" claim will be required and - # validated for all JSON web tokens. - # - #issuer: "provided-by-your-issuer" - - # A list of audiences to validate the "aud" claim against. - # - # Optional, if provided the "aud" claim will be required and - # validated for all JSON web tokens. - # - # Note that if the "aud" claim is included in a JSON web token then - # validation will fail without configuring audiences. - # - #audiences: - # - "provided-by-your-issuer" - """ From 66f12d0ba8845d3d22babe98d152fde5ab6e8ca2 Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Sat, 19 Jun 2021 14:49:55 +0200 Subject: [PATCH 07/11] Check if either a secret or a jwks uri is provided in jwt_config --- synapse/config/jwt.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/synapse/config/jwt.py b/synapse/config/jwt.py index 911131cdfc46..854da6febc35 100644 --- a/synapse/config/jwt.py +++ b/synapse/config/jwt.py @@ -14,6 +14,7 @@ from ._base import Config, ConfigError +MISSING_SECRET = "Either 'secret' or 'jwks_uri' is required in jwt_config." MISSING_JWT = """Missing jwt library. This is required for jwt login. Install by running: @@ -39,6 +40,9 @@ def read_config(self, config, **kwargs): self.jwt_issuer = jwt_config.get("issuer") self.jwt_audiences = jwt_config.get("audiences") + if not self.jwt_secret and not self.jwt_jwks_uri: + raise ConfigError(MISSING_SECRET) + try: import jwt From e706eb4c07231583299b8fbb0a62624181df9011 Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Sat, 19 Jun 2021 14:52:05 +0200 Subject: [PATCH 08/11] Default JWT subject claim field to "sub" --- synapse/config/jwt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/config/jwt.py b/synapse/config/jwt.py index 854da6febc35..31c13cc86864 100644 --- a/synapse/config/jwt.py +++ b/synapse/config/jwt.py @@ -35,7 +35,7 @@ def read_config(self, config, **kwargs): # that the claims exist on the JWT. self.jwt_secret = jwt_config.get("secret") self.jwt_jwks_uri = jwt_config.get("jwks_uri") - self.jwt_subject_claim = jwt_config.get("subject_claim") + self.jwt_subject_claim = jwt_config.get("subject_claim", "sub") self.jwt_normalize_user_id = jwt_config.get("normalize_user_id", False) self.jwt_issuer = jwt_config.get("issuer") self.jwt_audiences = jwt_config.get("audiences") From 987431aeebd4db503ebd2b083a12f3b72454b25c Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Sat, 19 Jun 2021 14:52:45 +0200 Subject: [PATCH 09/11] Increase minimum version of PyJWT library to 2.1.0 --- synapse/python_dependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/python_dependencies.py b/synapse/python_dependencies.py index 271c17c22615..e59151566b34 100644 --- a/synapse/python_dependencies.py +++ b/synapse/python_dependencies.py @@ -107,7 +107,7 @@ "url_preview": ["lxml>=3.5.0"], "sentry": ["sentry-sdk>=0.7.2"], "opentracing": ["jaeger-client>=4.0.0", "opentracing>=2.2.0"], - "jwt": ["pyjwt>=1.6.4"], + "jwt": ["pyjwt>=2.1.0"], # hiredis is not a *strict* dependency, but it makes things much faster. # (if it is not installed, we fall back to slow code.) "redis": ["txredisapi>=1.4.7", "hiredis"], From 93acad23c51f6872fe67eedd1ac0b5e4b09861bf Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Tue, 29 Jun 2021 21:39:14 +0200 Subject: [PATCH 10/11] Change spelling in sample config Co-authored-by: Patrick Cloke --- synapse/config/jwt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/config/jwt.py b/synapse/config/jwt.py index 31c13cc86864..99c9a5c10eb4 100644 --- a/synapse/config/jwt.py +++ b/synapse/config/jwt.py @@ -103,7 +103,7 @@ def generate_config_section(self, **kwargs): # #subject_claim: "sub" - # Perform normalization of the user ID and encode unsupported characters. + # Perform normalisation of the user ID and encode unsupported characters. # # Optional, defaults to false. # From c8c4a110d3fb3e2d98d2fad27d8c2c973ff5b6f1 Mon Sep 17 00:00:00 2001 From: Botond Horvath Date: Tue, 29 Jun 2021 22:46:48 +0200 Subject: [PATCH 11/11] Update docs/sample_config.yaml --- docs/sample_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 4cdee83923b6..1cfa848d09dd 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -2165,7 +2165,7 @@ sso: # #subject_claim: "sub" - # Perform normalization of the user ID and encode unsupported characters. + # Perform normalisation of the user ID and encode unsupported characters. # # Optional, defaults to false. #