Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit a3bad89

Browse files
authored
Add the ability to enable/disable registrations when in the OIDC flow (#14978)
Signed-off-by: Warren Bailey <warren@warrenbailey.net>
1 parent 9228ae6 commit a3bad89

File tree

6 files changed

+44
-3
lines changed

6 files changed

+44
-3
lines changed

changelog.d/14978.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add the ability to enable/disable registrations when in the OIDC flow.

docs/usage/configuration/config_documentation.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,6 +3100,11 @@ Options for each entry include:
31003100
match a pre-existing account instead of failing. This could be used if
31013101
switching from password logins to OIDC. Defaults to false.
31023102

3103+
* `enable_registration`: set to 'false' to disable automatic registration of new
3104+
users. This allows the OIDC SSO flow to be limited to sign in only, rather than
3105+
automatically registering users that have a valid SSO login but do not have
3106+
a pre-registered account. Defaults to true.
3107+
31033108
* `user_mapping_provider`: Configuration for how attributes returned from a OIDC
31043109
provider are mapped onto a matrix user. This setting has the following
31053110
sub-properties:
@@ -3216,6 +3221,7 @@ oidc_providers:
32163221
userinfo_endpoint: "https://accounts.example.com/userinfo"
32173222
jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
32183223
skip_verification: true
3224+
enable_registration: true
32193225
user_mapping_provider:
32203226
config:
32213227
subject_claim: "id"

synapse/config/oidc.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def oidc_enabled(self) -> bool:
136136
"type": "array",
137137
"items": SsoAttributeRequirement.JSON_SCHEMA,
138138
},
139+
"enable_registration": {"type": "boolean"},
139140
},
140141
}
141142

@@ -306,6 +307,7 @@ def _parse_oidc_config_dict(
306307
user_mapping_provider_class=user_mapping_provider_class,
307308
user_mapping_provider_config=user_mapping_provider_config,
308309
attribute_requirements=attribute_requirements,
310+
enable_registration=oidc_config.get("enable_registration", True),
309311
)
310312

311313

@@ -405,3 +407,6 @@ class OidcProviderConfig:
405407

406408
# required attributes to require in userinfo to allow login/registration
407409
attribute_requirements: List[SsoAttributeRequirement]
410+
411+
# Whether automatic registrations are enabled in the ODIC flow. Defaults to True
412+
enable_registration: bool

synapse/handlers/oidc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,7 @@ async def grandfather_existing_users() -> Optional[str]:
12391239
grandfather_existing_users,
12401240
extra_attributes,
12411241
auth_provider_session_id=sid,
1242+
registration_enabled=self._config.enable_registration,
12421243
)
12431244

12441245
def _remote_id_from_userinfo(self, userinfo: UserInfo) -> str:

synapse/handlers/sso.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ async def complete_sso_login_request(
383383
grandfather_existing_users: Callable[[], Awaitable[Optional[str]]],
384384
extra_login_attributes: Optional[JsonDict] = None,
385385
auth_provider_session_id: Optional[str] = None,
386+
registration_enabled: bool = True,
386387
) -> None:
387388
"""
388389
Given an SSO ID, retrieve the user ID for it and possibly register the user.
@@ -435,6 +436,10 @@ async def complete_sso_login_request(
435436
436437
auth_provider_session_id: An optional session ID from the IdP.
437438
439+
registration_enabled: An optional boolean to enable/disable automatic
440+
registrations of new users. If false and the user does not exist then the
441+
flow is aborted. Defaults to true.
442+
438443
Raises:
439444
MappingException if there was a problem mapping the response to a user.
440445
RedirectException: if the mapping provider needs to redirect the user
@@ -462,8 +467,16 @@ async def complete_sso_login_request(
462467
auth_provider_id, remote_user_id, user_id
463468
)
464469

465-
# Otherwise, generate a new user.
466-
if not user_id:
470+
if not user_id and not registration_enabled:
471+
logger.info(
472+
"User does not exist and registration are disabled for IdP '%s' and remote_user_id '%s'",
473+
auth_provider_id,
474+
remote_user_id,
475+
)
476+
raise MappingException(
477+
"User does not exist and registrations are disabled"
478+
)
479+
elif not user_id: # Otherwise, generate a new user.
467480
attributes = await self._call_attribute_mapper(sso_to_matrix_id_mapper)
468481

469482
next_step_url = self._get_url_for_next_new_user_step(

tests/handlers/test_oidc.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ def test_extra_attributes(self) -> None:
922922
auth_provider_session_id=None,
923923
)
924924

925-
@override_config({"oidc_config": DEFAULT_CONFIG})
925+
@override_config({"oidc_config": {**DEFAULT_CONFIG, "enable_registration": True}})
926926
def test_map_userinfo_to_user(self) -> None:
927927
"""Ensure that mapping the userinfo returned from a provider to an MXID works properly."""
928928
userinfo: dict = {
@@ -975,6 +975,21 @@ def test_map_userinfo_to_user(self) -> None:
975975
"Mapping provider does not support de-duplicating Matrix IDs",
976976
)
977977

978+
@override_config({"oidc_config": {**DEFAULT_CONFIG, "enable_registration": False}})
979+
def test_map_userinfo_to_user_does_not_register_new_user(self) -> None:
980+
"""Ensures new users are not registered if the enabled registration flag is disabled."""
981+
userinfo: dict = {
982+
"sub": "test_user",
983+
"username": "test_user",
984+
}
985+
request, _ = self.start_authorization(userinfo)
986+
self.get_success(self.handler.handle_oidc_callback(request))
987+
self.complete_sso_login.assert_not_called()
988+
self.assertRenderedError(
989+
"mapping_error",
990+
"User does not exist and registrations are disabled",
991+
)
992+
978993
@override_config({"oidc_config": {**DEFAULT_CONFIG, "allow_existing_users": True}})
979994
def test_map_userinfo_to_existing_user(self) -> None:
980995
"""Existing users can log in with OpenID Connect when allow_existing_users is True."""

0 commit comments

Comments
 (0)