mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-05-01 06:34:09 +02:00
Compare commits
8 commits
d977311339
...
f47c90fef6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f47c90fef6 | ||
|
|
979264e923 | ||
|
|
f7c1672959 | ||
|
|
51ccbbd240 | ||
|
|
c0781c5551 | ||
|
|
d0efefec4f | ||
|
|
99de5eded3 | ||
|
|
a2a9a02efa |
1
changelogs/client_server/newsfragments/2147.new
Normal file
1
changelogs/client_server/newsfragments/2147.new
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965).
|
||||
1
changelogs/client_server/newsfragments/2149.feature
Normal file
1
changelogs/client_server/newsfragments/2149.feature
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Add missing fields in example for `ExportedSessionData`.
|
||||
|
|
@ -1481,22 +1481,26 @@ 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" %}}
|
||||
|
||||
#### Client registration
|
||||
|
||||
Before being able to use the authorization flow to obtain an access token, a
|
||||
client needs to obtain a `client_id` by registering itself with the server.
|
||||
|
||||
One way to do that is to leverage OAuth 2.0 Dynamic Client Registration as
|
||||
defined in [RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591).
|
||||
This should be done via OAuth 2.0 Dynamic Client Registration as defined in
|
||||
[RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591).
|
||||
|
||||
##### Client metadata
|
||||
|
||||
In OAuth 2.0, clients register a set of metadata values with the authorization
|
||||
server which associates it to a newly generated `client_id`. These values are
|
||||
server, which associates it with a newly generated `client_id`. These values are
|
||||
used to describe the client to the user and define how the client interacts with
|
||||
the server.
|
||||
|
||||
{{% json-schema name="oauth2-client-metadata" %}}
|
||||
{{% definition path="schemas/oauth2-client-metadata" %}}
|
||||
|
||||
###### Metadata localization
|
||||
|
||||
|
|
@ -1539,20 +1543,19 @@ In all cases, the redirect URI MUST NOT have a fragment component.
|
|||
|
||||
`web` clients can use redirect URIs that:
|
||||
|
||||
- MUST use the `https` scheme
|
||||
- MUST NOT use a user or password in the authority component of the URI
|
||||
- MUST use the `https` scheme.
|
||||
- MUST NOT use a user or password in the authority component of the URI.
|
||||
- MUST use the client URI as a common base for the authority component, as
|
||||
defined previously
|
||||
- MAY include an `application/x-www-form-urlencoded` formatted query component
|
||||
defined previously.
|
||||
- MAY include an `application/x-www-form-urlencoded` formatted query component.
|
||||
|
||||
For example, with `https://example.com/` as the client URI,
|
||||
|
||||
These are valid redirect URIs:
|
||||
For example, with `https://example.com/` as the client URI, the following are
|
||||
valid redirect URIs:
|
||||
- `https://example.com/callback`
|
||||
- `https://app.example.com/callback`
|
||||
- `https://example.com:5173/?query=value`
|
||||
|
||||
These are invalid redirect URIs:
|
||||
With the same client URI, the following are invalid redirect URIs:
|
||||
- `https://example.com/callback#fragment`
|
||||
- `http://example.com/callback`
|
||||
- `http://localhost/`
|
||||
|
|
@ -1561,23 +1564,25 @@ These are invalid redirect URIs:
|
|||
|
||||
`native` clients can use three types of redirect URIs:
|
||||
|
||||
1. Private-Use URI Scheme:
|
||||
- the scheme MUST be prefixed with the client URI hostname in reverse-DNS
|
||||
notation. For example, if the client URI is `https://example.com/`, then a
|
||||
valid custom URI scheme would be `com.example.app:/`.
|
||||
- the URI MUST NOT have an authority component. This means that it MUST have
|
||||
either a single slash or none immediately following the scheme, with no
|
||||
hostname, username, or port.
|
||||
2. `http` URI on the loopback interface:
|
||||
- it MUST use the `http` scheme
|
||||
- the host part MUST be `localhost`, `127.0.0.1`, or `[::1]`
|
||||
- it MUST have no port. The homeserver MUST then accept any port number during
|
||||
the authorization flow.
|
||||
3. Claimed `https` Scheme URI: some operating systems allow apps to claim
|
||||
`https` scheme URIs in the domains they control. When the browser encounters a
|
||||
claimed URI, instead of the page being loaded in the browser, the native app
|
||||
is launched with the URI supplied as a launch parameter. The same rules as for
|
||||
`web` clients apply.
|
||||
1. **Private-Use URI Scheme**
|
||||
- The scheme MUST be prefixed with the client URI hostname in reverse-DNS
|
||||
notation. For example, if the client URI is `https://example.com/`, then a
|
||||
valid custom URI scheme would be `com.example.app:/`.
|
||||
- There MUST NOT be an authority component. This means that the URI MUST have
|
||||
either a single slash or none immediately following the scheme, with no
|
||||
hostname, username, or port.
|
||||
2. **`http` URI on the loopback interface**
|
||||
- The scheme MUST be `http`.
|
||||
- The host part MUST be `localhost`, `127.0.0.1`, or `[::1]`.
|
||||
- There MUST NOT be a port. The homeserver MUST then accept any port number
|
||||
during the authorization flow.
|
||||
3. **Claimed `https` Scheme URI**
|
||||
|
||||
Some operating systems allow apps to claim `https` scheme URIs in the
|
||||
domains they control. When the browser encounters a claimed URI, instead of
|
||||
the page being loaded in the browser, the native app is launched with the
|
||||
URI supplied as a launch parameter. The same rules as for `web` clients
|
||||
apply.
|
||||
|
||||
These restrictions are the same as defined by [RFC 8252 section 7](https://tools.ietf.org/html/rfc8252#section-7).
|
||||
|
||||
|
|
@ -1601,7 +1606,7 @@ These are invalid redirect URIs:
|
|||
|
||||
To register, the client sends an HTTP `POST` request to the
|
||||
`registration_endpoint`, which can be found in the server metadata. The body of
|
||||
the request is the JSON client metadata.
|
||||
the request is the JSON-encoded [`OAuthClientMetadata`](#client-metadata).
|
||||
|
||||
For example, the client could send the following registration request:
|
||||
|
||||
|
|
@ -1638,7 +1643,7 @@ Upon successful registration, the server replies with an `HTTP 201 Created`
|
|||
response, with a JSON object containing the allocated `client_id` and all the
|
||||
registered metadata values.
|
||||
|
||||
With the previous registration request, the server would reply with:
|
||||
With the registration request above, the server might reply with:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -1683,6 +1688,96 @@ client can share a single `client_id`, reducing the overall number of
|
|||
registrations.
|
||||
{{% /boxes/note %}}
|
||||
|
||||
#### 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: ``! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~``
|
||||
|
||||
### Account moderation
|
||||
|
||||
#### Account locking
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ properties:
|
|||
type: string
|
||||
description: |-
|
||||
The end-to-end message encryption algorithm that the key is for. Must be `m.megolm.v1.aes-sha2`.
|
||||
example: "m.megolm.v1.aes-sha2"
|
||||
forwarding_curve25519_key_chain:
|
||||
type: array
|
||||
items:
|
||||
|
|
@ -30,31 +31,24 @@ properties:
|
|||
description: |-
|
||||
Chain of Curve25519 keys through which this session was forwarded, via [m.forwarded_room_key](/client-server-api/#mforwarded_room_key)
|
||||
events.
|
||||
example: [ "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" ]
|
||||
sender_key:
|
||||
type: string
|
||||
description: |-
|
||||
Unpadded base64-encoded device Curve25519 key.
|
||||
example: "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU"
|
||||
sender_claimed_keys:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
A map from algorithm name (`ed25519`) to the Ed25519 signing key of the sending device.
|
||||
example: { "ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y" }
|
||||
session_key:
|
||||
type: string
|
||||
description: |-
|
||||
Unpadded base64-encoded session key in [session-export format](https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-export-format).
|
||||
example: {
|
||||
"algorithm": "m.megolm.v1.aes-sha2",
|
||||
"forwarding_curve25519_key_chain": [
|
||||
"hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw"
|
||||
],
|
||||
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
|
||||
"sender_claimed_keys": {
|
||||
"ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y",
|
||||
},
|
||||
"session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..."
|
||||
}
|
||||
example: "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..."
|
||||
required:
|
||||
- algorithm
|
||||
- forwarding_curve25519_key_chain
|
||||
|
|
|
|||
176
data/api/client-server/oauth_server_metadata.yaml
Normal file
176
data/api/client-server/oauth_server_metadata.yaml
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
# Copyright 2025 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Matrix Client-Server OAuth 2.0 Server Metadata Discovery API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
"/auth_metadata":
|
||||
get:
|
||||
summary: Get the OAuth 2.0 authorization server metadata.
|
||||
description: |-
|
||||
Gets the OAuth 2.0 authorization server metadata, as defined in
|
||||
[RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414), including the
|
||||
endpoint URLs and the supported parameters that can be used by the
|
||||
clients.
|
||||
|
||||
This endpoint definition includes only the fields that are meaningful in
|
||||
the context of the Matrix specification. The full list of possible
|
||||
fields is available in the [OAuth Authorization Server Metadata
|
||||
registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata),
|
||||
and normative definitions of them are available in their respective
|
||||
RFCs.
|
||||
|
||||
{{% boxes/note %}}
|
||||
The authorization server metadata is relatively large and may change
|
||||
over time. Clients should:
|
||||
|
||||
- Cache the metadata appropriately based on HTTP caching headers
|
||||
- Refetch the metadata if it is stale
|
||||
{{% /boxes/note %}}
|
||||
operationId: getAuthMetadata
|
||||
responses:
|
||||
"200":
|
||||
description: The OAuth 2.0 authorization server metadata.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
issuer:
|
||||
type: string
|
||||
format: uri
|
||||
description: |-
|
||||
The authorization server's issuer identifier, which is a URL that uses the
|
||||
`https` scheme and has no query or fragment components.
|
||||
|
||||
This is not used in the context of the Matrix specification, but is required
|
||||
by [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
|
||||
authorization_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: |-
|
||||
URL of the authorization endpoint, necessary to use the authorization code
|
||||
grant.
|
||||
token_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: |-
|
||||
URL of the token endpoint, necessary to use the authorization code grant and
|
||||
the refresh token grant.
|
||||
revocation_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: |-
|
||||
URL of the revocation endpoint, necessary to log out a client by invalidating
|
||||
its access and refresh tokens.
|
||||
registration_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: |-
|
||||
URL of the client registration endpoint, necessary to perform dynamic
|
||||
registration of a client.
|
||||
response_types_supported:
|
||||
type: array
|
||||
description: |-
|
||||
List of OAuth 2.0 response type strings that the server supports at the
|
||||
authorization endpoint.
|
||||
|
||||
This array MUST contain at least the `code` value, for clients to be able to
|
||||
use the authorization code grant.
|
||||
items:
|
||||
type: string
|
||||
description: A response type that the server supports.
|
||||
grant_types_supported:
|
||||
type: array
|
||||
description: |-
|
||||
List of OAuth 2.0 grant type strings that the server supports at the token
|
||||
endpoint.
|
||||
|
||||
This array MUST contain at least the `authorization_code` and `refresh_token`
|
||||
values, for clients to be able to use the authorization code grant and refresh
|
||||
token grant, respectively.
|
||||
items:
|
||||
type: string
|
||||
description: A grant type that the server supports.
|
||||
response_modes_supported:
|
||||
type: array
|
||||
description: |-
|
||||
List of OAuth 2.0 response mode strings that the server supports at the
|
||||
authorization endpoint.
|
||||
|
||||
This array MUST contain at least the `query` and `fragment` values, for
|
||||
improved security in the authorization code grant.
|
||||
items:
|
||||
type: string
|
||||
description: A response mode that the server supports.
|
||||
code_challenge_methods_supported:
|
||||
type: array
|
||||
description: |-
|
||||
List of OAuth 2.0 Proof Key for Code Exchange (PKCE) code challenge methods
|
||||
that the server supports at the authorization endpoint.
|
||||
|
||||
This array MUST contain at least the `S256` value, for improved security in
|
||||
the authorization code grant.
|
||||
items:
|
||||
type: string
|
||||
description: A PKCE code challenge method that the server supports.
|
||||
prompt_values_supported:
|
||||
type: array
|
||||
description: |-
|
||||
List of OpenID Connect prompt values that the server supports at the
|
||||
authorization endpoint.
|
||||
|
||||
Only the `create` value defined in [Initiating User Registration via OpenID
|
||||
Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html) is
|
||||
supported, for a client to signal to the server that the user desires to
|
||||
register a new account.
|
||||
items:
|
||||
type: string
|
||||
description: A prompt value that the server supports.
|
||||
required:
|
||||
- issuer
|
||||
- authorization_endpoint
|
||||
- token_endpoint
|
||||
- revocation_endpoint
|
||||
- registration_endpoint
|
||||
- response_types_supported
|
||||
- grant_types_supported
|
||||
- response_modes_supported
|
||||
- code_challenge_methods_supported
|
||||
example: {
|
||||
"issuer": "https://account.example.com/",
|
||||
"authorization_endpoint": "https://account.example.com/oauth2/auth",
|
||||
"token_endpoint": "https://account.example.com/oauth2/token",
|
||||
"registration_endpoint": "https://account.example.com/oauth2/clients/register",
|
||||
"revocation_endpoint": "https://account.example.com/oauth2/revoke",
|
||||
"response_types_supported": ["code"],
|
||||
"grant_types_supported": ["authorization_code", "refresh_token"],
|
||||
"response_modes_supported": ["query", "fragment"],
|
||||
"code_challenge_methods_supported": ["S256"],
|
||||
}
|
||||
tags:
|
||||
- Session management
|
||||
servers:
|
||||
- url: "{protocol}://{hostname}{basePath}"
|
||||
variables:
|
||||
protocol:
|
||||
enum:
|
||||
- http
|
||||
- https
|
||||
default: https
|
||||
hostname:
|
||||
default: localhost:8008
|
||||
basePath:
|
||||
default: /_matrix/client/v1
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
title: OAuth 2.0 Client Server Metadata
|
||||
title: OAuthClientMetadata
|
||||
type: object
|
||||
description: |-
|
||||
This definition of the metadata specifies only the fields that are meaningful
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
{{/*
|
||||
|
||||
This template is used to render the fields of a JSON schema that is not an
|
||||
event.
|
||||
|
||||
It expects to be passed a `name` parameter, which is the name of a file
|
||||
under /data/schemas. The file extension is omitted.
|
||||
|
||||
For example:
|
||||
|
||||
{{% json-schema name="oauth2-client-metadata" %}}
|
||||
|
||||
*/}}
|
||||
|
||||
{{ $schema := index .Site.Data "schemas" .Params.name }}
|
||||
{{ $path := delimit (slice "schemas" .Params.name) "/" }}
|
||||
|
||||
{{ $schema = partial "json-schema/resolve-refs" (dict "schema" $schema "path" $path) }}
|
||||
{{ $schema = partial "json-schema/resolve-allof" $schema }}
|
||||
|
||||
<section class="rendered-data event">
|
||||
|
||||
<details {{ if not .Site.Params.ui.rendered_data_collapsed }}open{{ end }}>
|
||||
<summary>
|
||||
|
||||
<h1>
|
||||
<code>{{ $schema.title }}</code>
|
||||
</h1>
|
||||
</summary>
|
||||
|
||||
<hr>
|
||||
|
||||
{{ if $schema.description -}}
|
||||
{{ $schema.description | markdownify -}}
|
||||
{{ end -}}
|
||||
|
||||
{{ $schema = merge $schema (dict "title" "") -}}
|
||||
|
||||
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema) -}}
|
||||
{{ range $additional_types -}}
|
||||
{{ partial "openapi/render-object-table" . -}}
|
||||
{{ end -}}
|
||||
|
||||
</details>
|
||||
|
||||
</section>
|
||||
Loading…
Reference in a new issue