Skip to content

Commit

Permalink
Make sure we advertise registration as disabled when MSC3861 is enabl…
Browse files Browse the repository at this point in the history
…ed (#17661)

This has been a problem with Element Web, as it will proble /register
with an empty body, which gave this error:

```
curl -d '{}' -HContent-Type:application/json /_matrix/client/v3/register

{"errcode": "M_UNKNOWN",
 "error": "Invalid username"}
```

And Element Web would choke on it. This changes that so we reply
instead:

```
{"errcode": "M_FORBIDDEN",
 "error": "Registration has been disabled. Only m.login.application_service registrations are allowed."}
```

Also adds a test for this.

See element-hq/element-web#27993

---------

Co-authored-by: Andrew Morgan <andrew@amorgan.xyz>
  • Loading branch information
sandhose and anoadragon453 authored Feb 18, 2025
1 parent ecad88f commit f7bc63e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog.d/17661.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make sure we advertise registration as disabled when MSC3861 is enabled.
12 changes: 8 additions & 4 deletions synapse/rest/client/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,14 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:

await self.ratelimiter.ratelimit(None, client_addr, update=False)

# Allow only ASes to use this API.
if body.get("type") != APP_SERVICE_REGISTRATION_TYPE:
raise SynapseError(
403,
"Registration has been disabled. Only m.login.application_service registrations are allowed.",
errcode=Codes.FORBIDDEN,
)

kind = parse_string(request, "kind", default="user")

if kind == "guest":
Expand All @@ -923,10 +931,6 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
if not isinstance(desired_username, str) or len(desired_username) > 512:
raise SynapseError(400, "Invalid username")

# Allow only ASes to use this API.
if body.get("type") != APP_SERVICE_REGISTRATION_TYPE:
raise SynapseError(403, "Non-application service registration type")

if not self.auth.has_access_token(request):
raise SynapseError(
400,
Expand Down
37 changes: 36 additions & 1 deletion tests/handlers/test_oauth_delegation.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
OAuthInsufficientScopeError,
SynapseError,
)
from synapse.appservice import ApplicationService
from synapse.http.site import SynapseRequest
from synapse.rest import admin
from synapse.rest.client import account, devices, keys, login, logout, register
Expand Down Expand Up @@ -575,6 +576,16 @@ def expect_unrecognized(
channel.json_body["errcode"], Codes.UNRECOGNIZED, channel.json_body
)

def expect_forbidden(
self, method: str, path: str, content: Union[bytes, str, JsonDict] = ""
) -> None:
channel = self.make_request(method, path, content)

self.assertEqual(channel.code, 403, channel.json_body)
self.assertEqual(
channel.json_body["errcode"], Codes.FORBIDDEN, channel.json_body
)

def test_uia_endpoints(self) -> None:
"""Test that endpoints that were removed in MSC2964 are no longer available."""

Expand Down Expand Up @@ -629,11 +640,35 @@ def test_account_management_endpoints_removed(self) -> None:

def test_registration_endpoints_removed(self) -> None:
"""Test that registration endpoints that were removed in MSC2964 are no longer available."""
appservice = ApplicationService(
token="i_am_an_app_service",
id="1234",
namespaces={"users": [{"regex": r"@alice:.+", "exclusive": True}]},
sender="@as_main:test",
)

self.hs.get_datastores().main.services_cache = [appservice]
self.expect_unrecognized(
"GET", "/_matrix/client/v1/register/m.login.registration_token/validity"
)

# Registration is disabled
self.expect_forbidden(
"POST",
"/_matrix/client/v3/register",
{"username": "alice", "password": "hunter2"},
)

# This is still available for AS registrations
# self.expect_unrecognized("POST", "/_matrix/client/v3/register")
channel = self.make_request(
"POST",
"/_matrix/client/v3/register",
{"username": "alice", "type": "m.login.application_service"},
shorthand=False,
access_token="i_am_an_app_service",
)
self.assertEqual(channel.code, 200, channel.json_body)

self.expect_unrecognized("GET", "/_matrix/client/v3/register/available")
self.expect_unrecognized(
"POST", "/_matrix/client/v3/register/email/requestToken"
Expand Down

0 comments on commit f7bc63e

Please sign in to comment.