summary refs log tree commit diff
path: root/packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch')
-rw-r--r--packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch175
1 files changed, 175 insertions, 0 deletions
diff --git a/packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch b/packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch
new file mode 100644

index 0000000..9aba9cb --- /dev/null +++ b/packages/overlays/matrix-synapse/patches/0018-Allow-only-requiring-a-field-be-present-in-an-SSO-re.patch
@@ -0,0 +1,175 @@ +From 1f4ae2f9eb94808f651b683b4650092015ec39e1 Mon Sep 17 00:00:00 2001 +From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> +Date: Mon, 19 May 2025 17:50:02 +0100 +Subject: [PATCH 18/34] Allow only requiring a field be present in an SSO + response, rather than specifying a required value (#18454) + +--- + changelog.d/18454.misc | 1 + + .../configuration/config_documentation.md | 10 ++- + synapse/config/sso.py | 7 +- + tests/handlers/test_oidc.py | 77 ++++++++++++++++++- + 4 files changed, 86 insertions(+), 9 deletions(-) + create mode 100644 changelog.d/18454.misc + +diff --git a/changelog.d/18454.misc b/changelog.d/18454.misc +new file mode 100644 +index 0000000000..892fbd1d94 +--- /dev/null ++++ b/changelog.d/18454.misc +@@ -0,0 +1 @@ ++Allow checking only for the existence of a field in an SSO provider's response, rather than requiring the value(s) to check. +\ No newline at end of file +diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md +index e688bc5cd8..3927b9ca14 100644 +--- a/docs/usage/configuration/config_documentation.md ++++ b/docs/usage/configuration/config_documentation.md +@@ -3782,17 +3782,23 @@ match particular values in the OIDC userinfo. The requirements can be listed und + ```yaml + attribute_requirements: + - attribute: family_name +- value: "Stephensson" ++ one_of: ["Stephensson", "Smith"] + - attribute: groups + value: "admin" ++ # If `value` or `one_of` are not specified, the attribute only needs ++ # to exist, regardless of value. ++ - attribute: picture + ``` ++ ++`attribute` is a required field, while `value` and `one_of` are optional. ++ + All of the listed attributes must match for the login to be permitted. Additional attributes can be added to + userinfo by expanding the `scopes` section of the OIDC config to retrieve + additional information from the OIDC provider. + + If the OIDC claim is a list, then the attribute must match any value in the list. + Otherwise, it must exactly match the value of the claim. Using the example +-above, the `family_name` claim MUST be "Stephensson", but the `groups` ++above, the `family_name` claim MUST be either "Stephensson" or "Smith", but the `groups` + claim MUST contain "admin". + + Example configuration: +diff --git a/synapse/config/sso.py b/synapse/config/sso.py +index 97b85e47ea..cf27a7ee13 100644 +--- a/synapse/config/sso.py ++++ b/synapse/config/sso.py +@@ -43,8 +43,7 @@ class SsoAttributeRequirement: + """Object describing a single requirement for SSO attributes.""" + + attribute: str +- # If neither value nor one_of is given, the attribute must simply exist. This is +- # only true for CAS configs which use a different JSON schema than the one below. ++ # If neither `value` nor `one_of` is given, the attribute must simply exist. + value: Optional[str] = None + one_of: Optional[List[str]] = None + +@@ -56,10 +55,6 @@ class SsoAttributeRequirement: + "one_of": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["attribute"], +- "oneOf": [ +- {"required": ["value"]}, +- {"required": ["one_of"]}, +- ], + } + + +diff --git a/tests/handlers/test_oidc.py b/tests/handlers/test_oidc.py +index e5f31d57ca..ff8e3c5cb6 100644 +--- a/tests/handlers/test_oidc.py ++++ b/tests/handlers/test_oidc.py +@@ -1453,7 +1453,7 @@ class OidcHandlerTestCase(HomeserverTestCase): + } + } + ) +- def test_attribute_requirements_one_of(self) -> None: ++ def test_attribute_requirements_one_of_succeeds(self) -> None: + """Test that auth succeeds if userinfo attribute has multiple values and CONTAINS required value""" + # userinfo with "test": ["bar"] attribute should succeed. + userinfo = { +@@ -1475,6 +1475,81 @@ class OidcHandlerTestCase(HomeserverTestCase): + auth_provider_session_id=None, + ) + ++ @override_config( ++ { ++ "oidc_config": { ++ **DEFAULT_CONFIG, ++ "attribute_requirements": [ ++ {"attribute": "test", "one_of": ["foo", "bar"]} ++ ], ++ } ++ } ++ ) ++ def test_attribute_requirements_one_of_fails(self) -> None: ++ """Test that auth fails if userinfo attribute has multiple values yet ++ DOES NOT CONTAIN a required value ++ """ ++ # userinfo with "test": ["something else"] attribute should fail. ++ userinfo = { ++ "sub": "tester", ++ "username": "tester", ++ "test": ["something else"], ++ } ++ request, _ = self.start_authorization(userinfo) ++ self.get_success(self.handler.handle_oidc_callback(request)) ++ self.complete_sso_login.assert_not_called() ++ ++ @override_config( ++ { ++ "oidc_config": { ++ **DEFAULT_CONFIG, ++ "attribute_requirements": [{"attribute": "test"}], ++ } ++ } ++ ) ++ def test_attribute_requirements_does_not_exist(self) -> None: ++ """OIDC login fails if the required attribute does not exist in the OIDC userinfo response.""" ++ # userinfo lacking "test" attribute should fail. ++ userinfo = { ++ "sub": "tester", ++ "username": "tester", ++ } ++ request, _ = self.start_authorization(userinfo) ++ self.get_success(self.handler.handle_oidc_callback(request)) ++ self.complete_sso_login.assert_not_called() ++ ++ @override_config( ++ { ++ "oidc_config": { ++ **DEFAULT_CONFIG, ++ "attribute_requirements": [{"attribute": "test"}], ++ } ++ } ++ ) ++ def test_attribute_requirements_exist(self) -> None: ++ """OIDC login succeeds if the required attribute exist (regardless of value) ++ in the OIDC userinfo response. ++ """ ++ # userinfo with "test" attribute and random value should succeed. ++ userinfo = { ++ "sub": "tester", ++ "username": "tester", ++ "test": random_string(5), # value does not matter ++ } ++ request, _ = self.start_authorization(userinfo) ++ self.get_success(self.handler.handle_oidc_callback(request)) ++ ++ # check that the auth handler got called as expected ++ self.complete_sso_login.assert_called_once_with( ++ "@tester:test", ++ self.provider.idp_id, ++ request, ++ ANY, ++ None, ++ new_user=True, ++ auth_provider_session_id=None, ++ ) ++ + @override_config( + { + "oidc_config": { +-- +2.49.0 +