mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-04-24 03:34:14 +02:00
Compare commits
4 commits
e89365f324
...
55f99e9134
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55f99e9134 | ||
|
|
3c9ba4a06d | ||
|
|
3e1cbe12f7 | ||
|
|
4f079f8a9c |
1
changelogs/client_server/newsfragments/2320.feature
Normal file
1
changelogs/client_server/newsfragments/2320.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add the OAuth 2.0 Device Authorization Grant (RFC 8628) as a supported grant type, as per [MSC4341](https://github.com/matrix-org/matrix-spec-proposals/pull/4341).
|
||||||
1
changelogs/client_server/newsfragments/2332.feature
Normal file
1
changelogs/client_server/newsfragments/2332.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add a "Policy Servers" module, as per [MSC4284](https://github.com/matrix-org/matrix-spec-proposals/pull/4284).
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Order the common and other error codes alphabetically and remove duplicate `M_THREEPID_IN_USE` definition.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Order the standard error codes alphabetically.
|
||||||
1
changelogs/server_server/newsfragments/2332.feature
Normal file
1
changelogs/server_server/newsfragments/2332.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add a concept of "Policy Servers", as per [MSC4284](https://github.com/matrix-org/matrix-spec-proposals/pull/4284).
|
||||||
|
|
@ -93,48 +93,27 @@ request being made was invalid.
|
||||||
|
|
||||||
These error codes can be returned by any API endpoint:
|
These error codes can be returned by any API endpoint:
|
||||||
|
|
||||||
`M_FORBIDDEN`
|
<!-- Please keep the error codes below in alphabetical order -->
|
||||||
: Forbidden access, e.g. joining a room without permission, failed login.
|
|
||||||
|
|
||||||
`M_UNKNOWN_TOKEN`
|
|
||||||
: The access or refresh token specified was not recognised.
|
|
||||||
|
|
||||||
: An additional response parameter, `soft_logout`, might be present on the
|
|
||||||
response for 401 HTTP status codes. See [the soft logout
|
|
||||||
section](#soft-logout) for more information.
|
|
||||||
|
|
||||||
`M_MISSING_TOKEN`
|
|
||||||
: No access token was specified for the request.
|
|
||||||
|
|
||||||
`M_USER_LOCKED`
|
|
||||||
: The account has been [locked](#account-locking) and cannot be used at this time.
|
|
||||||
|
|
||||||
`M_USER_SUSPENDED`
|
|
||||||
: The account has been [suspended](#account-suspension) and can only be used for
|
|
||||||
limited actions at this time.
|
|
||||||
|
|
||||||
`M_BAD_JSON`
|
`M_BAD_JSON`
|
||||||
: Request contained valid JSON, but it was malformed in some way, e.g.
|
: Request contained valid JSON, but it was malformed in some way, e.g.
|
||||||
missing required keys, invalid values for keys.
|
missing required keys, invalid values for keys.
|
||||||
|
|
||||||
`M_NOT_JSON`
|
`M_FORBIDDEN`
|
||||||
: Request did not contain valid JSON.
|
: Forbidden access, e.g. joining a room without permission, failed login.
|
||||||
|
|
||||||
`M_NOT_FOUND`
|
|
||||||
: No resource was found for this request.
|
|
||||||
|
|
||||||
`M_LIMIT_EXCEEDED`
|
`M_LIMIT_EXCEEDED`
|
||||||
: Too many requests have been sent in a short period of time. Wait a while
|
: Too many requests have been sent in a short period of time. Wait a while
|
||||||
then try again. See [Rate limiting](#rate-limiting).
|
then try again. See [Rate limiting](#rate-limiting).
|
||||||
|
|
||||||
`M_UNRECOGNIZED`
|
`M_MISSING_TOKEN`
|
||||||
: The server did not understand the request. This is expected to be returned with
|
: No access token was specified for the request.
|
||||||
a 404 HTTP status code if the endpoint is not implemented or a 405 HTTP status
|
|
||||||
code if the endpoint is implemented, but the incorrect HTTP method is used.
|
|
||||||
|
|
||||||
`M_UNKNOWN_DEVICE`
|
`M_NOT_FOUND`
|
||||||
: {{% added-in v="1.17" %}} The device ID supplied by the application service does
|
: No resource was found for this request.
|
||||||
not belong to the user ID during [identity assertion](/application-service-api/#identity-assertion).
|
|
||||||
|
`M_NOT_JSON`
|
||||||
|
: Request did not contain valid JSON.
|
||||||
|
|
||||||
`M_RESOURCE_LIMIT_EXCEEDED`
|
`M_RESOURCE_LIMIT_EXCEEDED`
|
||||||
: The request cannot be completed because the homeserver has reached a
|
: The request cannot be completed because the homeserver has reached a
|
||||||
|
|
@ -181,39 +160,85 @@ limit is a hard limit that cannot be increased.
|
||||||
`M_UNKNOWN`
|
`M_UNKNOWN`
|
||||||
: An unknown error has occurred.
|
: An unknown error has occurred.
|
||||||
|
|
||||||
|
`M_UNKNOWN_DEVICE`
|
||||||
|
: {{% added-in v="1.17" %}} The device ID supplied by the application service does
|
||||||
|
not belong to the user ID during [identity assertion](/application-service-api/#identity-assertion).
|
||||||
|
|
||||||
|
`M_UNKNOWN_TOKEN`
|
||||||
|
: The access or refresh token specified was not recognised.
|
||||||
|
|
||||||
|
: An additional response parameter, `soft_logout`, might be present on the
|
||||||
|
response for 401 HTTP status codes. See [the soft logout
|
||||||
|
section](#soft-logout) for more information.
|
||||||
|
|
||||||
|
`M_UNRECOGNIZED`
|
||||||
|
: The server did not understand the request. This is expected to be returned with
|
||||||
|
a 404 HTTP status code if the endpoint is not implemented or a 405 HTTP status
|
||||||
|
code if the endpoint is implemented, but the incorrect HTTP method is used.
|
||||||
|
|
||||||
|
`M_USER_LOCKED`
|
||||||
|
: The account has been [locked](#account-locking) and cannot be used at this time.
|
||||||
|
|
||||||
|
`M_USER_SUSPENDED`
|
||||||
|
: The account has been [suspended](#account-suspension) and can only be used for
|
||||||
|
limited actions at this time.
|
||||||
|
|
||||||
|
<!-- Please keep the error codes above in alphabetical order -->
|
||||||
|
|
||||||
#### Other error codes
|
#### Other error codes
|
||||||
|
|
||||||
The following error codes are specific to certain endpoints.
|
The following error codes are specific to certain endpoints.
|
||||||
|
|
||||||
<!-- TODO: move them to the endpoints that return them -->
|
<!-- TODO: move them to the endpoints that return them -->
|
||||||
|
|
||||||
`M_UNAUTHORIZED`
|
<!-- Please keep the error codes below in alphabetical order -->
|
||||||
: The request was not correctly authorized. Usually due to login failures.
|
|
||||||
|
|
||||||
`M_USER_DEACTIVATED`
|
`M_BAD_STATE`
|
||||||
: The user ID associated with the request has been deactivated. Typically
|
: The state change requested cannot be performed, such as attempting to
|
||||||
for endpoints that prove authentication, such as [`/login`](#get_matrixclientv3login).
|
unban a user who is not banned.
|
||||||
|
|
||||||
`M_USER_IN_USE`
|
`M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
|
||||||
: Encountered when trying to register a user ID which has been taken.
|
: The user is unable to reject an invite to join the server notices room.
|
||||||
|
See the [Server Notices](#server-notices) module for more information.
|
||||||
|
|
||||||
|
`M_CAPTCHA_INVALID`
|
||||||
|
: The Captcha provided did not match what was expected.
|
||||||
|
|
||||||
|
`M_CAPTCHA_NEEDED`
|
||||||
|
: A Captcha is required to complete the request.
|
||||||
|
|
||||||
|
`M_EXCLUSIVE`
|
||||||
|
: The resource being requested is reserved by an application service, or
|
||||||
|
the application service making the request has not created the resource.
|
||||||
|
|
||||||
|
`M_GUEST_ACCESS_FORBIDDEN`
|
||||||
|
: The room or resource does not permit guests to access it.
|
||||||
|
|
||||||
|
`M_INCOMPATIBLE_ROOM_VERSION`
|
||||||
|
: The client attempted to join a room that has a version the server does
|
||||||
|
not support. Inspect the `room_version` property of the error response
|
||||||
|
for the room's version.
|
||||||
|
|
||||||
|
`M_INVALID_PARAM`
|
||||||
|
: A parameter that was specified has the wrong value. For example, the
|
||||||
|
server expected an integer and instead received a string.
|
||||||
|
|
||||||
|
`M_INVALID_ROOM_STATE`
|
||||||
|
: Sent when the initial state given to the `createRoom` API is invalid.
|
||||||
|
|
||||||
`M_INVALID_USERNAME`
|
`M_INVALID_USERNAME`
|
||||||
: Encountered when trying to register a user ID which is not valid.
|
: Encountered when trying to register a user ID which is not valid.
|
||||||
|
|
||||||
|
`M_MISSING_PARAM`
|
||||||
|
: A required parameter was missing from the request.
|
||||||
|
|
||||||
`M_ROOM_IN_USE`
|
`M_ROOM_IN_USE`
|
||||||
: Sent when the room alias given to the `createRoom` API is already in
|
: Sent when the room alias given to the `createRoom` API is already in
|
||||||
use.
|
use.
|
||||||
|
|
||||||
`M_INVALID_ROOM_STATE`
|
`M_SERVER_NOT_TRUSTED`
|
||||||
: Sent when the initial state given to the `createRoom` API is invalid.
|
: The client's request used a third-party server, e.g. identity server,
|
||||||
|
that this server does not trust.
|
||||||
`M_THREEPID_IN_USE`
|
|
||||||
: Sent when a threepid given to an API cannot be used because the same
|
|
||||||
threepid is already in use.
|
|
||||||
|
|
||||||
`M_THREEPID_NOT_FOUND`
|
|
||||||
: Sent when a threepid given to an API cannot be used because no record
|
|
||||||
matching the threepid was found.
|
|
||||||
|
|
||||||
`M_THREEPID_AUTH_FAILED`
|
`M_THREEPID_AUTH_FAILED`
|
||||||
: Authentication could not be performed on the third-party identifier.
|
: Authentication could not be performed on the third-party identifier.
|
||||||
|
|
@ -223,56 +248,35 @@ matching the threepid was found.
|
||||||
if the server only permits, for example, email addresses from a
|
if the server only permits, for example, email addresses from a
|
||||||
particular domain.
|
particular domain.
|
||||||
|
|
||||||
`M_SERVER_NOT_TRUSTED`
|
`M_THREEPID_IN_USE`
|
||||||
: The client's request used a third-party server, e.g. identity server,
|
: The third party identifier specified by the client is not acceptable because it is
|
||||||
that this server does not trust.
|
already in use in some way.
|
||||||
|
|
||||||
|
`M_THREEPID_MEDIUM_NOT_SUPPORTED`
|
||||||
|
: The homeserver does not support adding a third party identifier of the given medium.
|
||||||
|
|
||||||
|
`M_THREEPID_NOT_FOUND`
|
||||||
|
: Sent when a threepid given to an API cannot be used because no record
|
||||||
|
matching the threepid was found.
|
||||||
|
|
||||||
|
`M_TOO_LARGE`
|
||||||
|
: The request or entity was too large.
|
||||||
|
|
||||||
|
`M_UNAUTHORIZED`
|
||||||
|
: The request was not correctly authorized. Usually due to login failures.
|
||||||
|
|
||||||
`M_UNSUPPORTED_ROOM_VERSION`
|
`M_UNSUPPORTED_ROOM_VERSION`
|
||||||
: The client's request to create a room used a room version that the
|
: The client's request to create a room used a room version that the
|
||||||
server does not support.
|
server does not support.
|
||||||
|
|
||||||
`M_INCOMPATIBLE_ROOM_VERSION`
|
`M_USER_DEACTIVATED`
|
||||||
: The client attempted to join a room that has a version the server does
|
: The user ID associated with the request has been deactivated. Typically
|
||||||
not support. Inspect the `room_version` property of the error response
|
for endpoints that prove authentication, such as [`/login`](#get_matrixclientv3login).
|
||||||
for the room's version.
|
|
||||||
|
|
||||||
`M_BAD_STATE`
|
`M_USER_IN_USE`
|
||||||
: The state change requested cannot be performed, such as attempting to
|
: Encountered when trying to register a user ID which has been taken.
|
||||||
unban a user who is not banned.
|
|
||||||
|
|
||||||
`M_GUEST_ACCESS_FORBIDDEN`
|
<!-- Please keep the error codes above in alphabetical order -->
|
||||||
: The room or resource does not permit guests to access it.
|
|
||||||
|
|
||||||
`M_CAPTCHA_NEEDED`
|
|
||||||
: A Captcha is required to complete the request.
|
|
||||||
|
|
||||||
`M_CAPTCHA_INVALID`
|
|
||||||
: The Captcha provided did not match what was expected.
|
|
||||||
|
|
||||||
`M_MISSING_PARAM`
|
|
||||||
: A required parameter was missing from the request.
|
|
||||||
|
|
||||||
`M_INVALID_PARAM`
|
|
||||||
: A parameter that was specified has the wrong value. For example, the
|
|
||||||
server expected an integer and instead received a string.
|
|
||||||
|
|
||||||
`M_TOO_LARGE`
|
|
||||||
: The request or entity was too large.
|
|
||||||
|
|
||||||
`M_EXCLUSIVE`
|
|
||||||
: The resource being requested is reserved by an application service, or
|
|
||||||
the application service making the request has not created the resource.
|
|
||||||
|
|
||||||
`M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
|
|
||||||
: The user is unable to reject an invite to join the server notices room.
|
|
||||||
See the [Server Notices](#server-notices) module for more information.
|
|
||||||
|
|
||||||
`M_THREEPID_MEDIUM_NOT_SUPPORTED`
|
|
||||||
: The homeserver does not support adding a third party identifier of the given medium.
|
|
||||||
|
|
||||||
`M_THREEPID_IN_USE`
|
|
||||||
: The third party identifier specified by the client is not acceptable because it is
|
|
||||||
already in use in some way.
|
|
||||||
|
|
||||||
#### Rate limiting
|
#### Rate limiting
|
||||||
|
|
||||||
|
|
@ -465,6 +469,8 @@ The flow for auto-discovery is as follows:
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="support" %}}
|
{{% http-api spec="client-server" api="support" %}}
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="policy_server" %}}
|
||||||
|
|
||||||
### API Versions
|
### API Versions
|
||||||
|
|
||||||
Upon connecting, the Matrix client and server need to negotiate which version of the specification
|
Upon connecting, the Matrix client and server need to negotiate which version of the specification
|
||||||
|
|
@ -554,7 +560,7 @@ endpoint.
|
||||||
|
|
||||||
With the OAuth 2.0 API, a client can obtain an access token by using one of the
|
With the OAuth 2.0 API, a client can obtain an access token by using one of the
|
||||||
[grant types](#grant-types) supported by the homeserver and authorizing the
|
[grant types](#grant-types) supported by the homeserver and authorizing the
|
||||||
proper [scope](#scope), as demonstrated in the [login flow](#login-flow). To
|
proper [scope](#scope), as demonstrated in the [login flows](#login-flows). To
|
||||||
invalidate the access token the client must use [token revocation](#token-revocation).
|
invalidate the access token the client must use [token revocation](#token-revocation).
|
||||||
|
|
||||||
### Using access tokens
|
### Using access tokens
|
||||||
|
|
@ -1681,7 +1687,7 @@ For a client to be considered fully OAuth 2.0 aware it MUST:
|
||||||
then the client MUST redirect users to manage their account at the [account
|
then the client MUST redirect users to manage their account at the [account
|
||||||
management URL](#oauth-20-account-management), if available, instead of
|
management URL](#oauth-20-account-management), if available, instead of
|
||||||
providing a native UI using the legacy API endpoints.
|
providing a native UI using the legacy API endpoints.
|
||||||
|
|
||||||
* If the user wishes to deactivate their account then the client MUST refer
|
* If the user wishes to deactivate their account then the client MUST refer
|
||||||
them to the account management URL.
|
them to the account management URL.
|
||||||
* If the user wishes to sign out a device other than its own then the client
|
* If the user wishes to sign out a device other than its own then the client
|
||||||
|
|
@ -1751,19 +1757,31 @@ authentication type.
|
||||||
|
|
||||||
1. [Discover the OAuth 2.0 server metadata](#server-metadata-discovery).
|
1. [Discover the OAuth 2.0 server metadata](#server-metadata-discovery).
|
||||||
2. [Register the client with the homeserver](#client-registration).
|
2. [Register the client with the homeserver](#client-registration).
|
||||||
3. [Obtain an access token](#login-flow) by authorizing a [scope](#scope) for the client with the [authorization code grant](#authorization-code-grant).
|
3. [Obtain an access token](#login-flows) by authorizing a [scope](#scope) for
|
||||||
|
the client with the [authorization code grant](#authorization-code-grant) or
|
||||||
|
[device authorization grant](#device-authorization-grant).
|
||||||
4. [Refresh the access token](#token-refresh-flow) with the [refresh token grant](#refresh-token-grant) when it expires.
|
4. [Refresh the access token](#token-refresh-flow) with the [refresh token grant](#refresh-token-grant) when it expires.
|
||||||
5. [Revoke the tokens](#token-revocation) when the users wants to log out of the client.
|
5. [Revoke the tokens](#token-revocation) when the users wants to log out of the client.
|
||||||
|
|
||||||
#### Login flow
|
#### Login flows
|
||||||
|
|
||||||
Logging in with the OAuth 2.0 API should be done with the [authorization code
|
Logging in and obtaining an access token with the OAuth 2.0 API should be done
|
||||||
grant](#authorization-code-grant). In the context of the Matrix specification,
|
using either the [authorization code grant](#authorization-code-grant) or
|
||||||
this means requesting a [scope](#scope) including full client-server API
|
[device authorization grant](#device-authorization-grant). In the context of the
|
||||||
read/write access and allocating a device ID.
|
Matrix specification, this means requesting a [scope](#scope) including full
|
||||||
|
client-server API read/write access and allocating a device ID.
|
||||||
|
|
||||||
Once the client has retrieved the [server metadata](#server-metadata-discovery),
|
##### Authorization code flow
|
||||||
it needs to generate the following values:
|
|
||||||
|
This login flow uses the [authorization code grant](#authorization-code-grant)
|
||||||
|
and is suitable for clients where the following criteria are met:
|
||||||
|
|
||||||
|
- There is a web browser available for the user to complete authentication and
|
||||||
|
authorization.
|
||||||
|
- The client can receive the callback via a redirect from the web browser.
|
||||||
|
|
||||||
|
Once the client has retrieved the [server metadata](#server-metadata-discovery)
|
||||||
|
the client needs to generate the following values:
|
||||||
|
|
||||||
- `device_id`: a unique identifier for this device; see the
|
- `device_id`: a unique identifier for this device; see the
|
||||||
[`urn:matrix:client:device:<device_id>`](#device-id-allocation) scope token.
|
[`urn:matrix:client:device:<device_id>`](#device-id-allocation) scope token.
|
||||||
|
|
@ -1904,6 +1922,143 @@ Sample response:
|
||||||
Finally, the client can call the [`/whoami`](#get_matrixclientv3accountwhoami)
|
Finally, the client can call the [`/whoami`](#get_matrixclientv3accountwhoami)
|
||||||
endpoint to get the user ID that owns the access token.
|
endpoint to get the user ID that owns the access token.
|
||||||
|
|
||||||
|
##### Device authorization flow
|
||||||
|
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
|
||||||
|
This flow uses the [device authorization grant](#device-authorization-grant) to
|
||||||
|
allow clients to obtain an access token without needing to directly interact
|
||||||
|
with a web browser. Instead, the user completes authorization on a web browser
|
||||||
|
that can be a separate device.
|
||||||
|
|
||||||
|
This is useful for devices with limited input
|
||||||
|
capabilities (such as CLI applications or embedded devices) or where the
|
||||||
|
redirect handling may be unreliable (such as a desktop applications).
|
||||||
|
|
||||||
|
Once the client has retrieved the [server metadata](#server-metadata-discovery)
|
||||||
|
the client needs to generate following value:
|
||||||
|
|
||||||
|
- `device_id`: a unique identifier for this device; see the
|
||||||
|
[`urn:matrix:client:device:<device_id>`](#device-id-allocation) scope token.
|
||||||
|
|
||||||
|
**Device authorization request**
|
||||||
|
|
||||||
|
The client sends a `application/x-www-form-urlencoded` encoded `POST` request to
|
||||||
|
the `device_authorization_endpoint` as defined in
|
||||||
|
[RFC 8628 section 3.1](https://datatracker.ietf.org/doc/html/rfc8628#section-3.1):
|
||||||
|
|
||||||
|
| Parameter | Value |
|
||||||
|
|-------------|----------------------------------------------------------------|
|
||||||
|
| `client_id` | The client ID returned from client registration. |
|
||||||
|
| `scope` | `urn:matrix:client:api:* urn:matrix:client:device:<device_id>` with the `device_id` generated previously. |
|
||||||
|
|
||||||
|
Sample device authorization request:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /oauth2/device HTTP/1.1
|
||||||
|
Host: account.example.com
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
client_id=s6BhdRkqt3&scope=urn%3Amatrix%3Aclient%3Aapi%3A%2A%20urn%3Amatrix%3Aclient%3Adevice%3AAABBBCCCDDD
|
||||||
|
```
|
||||||
|
|
||||||
|
**Device authorization response**
|
||||||
|
|
||||||
|
The server responds with a JSON object as defined in
|
||||||
|
[RFC 8628 section 3.2](https://datatracker.ietf.org/doc/html/rfc8628#section-3.2),
|
||||||
|
containing:
|
||||||
|
|
||||||
|
| Parameter | |
|
||||||
|
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `device_code` | The device verification code. |
|
||||||
|
| `user_code` | An end-user verification code. |
|
||||||
|
| `verification_uri` | The end-user verification URI on the authorization server. |
|
||||||
|
| `verification_uri_complete` | Optionally, the URI which doesn't require the user to manually type the `user_code`, designed for non-textual transmission. |
|
||||||
|
| `expires_in` | The lifetime in seconds of the `device_code` and `user_code`. |
|
||||||
|
| `interval` | The minimum number of seconds the client should wait between polling requests to the token endpoint. If omitted, clients should default to 5. |
|
||||||
|
|
||||||
|
It is RECOMMENDED that the server provides a `verification_uri_complete` such
|
||||||
|
that the user does not need to type in the `user_code`.
|
||||||
|
|
||||||
|
Sample response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
|
||||||
|
"user_code": "WDJB-MJHT",
|
||||||
|
"verification_uri": "https://account.example.com/link",
|
||||||
|
"verification_uri_complete": "https://account.example.com/link?user_code=WDJB-MJHT",
|
||||||
|
"expires_in": 1800,
|
||||||
|
"interval": 5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**User interaction**
|
||||||
|
|
||||||
|
The client conveys the `verification_uri_complete` (and/or `verification_uri`
|
||||||
|
and `user_code`) to the user. How the client does this depends on the
|
||||||
|
specific device characteristics and use case. For example:
|
||||||
|
|
||||||
|
- A CLI application could display the `verification_uri` and `user_code` as text
|
||||||
|
for the user to type into their browser on another device.
|
||||||
|
- An embedded device with a screen could encode the `verification_uri_complete`
|
||||||
|
(with fallback to `verification_uri`) as a QR code for the user to scan with
|
||||||
|
their phone.
|
||||||
|
- A desktop application running on a platform that does not support callbacks
|
||||||
|
could launch the `verification_uri_complete` (with fallback to
|
||||||
|
`verification_uri`) in the system browser.
|
||||||
|
|
||||||
|
The user opens the verification URI in a web browser, which may be on another
|
||||||
|
device, and completes authentication and authorization.
|
||||||
|
|
||||||
|
**Token polling**
|
||||||
|
|
||||||
|
While the user is completing authorization, the client polls the
|
||||||
|
`token_endpoint` for the outcome, at intervals no shorter than the `interval`
|
||||||
|
value from the device authorization response.
|
||||||
|
|
||||||
|
The poll request is a `POST` to the `token_endpoint` with the following
|
||||||
|
parameters, encoded as `application/x-www-form-urlencoded` in the body:
|
||||||
|
|
||||||
|
| Parameter | Value |
|
||||||
|
|---------------|----------------------------------------------------------------|
|
||||||
|
| `grant_type` | `urn:ietf:params:oauth:grant-type:device_code` |
|
||||||
|
| `device_code` | The `device_code` from the device authorization response. |
|
||||||
|
| `client_id` | The client ID returned from client registration. |
|
||||||
|
|
||||||
|
Sample token polling request:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /oauth2/token HTTP/1.1
|
||||||
|
Host: account.example.com
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS&client_id=s6BhdRkqt3
|
||||||
|
```
|
||||||
|
|
||||||
|
The server responds as defined in [RFC 8628 section
|
||||||
|
3.5](https://datatracker.ietf.org/doc/html/rfc8628#section-3.5):
|
||||||
|
|
||||||
|
- While authorization is pending, the server returns an `authorization_pending`
|
||||||
|
error (or `slow_down` if the client is polling too frequently).
|
||||||
|
- If authorization is denied, the server returns an `access_denied` error.
|
||||||
|
- If the device code expires, the server returns an `expired_token` error.
|
||||||
|
- On successful authorization, the server returns a JSON object containing the
|
||||||
|
access token, token type, expiration time, refresh token, and scope:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"access_token": "2YotnFZFEjr1zCsicMWpAA",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 299,
|
||||||
|
"refresh_token": "tGz3JOkF0XG5Qx2TlKWIA",
|
||||||
|
"scope": "urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, the client can call the [`/whoami`](#get_matrixclientv3accountwhoami)
|
||||||
|
endpoint to get the user ID that owns the access token.
|
||||||
|
|
||||||
#### Token refresh flow
|
#### Token refresh flow
|
||||||
|
|
||||||
Refreshing a token with the OAuth 2.0 API should be done with the [refresh token
|
Refreshing a token with the OAuth 2.0 API should be done with the [refresh token
|
||||||
|
|
@ -2234,6 +2389,7 @@ The client must also have obtained a `client_id` by [registering with the server
|
||||||
|
|
||||||
This specification supports the following grant types:
|
This specification supports the following grant types:
|
||||||
- [Authorization code grant](#authorization-code-grant)
|
- [Authorization code grant](#authorization-code-grant)
|
||||||
|
- {{% added-in v="1.18" %}} [Device authorization grant](#device-authorization-grant)
|
||||||
- [Refresh token grant](#refresh-token-grant)
|
- [Refresh token grant](#refresh-token-grant)
|
||||||
|
|
||||||
##### Authorization code grant
|
##### Authorization code grant
|
||||||
|
|
@ -2258,18 +2414,34 @@ To use this grant, homeservers and clients MUST:
|
||||||
Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
|
Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
|
||||||
for clients with an HTTPS redirect URI.
|
for clients with an HTTPS redirect URI.
|
||||||
|
|
||||||
###### User registration
|
##### Device authorization grant
|
||||||
|
|
||||||
Clients can signal to the server that the user desires to register a new account
|
{{% added-in v="1.18" %}}
|
||||||
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
|
As per [RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628), the device
|
||||||
`prompt_values_supported` authorization server metadata.
|
authorization grant lets clients on devices with limited input capabilities
|
||||||
|
obtain an access token by having the user complete authorization on a separate
|
||||||
|
device with a web browser.
|
||||||
|
|
||||||
Servers that support this parameter SHOULD show the account registration UI in
|
This grant requires the client to know the following [authorization server
|
||||||
the browser.
|
metadata](#server-metadata-discovery):
|
||||||
|
|
||||||
|
- `device_authorization_endpoint`
|
||||||
|
|
||||||
|
To use this grant, homeservers and clients MUST:
|
||||||
|
|
||||||
|
- Support the device authorization grant as per
|
||||||
|
[RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628).
|
||||||
|
- Support the [refresh token grant](#refresh-token-grant).
|
||||||
|
|
||||||
|
As with the [authorization code grant](#authorization-code-grant), 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 and refresh
|
||||||
|
token have the same lifetime constraints as described in the [refresh token
|
||||||
|
grant](#refresh-token-grant) section.
|
||||||
|
|
||||||
|
The full flow for using this grant is described in the
|
||||||
|
[device authorization flow](#device-authorization-flow).
|
||||||
|
|
||||||
##### Refresh token grant
|
##### Refresh token grant
|
||||||
|
|
||||||
|
|
@ -2376,6 +2548,22 @@ The server SHOULD return one of the following responses:
|
||||||
- For other errors, the server returns a `400 Bad Request` response with error
|
- For other errors, the server returns a `400 Bad Request` response with error
|
||||||
details
|
details
|
||||||
|
|
||||||
|
#### User registration
|
||||||
|
|
||||||
|
Clients can signal to the server that the user desires to register a new account
|
||||||
|
by initiating the [authorization code grant](#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.
|
||||||
|
|
||||||
|
The `prompt=create` parameter is not supported when using the [device
|
||||||
|
authorization grant](#device-authorization-grant).
|
||||||
|
|
||||||
#### Account management {id="oauth-20-account-management"}
|
#### Account management {id="oauth-20-account-management"}
|
||||||
|
|
||||||
{{% added-in v="1.18" %}}
|
{{% added-in v="1.18" %}}
|
||||||
|
|
@ -4089,6 +4277,7 @@ that profile.
|
||||||
| [Read and Unread Markers](#read-and-unread-markers) | Optional | Optional | Optional | Optional | Optional |
|
| [Read and Unread Markers](#read-and-unread-markers) | Optional | Optional | Optional | Optional | Optional |
|
||||||
| [Guest Access](#guest-access) | Optional | Optional | Optional | Optional | Optional |
|
| [Guest Access](#guest-access) | Optional | Optional | Optional | Optional | Optional |
|
||||||
| [Moderation Policy Lists](#moderation-policy-lists) | Optional | Optional | Optional | Optional | Optional |
|
| [Moderation Policy Lists](#moderation-policy-lists) | Optional | Optional | Optional | Optional | Optional |
|
||||||
|
| [Policy Servers](#policy-servers) | Optional | Optional | Optional | Optional | Optional |
|
||||||
| [OpenID](#openid) | Optional | Optional | Optional | Optional | Optional |
|
| [OpenID](#openid) | Optional | Optional | Optional | Optional | Optional |
|
||||||
| [Recently used emoji](#recently-used-emoji) | Optional | Optional | Optional | Optional | Optional |
|
| [Recently used emoji](#recently-used-emoji) | Optional | Optional | Optional | Optional | Optional |
|
||||||
| [Reference Relations](#reference-relations) | Optional | Optional | Optional | Optional | Optional |
|
| [Reference Relations](#reference-relations) | Optional | Optional | Optional | Optional | Optional |
|
||||||
|
|
@ -4191,6 +4380,7 @@ systems.
|
||||||
{{% cs-module name="Room Upgrades" filename="room_upgrades" %}}
|
{{% cs-module name="Room Upgrades" filename="room_upgrades" %}}
|
||||||
{{% cs-module name="Server Notices" filename="server_notices" %}}
|
{{% cs-module name="Server Notices" filename="server_notices" %}}
|
||||||
{{% cs-module name="Moderation policy lists" filename="moderation_policies" %}}
|
{{% cs-module name="Moderation policy lists" filename="moderation_policies" %}}
|
||||||
|
{{% cs-module name="Policy Servers" filename="policy_servers" %}}
|
||||||
{{% cs-module name="Spaces" filename="spaces" %}}
|
{{% cs-module name="Spaces" filename="spaces" %}}
|
||||||
{{% cs-module name="Event replacements" filename="event_replacements" %}}
|
{{% cs-module name="Event replacements" filename="event_replacements" %}}
|
||||||
{{% cs-module name="Event annotations and reactions" filename="event_annotations" %}}
|
{{% cs-module name="Event annotations and reactions" filename="event_annotations" %}}
|
||||||
|
|
|
||||||
98
content/client-server-api/modules/policy_servers.md
Normal file
98
content/client-server-api/modules/policy_servers.md
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
### Policy Servers
|
||||||
|
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
|
||||||
|
A Policy Server is a homeserver in the room designated to proactively check events
|
||||||
|
before they are sent to the room/users. Rooms are not required to use a Policy
|
||||||
|
Server (PS). Rooms which do use a Policy Server can prevent unwanted events from
|
||||||
|
reaching users.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Room operators might prefer to use a "moderation bot" instead of a Policy Server.
|
||||||
|
Moderation bots are reactive because they typically [redact](#redactions) events
|
||||||
|
after they've already been sent.
|
||||||
|
|
||||||
|
Room operators might also prefer to layer a moderation bot with a Policy Server
|
||||||
|
for added protection.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
A room's Policy Server is designated by the [`m.room.policy`](#mroompolicy) state
|
||||||
|
event described below. If the state event is not set in the room or is missing
|
||||||
|
required fields, the room does *not* use a Policy Server. Similarly, if the server name in the state
|
||||||
|
event has zero joined users in the room, the room also does *not* use a Policy
|
||||||
|
Server.
|
||||||
|
|
||||||
|
When the room is using a Policy Server, *all* events except for the `m.room.policy`
|
||||||
|
state event itself are checked by that Policy Server. This includes membership
|
||||||
|
events, power level changes, events from before the Policy Server was enabled,
|
||||||
|
and non-state or non-empty `state_key` `m.room.policy` events.
|
||||||
|
|
||||||
|
What a Policy Server checks for on an event is left as an implementation detail.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
More information about how a Policy Server operates precisely is available in
|
||||||
|
the [Server-Server API](/server-server-api/#policy-servers). Most notably, not
|
||||||
|
every homeserver is a Policy Server, and not every Policy Server is a full
|
||||||
|
homeserver.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% event event="m.room.policy" %}}
|
||||||
|
|
||||||
|
#### Client behaviour
|
||||||
|
|
||||||
|
Clients do not interact with the Policy Server directly, but may need enough
|
||||||
|
information to be able to set the `m.room.policy` state event. For this, a client
|
||||||
|
can attempt to call [`/.well-known/matrix/policy_server`](#getwell-knownmatrixpolicy_server)
|
||||||
|
on a user-provided server name. The returned information can then be used to
|
||||||
|
populate the `m.room.policy` state event.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Clients are *not* required to use `/.well-known/matrix/policy_server` to populate the
|
||||||
|
`m.room.policy` state event. If they have the required information from elsewhere,
|
||||||
|
they can simply send the state event.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
#### Server behaviour
|
||||||
|
|
||||||
|
See the [Policy Servers section of the Server-Server API](/server-server-api/#policy-servers).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
If implementing your own Policy Server, see [MSC4284: Policy Servers](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/4284-policy-servers.md)
|
||||||
|
for additional security, implementation, and safety considerations.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
#### Security considerations
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Portions of this section rely on context from the [Policy Servers section of the Server-Server API](/server-server-api/#policy-servers).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
By nature of being a proactive tool for a room, Policy Server can expect to be
|
||||||
|
Denial of Service (DoS) targets. Policy Servers MUST be tolerant to DoS attacks.
|
||||||
|
The scale of attack they need to tolerate is left as an implementation/deployment
|
||||||
|
detail. A Policy Server dedicated to a small community might not have the same
|
||||||
|
requirements as a Policy Server available for many communities to use.
|
||||||
|
|
||||||
|
To help ensure that rooms can be used when their chosen Policy Server is inaccessible,
|
||||||
|
the `m.room.policy` state event can be set *without* consulting the Policy Server.
|
||||||
|
This in effect allows users with appropriate power levels to wipe the content of
|
||||||
|
`m.room.policy`, disabling the Policy Server immediately.
|
||||||
|
|
||||||
|
Policy Servers MUST have a joined user in the room to prevent rooms overloading
|
||||||
|
or forcing a given server to act as a Policy Server. The Policy Server can evict
|
||||||
|
itself from the room to also disable usage immediately.
|
||||||
|
|
||||||
|
Events sent "before" the Policy Server was enabled can end up being recommended
|
||||||
|
for exclusion by the Policy Server. This is expected behaviour to ensure new policies
|
||||||
|
apply to events which took a while to send.
|
||||||
|
|
||||||
|
Homeservers might not ask a Policy Server for a signature on an event before sending
|
||||||
|
it to the room. Other compliant homeservers will request that signature instead,
|
||||||
|
and layered tooling (like "moderation bots") can help remove events which bypass
|
||||||
|
the room's Policy Server, if desirable.
|
||||||
|
|
||||||
|
Homeservers might request and receive a valid signature for an event, but delay
|
||||||
|
or never send the event. "Moderation bots" can monitor for clock drift on signed
|
||||||
|
events, if desirable. A Policy Server implementation might also monitor for clock
|
||||||
|
drift, though does need to consider that events can be backdated in ways beyond
|
||||||
|
`origin_server_ts`.
|
||||||
|
|
@ -70,26 +70,7 @@ the keys `error` and `errcode` MUST always be present.
|
||||||
|
|
||||||
Some standard error codes are below:
|
Some standard error codes are below:
|
||||||
|
|
||||||
`M_NOT_FOUND`
|
<!-- Please keep the error codes below in alphabetical order -->
|
||||||
: The resource requested could not be located.
|
|
||||||
|
|
||||||
`M_MISSING_PARAMS`
|
|
||||||
: The request was missing one or more parameters.
|
|
||||||
|
|
||||||
`M_INVALID_PARAM`
|
|
||||||
: The request contained one or more invalid parameters.
|
|
||||||
|
|
||||||
`M_SESSION_NOT_VALIDATED`
|
|
||||||
: The session has not been validated.
|
|
||||||
|
|
||||||
`M_NO_VALID_SESSION`
|
|
||||||
: A session could not be located for the given parameters.
|
|
||||||
|
|
||||||
`M_SESSION_EXPIRED`
|
|
||||||
: The session has expired and must be renewed.
|
|
||||||
|
|
||||||
`M_INVALID_EMAIL`
|
|
||||||
: The email address provided was not valid.
|
|
||||||
|
|
||||||
`M_EMAIL_SEND_ERROR`
|
`M_EMAIL_SEND_ERROR`
|
||||||
: There was an error sending an email. Typically seen when attempting to
|
: There was an error sending an email. Typically seen when attempting to
|
||||||
|
|
@ -98,10 +79,39 @@ verify ownership of a given email address.
|
||||||
`M_INVALID_ADDRESS`
|
`M_INVALID_ADDRESS`
|
||||||
: The provided third-party address was not valid.
|
: The provided third-party address was not valid.
|
||||||
|
|
||||||
|
`M_INVALID_EMAIL`
|
||||||
|
: The email address provided was not valid.
|
||||||
|
|
||||||
|
`M_INVALID_PARAM`
|
||||||
|
: The request contained one or more invalid parameters.
|
||||||
|
|
||||||
|
`M_MISSING_PARAMS`
|
||||||
|
: The request was missing one or more parameters.
|
||||||
|
|
||||||
|
`M_NO_VALID_SESSION`
|
||||||
|
: A session could not be located for the given parameters.
|
||||||
|
|
||||||
|
`M_NOT_FOUND`
|
||||||
|
: The resource requested could not be located.
|
||||||
|
|
||||||
`M_SEND_ERROR`
|
`M_SEND_ERROR`
|
||||||
: There was an error sending a notification. Typically seen when
|
: There was an error sending a notification. Typically seen when
|
||||||
attempting to verify ownership of a given third-party address.
|
attempting to verify ownership of a given third-party address.
|
||||||
|
|
||||||
|
`M_SESSION_EXPIRED`
|
||||||
|
: The session has expired and must be renewed.
|
||||||
|
|
||||||
|
`M_SESSION_NOT_VALIDATED`
|
||||||
|
: The session has not been validated.
|
||||||
|
|
||||||
|
`M_THREEPID_IN_USE`
|
||||||
|
: The third-party identifier is already in use by another user. Typically
|
||||||
|
this error will have an additional `mxid` property to indicate who owns
|
||||||
|
the third-party identifier.
|
||||||
|
|
||||||
|
`M_UNKNOWN`
|
||||||
|
: An unknown error has occurred.
|
||||||
|
|
||||||
`M_UNRECOGNIZED`
|
`M_UNRECOGNIZED`
|
||||||
: The request contained an unrecognised value, such as an unknown token or
|
: The request contained an unrecognised value, such as an unknown token or
|
||||||
medium.
|
medium.
|
||||||
|
|
@ -111,13 +121,7 @@ This is expected to be returned with a 404 HTTP status code if the endpoint is
|
||||||
not implemented or a 405 HTTP status code if the endpoint is implemented, but
|
not implemented or a 405 HTTP status code if the endpoint is implemented, but
|
||||||
the incorrect HTTP method is used.
|
the incorrect HTTP method is used.
|
||||||
|
|
||||||
`M_THREEPID_IN_USE`
|
<!-- Please keep the error codes above in alphabetical order -->
|
||||||
: The third-party identifier is already in use by another user. Typically
|
|
||||||
this error will have an additional `mxid` property to indicate who owns
|
|
||||||
the third-party identifier.
|
|
||||||
|
|
||||||
`M_UNKNOWN`
|
|
||||||
: An unknown error has occurred.
|
|
||||||
|
|
||||||
## Privacy
|
## Privacy
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,9 @@ server must ensure that the event:
|
||||||
otherwise it is rejected.
|
otherwise it is rejected.
|
||||||
6. Passes authorization rules based on the current state of the room,
|
6. Passes authorization rules based on the current state of the room,
|
||||||
otherwise it is "soft failed".
|
otherwise it is "soft failed".
|
||||||
|
7. {{% added-in v="1.18" %}} Is [validated](#validating-policy-server-signatures)
|
||||||
|
by the Policy Server, if the room is [using a Policy Server](#determining-if-a-policy-server-is-enabled-in-a-room),
|
||||||
|
otherwise it is "soft failed".
|
||||||
|
|
||||||
Further details of these checks, and how to handle failures, are
|
Further details of these checks, and how to handle failures, are
|
||||||
described below.
|
described below.
|
||||||
|
|
@ -689,6 +692,11 @@ then any new event `D'` will not reference `C`:
|
||||||
|
|
|
|
||||||
D'
|
D'
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
Events can also be soft failed if they fail [Policy Server checks](#validating-policy-server-signatures).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
#### Retrieving event authorization information
|
#### Retrieving event authorization information
|
||||||
|
|
||||||
The homeserver may be missing event authorization information, or wish
|
The homeserver may be missing event authorization information, or wish
|
||||||
|
|
@ -1277,6 +1285,171 @@ endpoint MUST be protected as follows:
|
||||||
room ID MUST be ignored if the sending server is denied access to
|
room ID MUST be ignored if the sending server is denied access to
|
||||||
the room identified by that ID.
|
the room identified by that ID.
|
||||||
|
|
||||||
|
The following endpoints MAY be protected:
|
||||||
|
|
||||||
|
- [`/_matrix/policy/v1/sign`](#post_matrixpolicyv1sign) - {{< added-in v="1.18" >}}
|
||||||
|
Protected if the server is tracking the DAG and chooses to enforce the ACL.
|
||||||
|
|
||||||
|
|
||||||
|
## Policy Servers
|
||||||
|
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
|
||||||
|
Policy Servers are an available tool for rooms to add proactive protections. Rooms
|
||||||
|
which use a Policy Server (PS) can prevent unwanted events from reaching users. Rooms
|
||||||
|
are not required to use a Policy Server, and can disable it any time after enabling
|
||||||
|
it.
|
||||||
|
|
||||||
|
For a homeserver to be a Policy Server, it MUST implement the following functionality
|
||||||
|
of the Server-Server API:
|
||||||
|
|
||||||
|
* [Normal server name resolution](#resolving-server-names).
|
||||||
|
* [Publishing a signing key](#publishing-keys).
|
||||||
|
* [Request authentication](#authentication).
|
||||||
|
* Being able to [make and send join requests](#joining-rooms).
|
||||||
|
* Receiving and processing [`POST /_matrix/policy/v1/sign`](#post_matrixpolicyv1sign)
|
||||||
|
requests.
|
||||||
|
|
||||||
|
All other functionality and endpoints are optional for a Policy Server.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Though a Policy Server is not required to implement the full Server-Server API
|
||||||
|
surface, some functionality may be desirable to implement anyway:
|
||||||
|
|
||||||
|
* Receiving [invites](#inviting-to-a-room) can make it easier to add the Policy
|
||||||
|
Server to a room.
|
||||||
|
* Receiving [transactions](#transactions) is recommended to avoid remote servers
|
||||||
|
flagging the Policy Server as "offline", even if the contents are discarded.
|
||||||
|
* Receiving [device lookups](#get_matrixfederationv1userdevicesuserid) can also
|
||||||
|
help reduce remote servers flagging the Policy Server as "offline".
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Policy Servers are *not* required to track the DAG for a room. Policy Servers
|
||||||
|
might be optimized for content moderation and therefore do not need knowledge of
|
||||||
|
the DAG.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
### Determining if a Policy Server is enabled in a room
|
||||||
|
|
||||||
|
For a room to be considered as "using" a Policy Server, *all* of the following
|
||||||
|
conditions MUST be true:
|
||||||
|
|
||||||
|
* The *current state* for the room has a valid [`m.room.policy`](/client-server-api/#mroompolicy)
|
||||||
|
state event with empty state key. Valid means `content` contains at least:
|
||||||
|
* A string value for `via`.
|
||||||
|
* An object value for `public_keys` containing at least a string value for
|
||||||
|
`ed25519`.
|
||||||
|
* The server name denoted by the `m.room.policy` state event's `via` has at least
|
||||||
|
one joined user in the room in *current state*. The user does not need any
|
||||||
|
special permissions or power levels in the room.
|
||||||
|
|
||||||
|
If a room has enabled a Policy Server, *all* servers in that room MUST [ask that
|
||||||
|
Policy Server](#asking-for-a-policy-server-signature-on-an-event) for a signature
|
||||||
|
before sending an event. If the Policy Server refuses to sign the event being
|
||||||
|
sent, servers SHOULD fail to send that event as per the [validation rules](#validating-policy-server-signatures).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
"Current state" shares the same definition as [soft failure](#soft-failure).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Policy Servers MUST have at least one joined user in the room to give the Policy
|
||||||
|
Server agency in whether it serves that role for the room. Otherwise, a room
|
||||||
|
would be able to force a Policy Server to participate and then overwhelm it.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
### Validating Policy Server signatures
|
||||||
|
|
||||||
|
Policy Servers use signatures to indicate whether an event was checked and is
|
||||||
|
recommended for inclusion in a room. The Policy Server's recommendation does *not*
|
||||||
|
affect the authorization rules for an event, but does affect whether homeservers
|
||||||
|
[soft fail](#soft-failure) or refuse to actually go forward with sending an event.
|
||||||
|
|
||||||
|
If a room has disabled (or never enabled) a Policy Server, events are recommended
|
||||||
|
for inclusion and subject to normal authorization rules.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Because the Policy Server is not asked to sign [`m.room.policy`](/client-server-api/#mroompolicy)
|
||||||
|
state events with empty string `state_key`s, those events will not have a Policy
|
||||||
|
Server signature. Those events are by default recommended for inclusion and still
|
||||||
|
subject to normal authorization rules.
|
||||||
|
|
||||||
|
All other events SHOULD have a valid Policy Server signature when a Policy Server
|
||||||
|
is enabled in the room, including non-state `m.room.policy` events and `m.room.policy`
|
||||||
|
state events with non-empty `state_key`s. This also includes state events like
|
||||||
|
membership and power level changes.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
If a room has enabled a Policy Server, the Policy Server's signature appears
|
||||||
|
alongside the normal [event signatures](#signing-events), though uses a public
|
||||||
|
key from the room's `m.room.policy` state event.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Currently, only Ed25519 keys are supported by homeservers. The Key ID for the
|
||||||
|
`ed25519` key in `m.room.policy` is *always* `ed25519:policy_server`.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
By embedding the Policy Server's public key into room state, the Policy Server
|
||||||
|
does not need to be online or have its keys cached by a notary in order to validate
|
||||||
|
an event.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
The Policy Server's [published signing key](#publishing-keys) SHOULD NOT be the
|
||||||
|
same key contained in the `m.room.policy` state event. This is to keep "can send
|
||||||
|
federation traffic" and "can recommend events for inclusion" separate, and to
|
||||||
|
allow rooms to revoke the Policy Server's key without cooperation of the Policy
|
||||||
|
Server.
|
||||||
|
|
||||||
|
If the Policy Server is acting as a normal homeserver and attempting to send an
|
||||||
|
event, that event will require a signature from the server's published signing
|
||||||
|
key alongside the Policy Server signature described in this section.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
If the Policy Server's signature is valid, the event is recommended for inclusion
|
||||||
|
in the room, and is still subject to normal authorization rules.
|
||||||
|
|
||||||
|
If the Policy Server's signature is invalid or missing, the homeserver SHOULD
|
||||||
|
[ask for a new signature](#asking-for-a-policy-server-signature-on-an-event). If
|
||||||
|
the event still does not have a valid Policy Server signature, the event is *not*
|
||||||
|
recommended for inclusion and the homeserver SHOULD:
|
||||||
|
|
||||||
|
* If applicable, reject the Client-Server API request which was generating the
|
||||||
|
event. If the Policy Server returned an error, that error SHOULD be provided
|
||||||
|
to the client verbatim. The event the client was attempting to send SHOULD be
|
||||||
|
discarded and not processed/sent any further.
|
||||||
|
* If the event was received over federation or the homeserver sends a local client's
|
||||||
|
event anyway, [soft fail](#soft-failure) the event.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
For clarity, an event which lacks a valid Policy Server signature is still subject
|
||||||
|
to normal authorization rules.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
When a Policy Server's signature is invalid, a new one is requested because the
|
||||||
|
Policy Server's key may have rotated between the event being signed and the event
|
||||||
|
being checked.
|
||||||
|
|
||||||
|
Because the key is contained in the `m.room.policy` state event, if the Policy
|
||||||
|
Server rotates its key without the room also updating the state event, events
|
||||||
|
will be flagged as not recommended for inclusion. This is expected behaviour.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
### Asking for a Policy Server signature on an event
|
||||||
|
|
||||||
|
Per [above](#determining-if-a-policy-server-is-enabled-in-a-room), if a room has
|
||||||
|
a Policy Server enabled, *all* servers in the room MUST ask the Policy Server to
|
||||||
|
sign their events before sending them to clients and servers.
|
||||||
|
|
||||||
|
After asking for a signature, homeservers SHOULD [validate](#validating-policy-server-signatures)
|
||||||
|
the returned signature before continuing to send events. If the Policy Server
|
||||||
|
returns an error, the event SHOULD NOT be sent to clients and servers.
|
||||||
|
|
||||||
|
{{% http-api spec="server-server" api="room_policy" %}}
|
||||||
|
|
||||||
## Signing Events
|
## Signing Events
|
||||||
|
|
||||||
Signing events is complicated by the fact that servers can choose to
|
Signing events is complicated by the fact that servers can choose to
|
||||||
|
|
@ -1300,6 +1473,12 @@ The signature is then copied back to the original event object.
|
||||||
For an example of a signed event, see the [room version
|
For an example of a signed event, see the [room version
|
||||||
specification](/rooms).
|
specification](/rooms).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
Events sent in rooms with [Policy Servers](#policy-servers) MUST [ask](#asking-for-a-policy-server-signature-on-an-event)
|
||||||
|
the Policy Server for a signature too.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
### Validating hashes and signatures on received events
|
### Validating hashes and signatures on received events
|
||||||
|
|
||||||
When a server receives an event over federation from another server, the
|
When a server receives an event over federation from another server, the
|
||||||
|
|
@ -1334,6 +1513,12 @@ only been given a redacted version of the event. To enforce this, the
|
||||||
receiving server should use the redacted copy it calculated rather than
|
receiving server should use the redacted copy it calculated rather than
|
||||||
the full copy it received.
|
the full copy it received.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.18" %}}
|
||||||
|
Events sent in rooms with [Policy Servers](#policy-servers) have [additional](#validating-policy-server-signatures)
|
||||||
|
signature validation requirements.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
### Calculating the reference hash for an event
|
### Calculating the reference hash for an event
|
||||||
|
|
||||||
The *reference hash* of an event covers the essential fields of an
|
The *reference hash* of an event covers the essential fields of an
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,7 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
description: |-
|
description: |-
|
||||||
URL of the token endpoint, necessary to use the authorization code grant and
|
URL of the token endpoint, used by the grants.
|
||||||
the refresh token grant.
|
|
||||||
revocation_endpoint:
|
revocation_endpoint:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
|
|
@ -101,6 +100,10 @@ paths:
|
||||||
This array MUST contain at least the `authorization_code` and `refresh_token`
|
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
|
values, for clients to be able to use the authorization code grant and refresh
|
||||||
token grant, respectively.
|
token grant, respectively.
|
||||||
|
|
||||||
|
{{% added-in v="1.18" %}} It MAY also contain
|
||||||
|
`urn:ietf:params:oauth:grant-type:device_code` to indicate support for the
|
||||||
|
[device authorization grant](/client-server-api/#device-authorization-grant).
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
description: A grant type that the server supports.
|
description: A grant type that the server supports.
|
||||||
|
|
@ -165,6 +168,14 @@ paths:
|
||||||
- "org.matrix.account_deactivate"
|
- "org.matrix.account_deactivate"
|
||||||
- "org.matrix.cross_signing_reset"
|
- "org.matrix.cross_signing_reset"
|
||||||
description: An action that the account management URL supports.
|
description: An action that the account management URL supports.
|
||||||
|
device_authorization_endpoint:
|
||||||
|
x-addedInMatrixVersion: "1.18"
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: |-
|
||||||
|
URL of the device authorization endpoint, as defined in
|
||||||
|
[RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628), necessary to use
|
||||||
|
the [device authorization grant](/client-server-api/#device-authorization-grant).
|
||||||
required:
|
required:
|
||||||
- issuer
|
- issuer
|
||||||
- authorization_endpoint
|
- authorization_endpoint
|
||||||
|
|
@ -180,9 +191,10 @@ paths:
|
||||||
"authorization_endpoint": "https://account.example.com/oauth2/auth",
|
"authorization_endpoint": "https://account.example.com/oauth2/auth",
|
||||||
"token_endpoint": "https://account.example.com/oauth2/token",
|
"token_endpoint": "https://account.example.com/oauth2/token",
|
||||||
"registration_endpoint": "https://account.example.com/oauth2/clients/register",
|
"registration_endpoint": "https://account.example.com/oauth2/clients/register",
|
||||||
|
"device_authorization_endpoint": "https://account.example.com/oauth2/device",
|
||||||
"revocation_endpoint": "https://account.example.com/oauth2/revoke",
|
"revocation_endpoint": "https://account.example.com/oauth2/revoke",
|
||||||
"response_types_supported": ["code"],
|
"response_types_supported": ["code"],
|
||||||
"grant_types_supported": ["authorization_code", "refresh_token"],
|
"grant_types_supported": ["authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:device_code"],
|
||||||
"response_modes_supported": ["query", "fragment"],
|
"response_modes_supported": ["query", "fragment"],
|
||||||
"code_challenge_methods_supported": ["S256"],
|
"code_challenge_methods_supported": ["S256"],
|
||||||
"account_management_uri": "https://account.example.com/manage",
|
"account_management_uri": "https://account.example.com/manage",
|
||||||
|
|
|
||||||
82
data/api/client-server/policy_server.yaml
Normal file
82
data/api/client-server/policy_server.yaml
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Copyright 2026 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 Policy Server Discovery API
|
||||||
|
version: 1.0.0
|
||||||
|
paths:
|
||||||
|
/matrix/policy_server:
|
||||||
|
get:
|
||||||
|
summary: Gets information about a Policy Server's configuration, if available.
|
||||||
|
description: |-
|
||||||
|
Gets public key information for a [Policy Server](/client-server-api/#policy-servers).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Like the [well-known discovery URI](/client-server-api/#well-known-uris),
|
||||||
|
this endpoint should be accessed with the hostname of the Policy Server's
|
||||||
|
[server name](/appendices/#server-name) by making a
|
||||||
|
GET request to `https://hostname/.well-known/matrix/policy_server`.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
Note that this endpoint is not necessarily handled by the homeserver or
|
||||||
|
Policy Server. It may be served by another webserver.
|
||||||
|
operationId: getWellknownPolicy
|
||||||
|
x-addedInMatrixVersion: "1.18"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: |-
|
||||||
|
Public keys for the Policy Server. Can be supplied to the [`m.room.policy`](/client-server-api/#mroompolicy)
|
||||||
|
state event.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
public_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
The unpadded base64-encoded public keys for the Policy Server. MUST contain
|
||||||
|
at least `ed25519`.
|
||||||
|
properties:
|
||||||
|
ed25519:
|
||||||
|
type: string
|
||||||
|
description: The unpadded base64-encoded ed25519 public key for the Policy Server.
|
||||||
|
required: ['ed25519']
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: The unpadded base64-encoded public key for the key algorithm.
|
||||||
|
required: ["public_keys"]
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"public_keys": {
|
||||||
|
"ed25519": "6yhHGKhCiXTSEN2ksjV7kX_N6rBQZ3Xb-M7LlC6NS-s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"404":
|
||||||
|
description: No policy server information available.
|
||||||
|
tags:
|
||||||
|
- Server administration
|
||||||
|
servers:
|
||||||
|
- url: "{protocol}://{hostname}{basePath}"
|
||||||
|
variables:
|
||||||
|
protocol:
|
||||||
|
enum:
|
||||||
|
- https
|
||||||
|
default: https
|
||||||
|
hostname:
|
||||||
|
default: localhost:8008
|
||||||
|
basePath:
|
||||||
|
default: /.well-known
|
||||||
172
data/api/server-server/room_policy.yaml
Normal file
172
data/api/server-server/room_policy.yaml
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
# Copyright 2026 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 Federation Room Policy API
|
||||||
|
version: 1.0.0
|
||||||
|
paths:
|
||||||
|
"/sign":
|
||||||
|
post:
|
||||||
|
summary: Asks the Policy Server to sign an event.
|
||||||
|
description: |-
|
||||||
|
A server is a Policy Server if it implements this endpoint, among
|
||||||
|
[other requirements](/server-server-api/#policy-servers). This endpoint
|
||||||
|
is otherwise optional. See [Unsupported Endpoints](/server-server-api/#unsupported-endpoints)
|
||||||
|
for details on how to exclude implementation of this endpoint.
|
||||||
|
|
||||||
|
This endpoint MUST NOT be called for events which have a type of `m.room.policy`
|
||||||
|
and an empty string `state_key`. All other events, including state events,
|
||||||
|
non-state `m.room.policy` events, and `m.room.policy` state events with
|
||||||
|
non-empty string `state_key`s are processed by this endpoint.
|
||||||
|
|
||||||
|
Whether a signature is required by a Policy Server further depends on whether
|
||||||
|
the room has [enabled a Policy Server](#determining-if-a-policy-server-is-enabled-in-a-room).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
The Policy Server MAY respond with *any* of the defined errors to indicate
|
||||||
|
failure. For example, if it wishes to hide whether it knows about a room,
|
||||||
|
it MAY return `400 M_FORBIDDEN` instead (or, it MAY sign the event anyway).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
What the Policy Server checks for when calling this endpoint is left as an
|
||||||
|
implementation detail.
|
||||||
|
operationId: askPolicyServerToSign
|
||||||
|
security:
|
||||||
|
- signedRequest: []
|
||||||
|
parameters: []
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The [PDU](/server-server-api/#pdus) to request a signature for. The event format
|
||||||
|
varies depending on the room version - check the [room version specification](/rooms)
|
||||||
|
for precise event formats.
|
||||||
|
properties: {}
|
||||||
|
example:
|
||||||
|
$ref: examples/minimal_pdu.json
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: |-
|
||||||
|
The Policy Server has signed the event, indicating that it recommends the event for
|
||||||
|
inclusion in the room. Only the Policy Server's signature is returned. This signature
|
||||||
|
is to be added to the event before sending or processing the event further.
|
||||||
|
|
||||||
|
`ed25519:policy_server` is *always* used for Ed25519 signatures.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
required: []
|
||||||
|
example: {
|
||||||
|
"policy.example.org": {
|
||||||
|
"ed25519:policy_server": "zLFxllD0pbBuBpfHh8NuHNaICpReF/PAOpUQTsw+bFGKiGfDNAsnhcP7pbrmhhpfbOAxIdLraQLeeiXBryLmBw"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"429":
|
||||||
|
$ref: '#/components/responses/rateLimited'
|
||||||
|
"400":
|
||||||
|
description: |-
|
||||||
|
The request is invalid or the Policy Server refuses to sign the event.
|
||||||
|
|
||||||
|
Error codes include:
|
||||||
|
* `M_BAD_JSON` - The supplied PDU-formatted event was improperly formatted. For example,
|
||||||
|
missing keys required for the room version.
|
||||||
|
* `M_NOT_JSON` - The body wasn't JSON.
|
||||||
|
* `M_FORBIDDEN` - The Policy Server refuses to sign the event.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
# XXX: We should move error definitions into a more generic place.
|
||||||
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "The message appears to contain possible spam"
|
||||||
|
}
|
||||||
|
"403":
|
||||||
|
description: |-
|
||||||
|
The calling server is [ACL'd](/server-server-api/#server-access-control-lists-acls).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
This endpoint is optionally affected by server ACLs. The Policy Server
|
||||||
|
MAY NOT apply an ACL to the request, especially if the Policy Server
|
||||||
|
is not tracking the room DAG.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
# XXX: We should move error definitions into a more generic place.
|
||||||
|
- $ref: ../client-server/definitions/errors/error.yaml
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
errcode:
|
||||||
|
description: "The `M_FORBIDDEN` error code."
|
||||||
|
required: [errcode]
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "Your server is not allowed to request a signature."
|
||||||
|
}
|
||||||
|
"404":
|
||||||
|
description: |-
|
||||||
|
The server is not a Policy Server, or the room is unknown/not protected by the Policy Server.
|
||||||
|
|
||||||
|
Error codes include:
|
||||||
|
* `M_NOT_FOUND` - The room is not known or is not protected by the Policy Server.
|
||||||
|
* `M_UNRECOGNIZED` - The server is not a Policy Server. See [Unsupported Endpoints](/server-server-api/#unsupported-endpoints)
|
||||||
|
for more detail.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
# XXX: We should move error definitions into a more generic place.
|
||||||
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value: {
|
||||||
|
"errcode": "M_NOT_FOUND",
|
||||||
|
"error": "Unknown room"
|
||||||
|
}
|
||||||
|
servers:
|
||||||
|
- url: "{protocol}://{hostname}{basePath}"
|
||||||
|
variables:
|
||||||
|
protocol:
|
||||||
|
enum:
|
||||||
|
- http
|
||||||
|
- https
|
||||||
|
default: https
|
||||||
|
hostname:
|
||||||
|
default: localhost:8448
|
||||||
|
basePath:
|
||||||
|
default: /_matrix/policy/v1
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
signedRequest:
|
||||||
|
$ref: definitions/security.yaml#/signedRequest
|
||||||
|
responses:
|
||||||
|
rateLimited:
|
||||||
|
description: This request was rate-limited.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
# XXX: We should move error definitions into a more generic place.
|
||||||
|
$ref: ../client-server/definitions/errors/rate_limited.yaml
|
||||||
|
|
||||||
11
data/event-schemas/examples/m.room.policy.yaml
Normal file
11
data/event-schemas/examples/m.room.policy.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"$ref": "core/state_event.json",
|
||||||
|
"type": "m.room.policy",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"via": "policy.example.org",
|
||||||
|
"public_keys": {
|
||||||
|
"ed25519": "6yhHGKhCiXTSEN2ksjV7kX_N6rBQZ3Xb-M7LlC6NS-s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
data/event-schemas/schema/m.room.policy.yaml
Normal file
41
data/event-schemas/schema/m.room.policy.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
$schema: https://json-schema.org/draft/2020-12/schema
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/state_event.yaml
|
||||||
|
description: |-
|
||||||
|
A [Policy Server](/client-server-api/#policy-servers) configuration. If invalid
|
||||||
|
or not set, the room does not use a Policy Server.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
via:
|
||||||
|
description: |-
|
||||||
|
The server name to use as a Policy Server. MUST have a joined user in
|
||||||
|
the room.
|
||||||
|
type: string
|
||||||
|
public_keys:
|
||||||
|
description: |-
|
||||||
|
The unpadded base64-encoded public keys for the Policy Server. MUST contain at
|
||||||
|
least `ed25519`.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
ed25519:
|
||||||
|
type: string
|
||||||
|
description: The unpadded base64-encoded ed25519 public key for the Policy Server.
|
||||||
|
required: ['ed25519']
|
||||||
|
additionalProperties:
|
||||||
|
description: The unpadded base64-encoded public key for the key algorithm.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- via
|
||||||
|
- public_keys
|
||||||
|
state_key:
|
||||||
|
description: An empty string.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.room.policy
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
Loading…
Reference in a new issue