Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC3231: Token authenticated registration #3231

Merged
merged 15 commits into from
Sep 27, 2021
Merged
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions proposals/3231-token-authenticated-registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# MSC3231: Token Authenticated Registration

Currently, homeserver administrators must choose between allowing anyone to
register and completely disabling registrations. This is a problem for
administrators who want to let certain people have an account on their server,
but do not want to register the accounts manually (possibly because the
initial password may not be changed by the user).

There are some existing external solutions (see the **Alternatives** section),
but these require additional effort from administrators and are disconnected
from Matrix clients. It would be useful for administrators to have a convenient
method of limiting registrations to certain people which requires minimal setup
and is integrated with existing clients.

## Proposal
Half-Shot marked this conversation as resolved.
Show resolved Hide resolved

The [/\_matrix/client/r0/register](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-register)
endpoint uses the [User-Interactive Authentication API](https://matrix.org/docs/spec/client_server/r0.6.1#user-interactive-authentication-api).
A new authentication type `m.login.registration_token` will be defined which requires
a `token` key to be present in the submitted `auth` dict. The token will be a
string of no more than 64 characters, and contain only characters matched by the
regex `[A-Za-z0-9-_]`.
govynnus marked this conversation as resolved.
Show resolved Hide resolved
This will avoid URL encoding issues with the validity checking endpoint, and
prevent DoS attacks from extremely long tokens.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems spurious: making something against the spec doesn't stop it from being a viable attack (if only...)


For example, when a client attempts registration with no `auth` dict, a server
may respond with:

```
HTTP/1.1 401 Unauthorized

{
"flows": [
{
"stages": [ "m.login.registration_token" ]
}
],
"params": {},
"session": "xxxxx"
}
```

The client would then prompt the user to enter a token and send a new request
with an `auth` dict:

```
POST /_matrix/client/r0/register

{
"auth": {
"type": "m.login.registration_token",
"token": "fBVFdqVE",
"session": "xxxxx"
}
"device_id": "ABC",
"initial_device_display_name": "Some Client",
"password": "badpassword",
govynnus marked this conversation as resolved.
Show resolved Hide resolved
"username": "bob"
}
```

If the server verifies that `fBVFdqVE` is a valid token then the account is
registered as normal assuming all other required auth stages have been completed, otherwise a `401` status is returned. Once registration of
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
the user has completed, the server may alter the validity of the token.
For example, the token may be completely invalidated, or its number of permitted
uses reduced. Management of the tokens is left to the server implementation.

Using the User-Interactive Authentication API means clients' existing
registration logic will be unaffected, with a fallback available for clients
without native support for the new authentication type.
govynnus marked this conversation as resolved.
Show resolved Hide resolved


### Checking the validity of a token

A Client may wish to present username and password inputs only after it has
checked the token is valid.
govynnus marked this conversation as resolved.
Show resolved Hide resolved

Clients would be able to check the validity of a token in advance of
registration with a `GET` request to
`/_matrix/client/v1/register/m.login.registration_token/validity`.
This endpoint would take a required `token` query parameter, and validity would be
indicated by the boolean `valid` key in the response.

For example, a client would send:

```
GET /_matrix/client/v1/register/m.login.registration_token/validity?token=abcd
govynnus marked this conversation as resolved.
Show resolved Hide resolved
govynnus marked this conversation as resolved.
Show resolved Hide resolved
```

If `abcd` is a valid token, the server would respond with:

```
HTTP/1.1 200 OK

{
"valid": true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add valid_until or invalid_since to show that the token was valid in the past but is not valid anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whether tokens expire or not is up to the server, so some tokens might not expire, and it may not be easy for servers to store when a token becomes invalid.

The response could be changed so that the client can distinguish between tokens which are:

  • unknown to the server
  • known but invalid (were valid in the past)
  • valid

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the usecase for distinguishing between "unknown to the server" and "known but invalid (were valid in the past)".

Also note that doing so consistently would require homeserver implementations to keep a record of all tokens ever created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about the usecase. I don't think servers would be required to keep a record because if the token is unknown (maybe it was valid but is now deleted) then it can say so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also simple enough to add in a future extension so it shouldn't necessarily block the MSC. It does seem like it could be useful: servers presumably wouldn't be obliged to be 100% correct about what tokens are were valid and have never been valid.

}
```

This does not perform any actual authentication, and the validity of the token
may change between the check and the User-Interactive Authentication.

This endpoint should be rate limited in order to prevent dictionary attacks.

govynnus marked this conversation as resolved.
Show resolved Hide resolved
## Potential issues
govynnus marked this conversation as resolved.
Show resolved Hide resolved
govynnus marked this conversation as resolved.
Show resolved Hide resolved

The new authentication type would only apply to the
`/_matrix/client/r0/register` endpoint. This should not cause problems, but it
would be worth noting in any change to the specification.


## Alternatives

[matrix-registration](https://github.com/ZerataX/matrix-registration/) is an
application which provides token management and a standalone web interface.
It uses Synapse's admin API to do registrations.

[Midnight](https://github.com/KombuchaPrivacy/midnight) sits in front of a
homeserver and handles the `/_matrix/client/r0/register` endpoint. It provides
token management and does additional checks on the requested username.
Registration requests are forwarded to the homeserver once authenticated.
It uses the User-Interactive Authentication API in a very similar way to this
MSC, which could allow existing Matrix clients to be used.

[matrix-register-bot](https://github.com/krombel/matrix-register-bot) is a
Matrix bot which allows registrations done through the provided web interface
to be accepted or denied by users in a certain room. When a registration is
approved temporary credentials are sent to the user's verified email address.
It can use Synapse's admin API or [matrix-synapse-rest-auth](https://github.com/kamax-matrix/matrix-synapse-rest-password-provider#integrate)
to do the registration.


## Unstable prefix

Implementations should use `org.matrix.msc3231.login.registration_token` as the
authentication type until this MSC has passed FCP and been merged.
Similarly, `/_matrix/client/unstable/org.matrix.msc3231/register/org.matrix.msc3231.login.registration_token/validity`
should be used as the endpoint for checking the validity of a token in advance.