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

Implement MSC3231: Token authenticated registration #10142

Merged
merged 54 commits into from
Aug 21, 2021
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5856f81
Hard-coded token authenticated registration
govynnus Jun 3, 2021
5f21580
Create registration_tokens table
govynnus Jun 10, 2021
2b8726c
Check in database to validate registration token
govynnus Jun 11, 2021
5b1ec0b
Increment `completed` when registration token used
govynnus Jun 14, 2021
15e5769
Rename total_uses to uses_allowed
govynnus Jun 14, 2021
9c502b0
Improve unit tests
govynnus Jun 14, 2021
e7754a9
Increment pending while registration in progress
govynnus Jun 14, 2021
ef05a6d
Add unit test for registration token expiry
govynnus Jun 16, 2021
53f0e05
Fix config file related bits
govynnus Jun 16, 2021
7883191
Run connected database ops in same transaction
govynnus Jun 16, 2021
1debc22
Fix some formatting problems
govynnus Jun 17, 2021
6ac376d
Test `completed` is empty when auth should fail
govynnus Jun 17, 2021
dfa8fec
Override type of simple_select_one_txn
govynnus Jun 17, 2021
c89d786
Raise error if token changes during UIA
govynnus Jun 17, 2021
e7bd00a
Add validity checking endpoint
govynnus Jun 18, 2021
d6704fd
Use AuthHandler methods for accessing UIA session
govynnus Jun 20, 2021
003e67d
Rate limit validity checking endpoint
govynnus Jun 29, 2021
3c51680
Use LoginError rather than SynapseError in checker
govynnus Jun 29, 2021
af90be7
Add fallback
govynnus Jun 30, 2021
1552b70
Docs for currently non-existent admin API
govynnus Jul 6, 2021
4df4a6e
Implement admin API
govynnus Jul 10, 2021
6901eee
Move admin api docs to correct location
govynnus Jul 19, 2021
93f752d
Include general API shape in docstrings
govynnus Jul 20, 2021
b2bf3ac
More input validation when creating and updating
govynnus Jul 20, 2021
5d5bdef
Add space to SQL query
govynnus Jul 20, 2021
b61c7f6
Fix SQL query for invalid tokens
govynnus Jul 20, 2021
e7495e6
Decrease pending when UIA session expires
govynnus Jul 22, 2021
39d24d2
Add type to test argument
govynnus Jul 23, 2021
70cc9d2
Add test for session expiry with deleted token
govynnus Jul 23, 2021
09f6572
Use f-strings rather than str.format()
govynnus Jul 27, 2021
36adec4
Update docs/usage/administration/admin_api/registration_tokens.md
govynnus Jul 27, 2021
7e539f5
Use more descriptive name
govynnus Jul 27, 2021
1cf29c9
Return 200 when nothing to update
govynnus Jul 27, 2021
7f9efcd
Remove unneeded else and add missing f
govynnus Jul 27, 2021
e9435f8
Run linter
govynnus Jul 27, 2021
f6e4831
Add uses_allowed to updating example in docstring
govynnus Aug 12, 2021
7208760
Add return values to docstring
govynnus Aug 12, 2021
47b8837
Add docstring to validity checking endpoint
govynnus Aug 12, 2021
b76099e
Move functions into RegistrationWorkerStore
govynnus Aug 12, 2021
86bbc24
Merge branch 'develop' into token-registration
govynnus Aug 19, 2021
c6cb80b
Add link to admin API docs in config file
govynnus Aug 19, 2021
ba22ffd
Move table creation SQL to latest delta
govynnus Aug 19, 2021
c775dce
Add changelog entry
govynnus Aug 19, 2021
f327b29
Regenerate sample config
govynnus Aug 19, 2021
c6bcae2
Move table creation sql to actual newest delta
govynnus Aug 20, 2021
01a74da
Avoid integrity error when creating tokens
govynnus Aug 20, 2021
5bfc707
Fix docs, comments and variable names
govynnus Aug 20, 2021
b5608c3
Try again if generated token already exists
govynnus Aug 20, 2021
bf28876
Let validity checking endpoint be used by workers
govynnus Aug 20, 2021
2e59dda
Document usage of `null` when updating tokens
govynnus Aug 20, 2021
df0077d
Merge remote-tracking branch 'upstream/develop' into token-registration
govynnus Aug 20, 2021
54867ef
Simplify retrying of token generation
govynnus Aug 21, 2021
20b566c
Small additions to admin api documentation
govynnus Aug 21, 2021
04b237a
Update synapse/storage/databases/main/registration.py
anoadragon453 Aug 21, 2021
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
1 change: 1 addition & 0 deletions changelog.d/10142.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for [MSC3231 - Token authenticated registration](https://github.com/matrix-org/matrix-doc/pull/3231). Users can be required to submit a token during registration to authenticate themselves. Contributed by Callum Brown.
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
- [Media](admin_api/media_admin_api.md)
- [Purge History](admin_api/purge_history_api.md)
- [Register Users](admin_api/register_api.md)
- [Registration Tokens](usage/administration/admin_api/registration_tokens.md)
- [Manipulate Room Membership](admin_api/room_membership.md)
- [Rooms](admin_api/rooms.md)
- [Server Notices](admin_api/server_notices.md)
Expand Down
15 changes: 15 additions & 0 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,8 @@ log_config: "CONFDIR/SERVERNAME.log.config"
# is using
# - one for registration that ratelimits registration requests based on the
# client's IP address.
# - one for checking the validity of registration tokens that ratelimits
# requests based on the client's IP address.
# - one for login that ratelimits login requests based on the client's IP
# address.
# - one for login that ratelimits login requests based on the account the
Expand Down Expand Up @@ -821,6 +823,10 @@ log_config: "CONFDIR/SERVERNAME.log.config"
# per_second: 0.17
# burst_count: 3
#
#rc_registration_token_validity:
# per_second: 0.1
# burst_count: 5
#
#rc_login:
# address:
# per_second: 0.17
Expand Down Expand Up @@ -1169,6 +1175,15 @@ url_preview_accept_language:
#
#enable_3pid_lookup: true

# Require users to submit a token during registration.
# Tokens can be managed using the admin API:
# https://matrix-org.github.io/synapse/latest/usage/administration/admin_api/registration_tokens.html
# Note that `enable_registration` must be set to `true`.
# Disabling this option will not delete any tokens previously generated.
# Defaults to false. Uncomment the following to require tokens:
#
#registration_requires_token: true

# If set, allows registration of standard or admin accounts by anyone who
# has the shared secret, even if registration is otherwise disabled.
#
Expand Down
292 changes: 292 additions & 0 deletions docs/usage/administration/admin_api/registration_tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
# Registration Tokens

This API allows you to manage tokens which can be used to authenticate
registration requests, as proposed in [MSC3231](https://github.com/govynnus/matrix-doc/blob/token-registration/proposals/3231-token-authenticated-registration.md).
To use it, you will need to enable the `registration_requires_token` config
option, and authenticate by providing an `access_token` for a server admin:
see [Admin API](../../usage/administration/admin_api).
Note that this API is still experimental; not all clients may support it yet.

govynnus marked this conversation as resolved.
Show resolved Hide resolved

## Registration token objects

Most endpoints make use of JSON objects that contain details about tokens.
These objects have the following fields:
- `token`: The token which can be used to authenticate registration.
- `uses_allowed`: The number of times the token can be used to complete a
registration before it becomes invalid.
- `pending`: The number of pending uses the token has. When someone uses
the token to authenticate themselves, the pending counter is incremented
so that the token is not used more than the permitted number of times.
When the person completes registration the pending counter is decremented,
and the completed counter is incremented.
- `completed`: The number of times the token has been used to successfully
complete a registration.
- `expiry_time`: The latest time the token is valid. Given as the number of
milliseconds since 1970-01-01 00:00:00 UTC (the start of the Unix epoch).


## List all tokens

Lists all tokens and details about them. If the request is successful, the top
level JSON object will have a `registration_tokens` key which is an array of
registration token objects.

```
GET /_synapse/admin/v1/registration_tokens
```

Optional query parameters:
- `valid`: `true` or `false`. If `true`, only valid tokens are returned.
If `false`, only tokens that have expired or have had all uses exhausted are
returned. If omitted, all tokens are returned regardless of validity.

Example:

```
GET /_synapse/admin/v1/registration_tokens
```
```
200 OK

{
"registration_tokens": [
{
"token": "abcd",
"uses_allowed": 3,
"pending": 0,
"completed": 1,
"expiry_time": null
},
{
"token": "pqrs",
"uses_allowed": 2,
"pending": 1,
"completed": 1,
"expiry_time": null
},
{
"token": "wxyz",
"uses_allowed": null,
"pending": 0,
"completed": 9,
"expiry_time": 1625394937000 // 2021-07-04 10:35:37 UTC
}
]
}
```

Example using the `valid` query parameter:

```
GET /_synapse/admin/v1/registration_tokens?valid=false
```
```
200 OK

{
"registration_tokens": [
{
"token": "pqrs",
"uses_allowed": 2,
"pending": 1,
"completed": 1,
"expiry_time": null
},
{
"token": "wxyz",
"uses_allowed": null,
"pending": 0,
"completed": 9,
"expiry_time": 1625394937000 // 2021-07-04 10:35:37 UTC
}
]
}
```


## Get one token

Get details about a single token. If the request is successful, the response
body will be a registration token object.

```
GET /_synapse/admin/v1/registration_tokens/<token>
```

Path parameters:
- `token`: The registration token to return details of.

Example:

```
GET /_synapse/admin/v1/registration_tokens/abcd
```
```
200 OK

{
"token": "abcd",
"uses_allowed": 3,
"pending": 0,
"completed": 1,
"expiry_time": null
}
```


## Create token

Create a new registration token. If the request is successful, the newly created
token will be returned as a registration token object in the response body.

```
POST /_synapse/admin/v1/registration_tokens/new
```

The request body must be a JSON object and can contain the following fields:
- `token`: The registration token. A string of no more than 64 characters that
consists only of characters matched by the regex `[A-Za-z0-9-_]`.
Default: randomly generated.
- `uses_allowed`: The integer number of times the token can be used to complete
a registration before it becomes invalid.
Default: `null` (unlimited uses).
- `expiry_time`: The latest time the token is valid. Given as the number of
milliseconds since 1970-01-01 00:00:00 UTC (the start of the Unix epoch).
You could use, for example, `date '+%s000' -d 'tomorrow'`.
Default: `null` (token does not expire).
- `length`: The length of the token randomly generated if `token` is not
specified. Must be between 1 and 64 inclusive. Default: `16`.

If a field is omitted the default is used.

Example using defaults:

```
POST /_synapse/admin/v1/registration_tokens/new

{}
```
```
200 OK

{
"token": "0M-9jbkf2t_Tgiw1",
"uses_allowed": null,
"pending": 0,
"completed": 0,
"expiry_time": null
}
```

Example specifying some fields:

```
POST /_synapse/admin/v1/registration_tokens/new

{
"token": "defg",
"uses_allowed": 1
}
```
```
200 OK

{
"token": "defg",
"uses_allowed": 1,
"pending": 0,
"completed": 0,
"expiry_time": null
}
```


## Update token

Update the number of allowed uses or expiry time of a token. If the request is
successful, the updated token will be returned as a registration token object
in the response body.

```
PUT /_synapse/admin/v1/registration_tokens/<token>
```

Path parameters:
- `token`: The registration token to update.

The request body must be a JSON object and can contain the following fields:
- `uses_allowed`: The integer number of times the token can be used to complete
a registration before it becomes invalid.
If `null` the token will have an unlimited number of uses.
- `expiry_time`: The latest time the token is valid. Given as the number of
milliseconds since 1970-01-01 00:00:00 UTC (the start of the Unix epoch).
If `null` the token will not expire.

If a field is omitted its value is not modified.

Example:

```
PUT /_synapse/admin/v1/registration_tokens/defg

{
"expiry_time": 4781243146000 // 2121-07-06 11:05:46 UTC
}
```
```
200 OK

{
"token": "defg",
"uses_allowed": 1,
"pending": 0,
"completed": 0,
"expiry_time": 4781243146000
}
```


## Delete token

Delete a registration token. If the request is successful, the response body
will be an empty JSON object.

```
DELETE /_synapse/admin/v1/registration_tokens/<token>
```

Path parameters:
- `token`: The registration token to delete.

Example:

```
DELETE /_synapse/admin/v1/registration_tokens/wxyz
```
```
200 OK

{}
```


## Errors

If a request fails a "standard error response" will be returned as defined in
the [Matrix Client-Server API specification](https://matrix.org/docs/spec/client_server/r0.6.1#api-standards).

For example, if the token specified in a path parameter does not exist a
`404 Not Found` error will be returned.

```
GET /_synapse/admin/v1/registration_tokens/1234
```
```
404 Not Found

{
"errcode": "M_NOT_FOUND",
"error": "No such registration token: 1234"
}
```
1 change: 1 addition & 0 deletions docs/workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ expressions:
# Registration/login requests
^/_matrix/client/(api/v1|r0|unstable)/login$
^/_matrix/client/(r0|unstable)/register$
^/_matrix/client/unstable/org.matrix.msc3231/register/org.matrix.msc3231.login.registration_token/validity$

# Event sending requests
^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/redact
Expand Down
1 change: 1 addition & 0 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class LoginType:
TERMS = "m.login.terms"
SSO = "m.login.sso"
DUMMY = "m.login.dummy"
REGISTRATION_TOKEN = "org.matrix.msc3231.login.registration_token"


# This is used in the `type` parameter for /register when called by
Expand Down
6 changes: 5 additions & 1 deletion synapse/app/generic_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@
ProfileRestServlet,
)
from synapse.rest.client.push_rule import PushRuleRestServlet
from synapse.rest.client.register import RegisterRestServlet
from synapse.rest.client.register import (
RegisterRestServlet,
RegistrationTokenValidityRestServlet,
)
from synapse.rest.client.sendtodevice import SendToDeviceRestServlet
from synapse.rest.client.versions import VersionsRestServlet
from synapse.rest.client.voip import VoipRestServlet
Expand Down Expand Up @@ -279,6 +282,7 @@ def _listen_http(self, listener_config: ListenerConfig):
resource = JsonResource(self, canonical_json=False)

RegisterRestServlet(self).register(resource)
RegistrationTokenValidityRestServlet(self).register(resource)
login.register_servlets(self, resource)
ThreepidRestServlet(self).register(resource)
DevicesRestServlet(self).register(resource)
Expand Down
Loading