summary refs log tree commit diff
diff options
context:
space:
mode:
author_ <x5f@fastmail.com>2025-05-15 04:31:52 -0700
committerGitHub <noreply@github.com>2025-05-15 11:31:52 +0000
commit44ae5362fd952dbb209f4b52ee9c96641163f032 (patch)
tree96633992edbd35c9574f688202f9cf5704433047
parentFix room_list_publication_rules docs for v1.126.0 (#18286) (diff)
downloadsynapse-44ae5362fd952dbb209f4b52ee9c96641163f032.tar.xz
Add option to allow registrations that begin with '_' (#18262)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
-rw-r--r--changelog.d/18262.feature1
-rw-r--r--docs/usage/configuration/config_documentation.md14
-rw-r--r--synapse/config/registration.py4
-rw-r--r--synapse/handlers/register.py5
-rw-r--r--tests/handlers/test_register.py23
5 files changed, 46 insertions, 1 deletions
diff --git a/changelog.d/18262.feature b/changelog.d/18262.feature
new file mode 100644

index 0000000000..c8249faa76 --- /dev/null +++ b/changelog.d/18262.feature
@@ -0,0 +1 @@ +Add option to allow registrations that begin with `_`. Contributed by `_` (@hex5f). diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md
index 2228c18a6c..e688bc5cd8 100644 --- a/docs/usage/configuration/config_documentation.md +++ b/docs/usage/configuration/config_documentation.md
@@ -2887,6 +2887,20 @@ Example configuration: inhibit_user_in_use_error: true ``` --- +### `allow_underscore_prefixed_registration` + +Whether users are allowed to register with a underscore-prefixed localpart. +By default, AppServices use prefixes like `_example` to namespace their +associated ghost users. If turned on, this may result in clashes or confusion. +Useful when provisioning users from an external identity provider. + +Defaults to false. + +Example configuration: +```yaml +allow_underscore_prefixed_registration: false +``` +--- ## User session management --- ### `session_lifetime` diff --git a/synapse/config/registration.py b/synapse/config/registration.py
index 3cf7031656..8adf21079e 100644 --- a/synapse/config/registration.py +++ b/synapse/config/registration.py
@@ -162,6 +162,10 @@ class RegistrationConfig(Config): "disable_msisdn_registration", False ) + self.allow_underscore_prefixed_localpart = config.get( + "allow_underscore_prefixed_localpart", False + ) + session_lifetime = config.get("session_lifetime") if session_lifetime is not None: session_lifetime = self.parse_duration(session_lifetime) diff --git a/synapse/handlers/register.py b/synapse/handlers/register.py
index ecfea175c7..3e86349981 100644 --- a/synapse/handlers/register.py +++ b/synapse/handlers/register.py
@@ -159,7 +159,10 @@ class RegistrationHandler: if not localpart: raise SynapseError(400, "User ID cannot be empty", Codes.INVALID_USERNAME) - if localpart[0] == "_": + if ( + localpart[0] == "_" + and not self.hs.config.registration.allow_underscore_prefixed_localpart + ): raise SynapseError( 400, "User ID may not begin with _", Codes.INVALID_USERNAME ) diff --git a/tests/handlers/test_register.py b/tests/handlers/test_register.py
index 92487692db..dda389c08b 100644 --- a/tests/handlers/test_register.py +++ b/tests/handlers/test_register.py
@@ -588,6 +588,29 @@ class RegistrationTestCase(unittest.HomeserverTestCase): d = self.store.is_support_user(user_id) self.assertFalse(self.get_success(d)) + def test_underscore_localpart_rejected_by_default(self) -> None: + for invalid_user_id in ("_", "_prefixed"): + with self.subTest(invalid_user_id=invalid_user_id): + self.get_failure( + self.handler.register_user(localpart=invalid_user_id), + SynapseError, + ) + + @override_config( + { + "allow_underscore_prefixed_localpart": True, + } + ) + def test_underscore_localpart_allowed_if_configured(self) -> None: + for valid_user_id in ("_", "_prefixed"): + with self.subTest(valid_user_id=valid_user_id): + user_id = self.get_success( + self.handler.register_user( + localpart=valid_user_id, + ), + ) + self.assertEqual(user_id, f"@{valid_user_id}:test") + def test_invalid_user_id(self) -> None: invalid_user_id = "^abcd" self.get_failure(