Skip to content
Snippets Groups Projects
Unverified Commit fe69e7f6 authored by Aurélien Grimpard's avatar Aurélien Grimpard Committed by GitHub
Browse files

Handle "registration_enabled" parameter for CAS (#16262)

Similar to OIDC, CAS providers can now disable registration such
that only existing users are able to login via SSO.
parent 32fb2641
No related branches found
No related tags found
No related merge requests found
Add the ability to enable/disable registrations when in the CAS flow. Contributed by Aurélien Grimpard.
...@@ -3430,6 +3430,12 @@ Has the following sub-options: ...@@ -3430,6 +3430,12 @@ Has the following sub-options:
and the values must match the given value. Alternately if the given value and the values must match the given value. Alternately if the given value
is `None` then any value is allowed (the attribute just must exist). is `None` then any value is allowed (the attribute just must exist).
All of the listed attributes must match for the login to be permitted. All of the listed attributes must match for the login to be permitted.
* `enable_registration`: set to 'false' to disable automatic registration of new
users. This allows the CAS SSO flow to be limited to sign in only, rather than
automatically registering users that have a valid SSO login but do not have
a pre-registered account. Defaults to true.
*Added in Synapse 1.93.0.*
Example configuration: Example configuration:
```yaml ```yaml
...@@ -3441,6 +3447,7 @@ cas_config: ...@@ -3441,6 +3447,7 @@ cas_config:
required_attributes: required_attributes:
userGroup: "staff" userGroup: "staff"
department: None department: None
enable_registration: true
``` ```
--- ---
### `sso` ### `sso`
......
...@@ -57,6 +57,8 @@ class CasConfig(Config): ...@@ -57,6 +57,8 @@ class CasConfig(Config):
required_attributes required_attributes
) )
self.cas_enable_registration = cas_config.get("enable_registration", True)
self.idp_name = cas_config.get("idp_name", "CAS") self.idp_name = cas_config.get("idp_name", "CAS")
self.idp_icon = cas_config.get("idp_icon") self.idp_icon = cas_config.get("idp_icon")
self.idp_brand = cas_config.get("idp_brand") self.idp_brand = cas_config.get("idp_brand")
...@@ -67,6 +69,7 @@ class CasConfig(Config): ...@@ -67,6 +69,7 @@ class CasConfig(Config):
self.cas_protocol_version = None self.cas_protocol_version = None
self.cas_displayname_attribute = None self.cas_displayname_attribute = None
self.cas_required_attributes = [] self.cas_required_attributes = []
self.cas_enable_registration = False
# CAS uses a legacy required attributes mapping, not the one provided by # CAS uses a legacy required attributes mapping, not the one provided by
......
...@@ -70,6 +70,7 @@ class CasHandler: ...@@ -70,6 +70,7 @@ class CasHandler:
self._cas_protocol_version = hs.config.cas.cas_protocol_version self._cas_protocol_version = hs.config.cas.cas_protocol_version
self._cas_displayname_attribute = hs.config.cas.cas_displayname_attribute self._cas_displayname_attribute = hs.config.cas.cas_displayname_attribute
self._cas_required_attributes = hs.config.cas.cas_required_attributes self._cas_required_attributes = hs.config.cas.cas_required_attributes
self._cas_enable_registration = hs.config.cas.cas_enable_registration
self._http_client = hs.get_proxied_http_client() self._http_client = hs.get_proxied_http_client()
...@@ -395,4 +396,5 @@ class CasHandler: ...@@ -395,4 +396,5 @@ class CasHandler:
client_redirect_url, client_redirect_url,
cas_response_to_user_attributes, cas_response_to_user_attributes,
grandfather_existing_users, grandfather_existing_users,
registration_enabled=self._cas_enable_registration,
) )
...@@ -197,6 +197,23 @@ class CasHandlerTestCase(HomeserverTestCase): ...@@ -197,6 +197,23 @@ class CasHandlerTestCase(HomeserverTestCase):
auth_provider_session_id=None, auth_provider_session_id=None,
) )
@override_config({"cas_config": {"enable_registration": False}})
def test_map_cas_user_does_not_register_new_user(self) -> None:
"""Ensures new users are not registered if the enabled registration flag is disabled."""
# stub out the auth handler
auth_handler = self.hs.get_auth_handler()
auth_handler.complete_sso_login = AsyncMock() # type: ignore[method-assign]
cas_response = CasResponse("test_user", {})
request = _mock_request()
self.get_success(
self.handler._handle_cas_response(request, cas_response, "redirect_uri", "")
)
# check that the auth handler was not called as expected
auth_handler.complete_sso_login.assert_not_called()
def _mock_request() -> Mock: def _mock_request() -> Mock:
"""Returns a mock which will stand in as a SynapseRequest""" """Returns a mock which will stand in as a SynapseRequest"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment