Compare commits

...

3 commits

Author SHA1 Message Date
Kévin Commaille 3a1479a48b
Add link to client registration
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-06-18 11:14:41 +02:00
Kévin Commaille 9497d3c03d
Move "Login flow" and "Refresh Token flow" as the first sections of OAuth 2.0
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-06-18 11:12:15 +02:00
Kévin Commaille 572c2f3119
Apply review suggestions
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-06-18 11:10:42 +02:00

View file

@ -1481,178 +1481,6 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`.
### OAuth 2.0 API
#### Server metadata discovery
{{% http-api spec="client-server" api="oauth_server_metadata" %}}
#### Scope
The client requests a scope in the OAuth 2.0 authorization flow, which is then
associated to the generated access and refresh tokens. This provides a framework
for obtaining user consent.
A scope is defined in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3)
as a string containing a list of space-separated scope tokens.
{{% boxes/note %}}
The framework encourages the practice of obtaining additional user consent when
a client asks for a new scope that was not granted previously. This could be
used by future MSCs to replace the legacy [User-Interactive Authentication API](#user-interactive-authentication-api).
{{% /boxes/note %}}
##### Scope token format
All scope tokens related to Matrix should start with `urn:matrix:` and use the
`:` delimiter for further sub-division.
Scope tokens related to mapping of Client-Server API access levels should start
with `urn:matrix:client:`.
{{% boxes/note %}}
For MSCs that build on this namespace, unstable subdivisions should be used
whilst in development. For example, if MSCXXXX wants to introduce the
`urn:matrix:client:foo` scope, it could use
`urn:matrix:client:com.example.mscXXXX.foo` during development.
If it needs to introduce multiple scopes, like `urn:matrix:client:foo` and
`urn:matrix:client:bar`, it could use
`urn:matrix:client:com.example.mscXXXX:foo` and
`urn:matrix:client:com.example.mscXXXX:bar`.
{{% /boxes/note %}}
##### Allocated scope tokens
This specification defines the following scope tokens:
- [`urn:matrix:client:api:*`](#full-client-server-api-readwrite-access)
- [`urn:matrix:client:device:<device_id>`](#device-id-allocation)
###### Full client-server API read/write access
| Scope | Purpose |
|---------------------------|---------------------------------------------|
| `urn:matrix:client:api:*` | Grants full access to the Client-Server API. |
{{% boxes/note %}}
This token matches the behavior of the legacy authentication API. Future MSCs
could introduce more fine-grained scope tokens like
`urn:matrix:client:api:read:*` for read-only access.
{{% /boxes/note %}}
###### Device ID allocation
| Scope | Purpose |
|----------------------------------------|----------------------------------------------------------------------------------------------|
| `urn:matrix:client:device:<device_id>` | Allocates the given `device_id` and associates it to the generated access and refresh tokens. |
Contrary to the legacy login and registration APIs where the homeserver is
typically the one generating a `device_id` and providing it to the client, with
the OAuth 2.0 API, the client is responsible for allocating the `device_id`.
There MUST be exactly one `urn:matrix:client:device:<device_id>` token in the
requested scope in the login flow.
When generating a new `device_id`, the client SHOULD generate a random string
with enough entropy. It SHOULD only use characters from the unreserved character
list defined by [RFC 3986 section 2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3):
```
unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~"
```
Using this alphabet, a 10 character string is enough to stand a sufficient
chance of being unique per user. The homeserver MAY reject a request for a
`device_id` that is not long enough or contains characters outside the
unreserved list.
In any case it MUST only use characters allowed by the OAuth 2.0 scope
definition in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3),
which is defined as the following ASCII ranges:
```
%x21 / %x23-5B / %x5D-7E
```
This definition matches:
- alphanumeric characters: `A-Z`, `a-z`, `0-9`
- the following characters: ``! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~``
#### Grant types
[RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) and other RFCs define
several "grant types": ways to obtain an ["access token"](#using-access-tokens).
All these grants types require the client to know the following authorization
server metadata:
- `token_endpoint`
- `grant_types_supported`
The client must also have obtained a `client_id` by registering with the server.
This specification supports the following grant types:
- [Authorization code grant](#authorization-code-grant)
- [Refresh token grant](#refresh-token-grant)
##### Authorization code grant
As per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1),
the authorization code grant lets the client obtain an access token through a
browser redirect.
This grant requires the client to know the following authorization server
metadata:
- `authorization_endpoint`
- `response_types_supported`
- `response_mode_supported`
To use this grant, homeservers and clients MUST:
- Support the authorization code grant as per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1).
- Support the [refresh token grant](#refresh-token-grant).
- Support PKCE using the `S256` code challenge method as per [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636).
- Use pre-registered, strict redirect URIs.
- Use the `fragment` response mode as per [OAuth 2.0 Multiple Response Type
Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
for clients with an HTTPS redirect URI.
###### User registration
Clients can signal to the server that the user desires to register a new account
by initiating the authorization code grant with the `prompt=create` parameter
set in the authorization request as defined in [Initiating User Registration via
OpenID Connect 1.0](https://openid.net/specs/openid-connect-prompt-create-1_0.html).
Whether the homeserver supports this parameter is advertised by the
`prompt_values_supported` authorization server metadata.
Servers that support this parameter SHOULD show the account registration UI in
the browser.
##### Refresh token grant
As per [RFC 6749 section 6](https://datatracker.ietf.org/doc/html/rfc6749#section-6),
the refresh token grant lets the client exchange a refresh token for an access
token.
When authorization is granted to a client, the homeserver MUST issue a refresh
token to the client in addition to the access token.
The access token MUST be short-lived and SHOULD be refreshed using the
`refresh_token` when expired.
The homeserver SHOULD issue a new refresh token each time an old one is used,
and invalidate the old one. However, it MUST ensure that the client is able to
retry the refresh request in the case that the response to the request is lost.
The homeserver SHOULD consider that the session is compromised if an old,
invalidated refresh token is used, and SHOULD revoke the session.
The client MUST handle access token refresh failures as follows:
- If the refresh fails due to network issues or a `5xx` HTTP status code from
the server, the client should retry the request with the old refresh token
later.
- If the refresh fails due to a `4xx` HTTP status code from the server, the
client should consider the session logged out.
#### Login flow
Logging in with the OAuth 2.0 API should be done with the [authorization code
@ -1660,10 +1488,11 @@ grant](#authorization-code-grant). In the context of the Matrix specification,
this means requesting a [scope](#scope) including full client-server API
read/write access and allocating a device ID.
First, the client needs to generate the following values:
Once the client has retrieved the [server metadata](#server-metadata-discovery),
it needs to generate the following values:
- `device_id`: a unique identifier for this device; see the
[`urn:matrix:client:device:<device_id>`] scope.
[`urn:matrix:client:device:<device_id>`](#device-id-allocation) scope token.
- `state`: a unique opaque identifier, like a [transaction ID](#transaction-identifiers),
that will allow the client to maintain state between the authorization request
and the callback.
@ -1689,7 +1518,7 @@ The client then constructs the authorization request URL using the
| `scope` | `urn:matrix:client:api:* urn:matrix:client:device:<device_id>` with the `device_id` generated previously. |
| `state` | The `state` value generated previously. |
| `response_mode` | `fragment` or `query` (see "[Callback](#callback)" below). |
| `code_challenge` | Computed from the `code_verifier` value generated previously using the SHA-256 algorithm, as described in [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) |
| `code_challenge` | Computed from the `code_verifier` value generated previously using the SHA-256 algorithm, as described in [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636). |
| `code_challenge_method` | `S256` |
This authorization request URL must be opened in the user's browser:
@ -1820,6 +1649,178 @@ The server replies with a JSON object containing the new access token, the token
type, the expiration time, and a new refresh token, like in the authorization
flow.
#### Server metadata discovery
{{% http-api spec="client-server" api="oauth_server_metadata" %}}
#### Scope
The client requests a scope in the OAuth 2.0 authorization flow, which is then
associated to the generated access and refresh tokens. This provides a framework
for obtaining user consent.
A scope is defined in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3)
as a string containing a list of space-separated scope tokens.
{{% boxes/note %}}
The framework encourages the practice of obtaining additional user consent when
a client asks for a new scope that was not granted previously. This could be
used by future MSCs to replace the legacy [User-Interactive Authentication API](#user-interactive-authentication-api).
{{% /boxes/note %}}
##### Scope token format
All scope tokens related to Matrix should start with `urn:matrix:` and use the
`:` delimiter for further sub-division.
Scope tokens related to mapping of Client-Server API access levels should start
with `urn:matrix:client:`.
{{% boxes/note %}}
For MSCs that build on this namespace, unstable subdivisions should be used
whilst in development. For example, if MSCXXXX wants to introduce the
`urn:matrix:client:foo` scope, it could use
`urn:matrix:client:com.example.mscXXXX.foo` during development.
If it needs to introduce multiple scopes, like `urn:matrix:client:foo` and
`urn:matrix:client:bar`, it could use
`urn:matrix:client:com.example.mscXXXX:foo` and
`urn:matrix:client:com.example.mscXXXX:bar`.
{{% /boxes/note %}}
##### Allocated scope tokens
This specification defines the following scope tokens:
- [`urn:matrix:client:api:*`](#full-client-server-api-readwrite-access)
- [`urn:matrix:client:device:<device_id>`](#device-id-allocation)
###### Full client-server API read/write access
| Scope | Purpose |
|---------------------------|---------------------------------------------|
| `urn:matrix:client:api:*` | Grants full access to the Client-Server API. |
{{% boxes/note %}}
This token matches the behavior of the legacy authentication API. Future MSCs
could introduce more fine-grained scope tokens like
`urn:matrix:client:api:read:*` for read-only access.
{{% /boxes/note %}}
###### Device ID allocation
| Scope | Purpose |
|----------------------------------------|----------------------------------------------------------------------------------------------|
| `urn:matrix:client:device:<device_id>` | Allocates the given `device_id` and associates it to the generated access and refresh tokens. |
Contrary to the legacy login and registration APIs where the homeserver is
typically the one generating a `device_id` and providing it to the client, with
the OAuth 2.0 API, the client is responsible for allocating the `device_id`.
There MUST be exactly one `urn:matrix:client:device:<device_id>` token in the
requested scope in the login flow.
When generating a new `device_id`, the client SHOULD generate a random string
with enough entropy. It SHOULD only use characters from the unreserved character
list defined by [RFC 3986 section 2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3):
```
unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~"
```
Using this alphabet, a 10 character string is enough to stand a sufficient
chance of being unique per user. The homeserver MAY reject a request for a
`device_id` that is not long enough or contains characters outside the
unreserved list.
In any case it MUST only use characters allowed by the OAuth 2.0 scope
definition in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3),
which is defined as the following ASCII ranges:
```
%x21 / %x23-5B / %x5D-7E
```
This definition matches:
- alphanumeric characters: `A-Z`, `a-z`, `0-9`
- the following characters: ``! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~``
#### Grant types
[RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) and other RFCs define
several "grant types": ways to obtain an ["access token"](#using-access-tokens).
All these grants types require the client to know the following [authorization
server metadata](#server-metadata-discovery):
- `token_endpoint`
- `grant_types_supported`
The client must also have obtained a `client_id` by [registering with the server](#client-registration).
This specification supports the following grant types:
- [Authorization code grant](#authorization-code-grant)
- [Refresh token grant](#refresh-token-grant)
##### Authorization code grant
As per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1),
the authorization code grant lets the client obtain an access token through a
browser redirect.
This grant requires the client to know the following [authorization server
metadata](#server-metadata-discovery):
- `authorization_endpoint`
- `response_types_supported`
- `response_mode_supported`
To use this grant, homeservers and clients MUST:
- Support the authorization code grant as per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1).
- Support the [refresh token grant](#refresh-token-grant).
- Support PKCE using the `S256` code challenge method as per [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636).
- Use [pre-registered](#client-registration), strict redirect URIs.
- Use the `fragment` response mode as per [OAuth 2.0 Multiple Response Type
Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
for clients with an HTTPS redirect URI.
###### User registration
Clients can signal to the server that the user desires to register a new account
by initiating the authorization code grant with the `prompt=create` parameter
set in the authorization request as defined in [Initiating User Registration via
OpenID Connect 1.0](https://openid.net/specs/openid-connect-prompt-create-1_0.html).
Whether the homeserver supports this parameter is advertised by the
`prompt_values_supported` authorization server metadata.
Servers that support this parameter SHOULD show the account registration UI in
the browser.
##### Refresh token grant
As per [RFC 6749 section 6](https://datatracker.ietf.org/doc/html/rfc6749#section-6),
the refresh token grant lets the client exchange a refresh token for an access
token.
When authorization is granted to a client, the homeserver MUST issue a refresh
token to the client in addition to the access token.
The access token MUST be short-lived and SHOULD be refreshed using the
`refresh_token` when expired.
The homeserver SHOULD issue a new refresh token each time an old one is used,
and invalidate the old one. However, it MUST ensure that the client is able to
retry the refresh request in the case that the response to the request is lost.
The homeserver SHOULD consider that the session is compromised if an old,
invalidated refresh token is used, and SHOULD revoke the session.
The client MUST handle access token refresh failures as follows:
- If the refresh fails due to network issues or a `5xx` HTTP status code from
the server, the client should retry the request with the old refresh token
later.
- If the refresh fails due to a `4xx` HTTP status code from the server, the
client should consider the session logged out.
### Account moderation
#### Account locking