From a2e9656847f159b7a7eae287e7d7807589d5a333 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 14 Jan 2021 18:12:28 +0100 Subject: [PATCH 01/31] API Scopes MSC --- proposals/2967-api-scopes.md | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 proposals/2967-api-scopes.md diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md new file mode 100644 index 00000000000..7329f3b2b49 --- /dev/null +++ b/proposals/2967-api-scopes.md @@ -0,0 +1,74 @@ +# MSC2967: API scope restriction + +When a user logs in with a Matrix client, it gives this client full access to their Matrix account. + +This introduces scopes to allow restricting client access to only part of the Matrix client API. + +## Proposal + +The [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of OAuth 2.0 to authenticate against a Matrix server. +OAuth 2.0 grants have scopes associated to them and encourage to ask for user consent when a client asks for a new scope that was not granted before. + +This MSC does not attempt to define all the scopes necessary to cover the whole API, but lays out a base for that. + +### Format + +URN are widely used formats for OAuth 2.0 scopes. +All scopes related to Matrix must therefore start with `urn:matrix:`. + +Calls to the Matrix client API, excluding calls that need UIA, must be restricted by scopes prefixed by `urn:matrix:api:`. +Calls to endpoints that currently need User-Interactive Authentication (UIA) must be restricted by scopes prefixed by `urn:matrix:sudo:`. + +Protected resource can have both `read` and `write` operations. +`write` access to a resource implies `read` access to it. +Access to those operations are specified as the scope suffix, e.g. `urn:matrix:api:[resource]:read`. + +### Globs + +Scopes used by the Matrix client API support wildcard globs. +`urn:matrix:api:*` gives full access to the API (excluding UIA). +`urn:matrix:api:*:read` gives read-only access to the API. +Access to the `urn:matrix:sudo:*` can be time-restricted and require user re-authentication for sensitive operations. + +Top-level wildcards (`urn:matrix:*` or `*`) are not valid and must be rejected by the authentication server. +Wildcards can only replace URN segments, e.g. `urn:matrix:a*` is invalid. + +### Exact scopes + +The exact scopes are intentionally not specified in this MSC. +The glob mechanism allows to the existing behaviour during a transition period while allowing further MSCs that introduces those exact scopes. + +### Device handling + +With the pre-MSC2964 authentication mechanism, a `device_id` was associated with the access token. +Since there are no such thing as a session in OAuth 2.0, this can be hardly mapped like this. + +`device_id` can be bound to a client session via a scope with this format: `urn:matrix:device:[device_id]`. +If the client does not ask such a scope during the initial login, the authentication server must generate a new `device_id` and give it as a granted scope to the client. +A client can adopt and rehydrate an existing client by asking for its scope on login. +This also has a nice side-effect: if the device asked was never used by the client making the request, the authorization server will ask for explicit consent from the user. + +The authentication server must only grant exactly one device scope for a token. +Wildcards are not allowed under the `urn:matrix:device:` prefix. + +## Potential issues + +The Device ID handling involves some custom logic on the authorization server side. +This means the Matrix server must be involved at some point in the authorization logic, which also involves implementation-specific code for each Matrix server implementation and OAuth 2.0 authentication server implementation. +This is not a problem when the Matrix server acts as the authorization server. + +## Alternatives + +Scope format could also have an URL format, e.g. `https://matrix.org/api/*/read`. +The URL prefix could either be static (`https://matrix.org`) or dependant on the homeserver (`https://matrix.example.com`). +In both cases, the URL could be confused with API endpoints and in the second case it would require discovery to know what scopes to ask. + +The actual prefix as well as the `:api:`, `:sudo:` and `:device:` URN parts are open to debate. + +## Security considerations + +TBD + +## Unstable prefix + +None relevant. From 544d75b413277f14393a635ea17be3d0d49529c5 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 16 May 2022 16:30:14 +0100 Subject: [PATCH 02/31] Proposed insufficient privilege response format --- proposals/2967-api-scopes.md | 56 ++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 7329f3b2b49..6175c8586f1 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -2,7 +2,7 @@ When a user logs in with a Matrix client, it gives this client full access to their Matrix account. -This introduces scopes to allow restricting client access to only part of the Matrix client API. +This proposal introduces access scopes to allow restricting client access to only part(s) of the Matrix client API. ## Proposal @@ -11,7 +11,9 @@ OAuth 2.0 grants have scopes associated to them and encourage to ask for user co This MSC does not attempt to define all the scopes necessary to cover the whole API, but lays out a base for that. -### Format +Additionally it is proposed that a standard approach to error response representation is adopted across the API. This could replace the UIA based responses that exist on some API endpoints today. + +### Scope format URN are widely used formats for OAuth 2.0 scopes. All scopes related to Matrix must therefore start with `urn:matrix:`. @@ -23,7 +25,7 @@ Protected resource can have both `read` and `write` operations. `write` access to a resource implies `read` access to it. Access to those operations are specified as the scope suffix, e.g. `urn:matrix:api:[resource]:read`. -### Globs +#### Globs Scopes used by the Matrix client API support wildcard globs. `urn:matrix:api:*` gives full access to the API (excluding UIA). @@ -33,12 +35,7 @@ Access to the `urn:matrix:sudo:*` can be time-restricted and require user re-aut Top-level wildcards (`urn:matrix:*` or `*`) are not valid and must be rejected by the authentication server. Wildcards can only replace URN segments, e.g. `urn:matrix:a*` is invalid. -### Exact scopes - -The exact scopes are intentionally not specified in this MSC. -The glob mechanism allows to the existing behaviour during a transition period while allowing further MSCs that introduces those exact scopes. - -### Device handling +#### Device handling With the pre-MSC2964 authentication mechanism, a `device_id` was associated with the access token. Since there are no such thing as a session in OAuth 2.0, this can be hardly mapped like this. @@ -51,20 +48,61 @@ This also has a nice side-effect: if the device asked was never used by the clie The authentication server must only grant exactly one device scope for a token. Wildcards are not allowed under the `urn:matrix:device:` prefix. +### Exact scopes + +The exact scopes are intentionally not specified in this MSC. +The glob mechanism allows to the existing behaviour during a transition period while allowing further MSCs that introduces those exact scopes. + +### Insufficient privilege response + +It is proposed that a [RFC6750](https://datatracker.ietf.org/doc/html/rfc6750) formatted `WWW-Authenticate` response header is used to provide feedback to the client with `error="insufficent_scope"`. + +``` +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Bearer realm="matrix-client.matrix.org", + error="insufficient_scope", + scope="urn:matrix:api:something" +``` + +On receipt of such a response the client can then request a new authorization from the issuer as per [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) requesting the additional scope be granted. + +For non-UIA API endpoints the rest of the response would be as per the [standard error respponse](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) spec. + +For example: + +``` +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Bearer realm="matrix-client.matrix.org", error="insufficient_scope", scope="urn:matrix:api:something" +Content-Type: application/json + +{ + "errcode": "M_FORBIDDEN", + "error": "Insufficient privilege" +} +``` + ## Potential issues The Device ID handling involves some custom logic on the authorization server side. This means the Matrix server must be involved at some point in the authorization logic, which also involves implementation-specific code for each Matrix server implementation and OAuth 2.0 authentication server implementation. This is not a problem when the Matrix server acts as the authorization server. +The addition of the `WWW-Authenticate` header could cause issue with some clients. + ## Alternatives +### Scopes Scope format could also have an URL format, e.g. `https://matrix.org/api/*/read`. The URL prefix could either be static (`https://matrix.org`) or dependant on the homeserver (`https://matrix.example.com`). In both cases, the URL could be confused with API endpoints and in the second case it would require discovery to know what scopes to ask. The actual prefix as well as the `:api:`, `:sudo:` and `:device:` URN parts are open to debate. +### Insufficient privilege response +The [standard error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used, however this wouldn't work on UIA endpoints which already have a different format response. + +A custom HTTP header could be used instead. + ## Security considerations TBD From d49f2d8856fc3272879fb55346809f96c21157f6 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 18 May 2022 18:45:40 +0100 Subject: [PATCH 03/31] Remove realm as not required --- proposals/2967-api-scopes.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 6175c8586f1..b3ea15fe5b4 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -59,9 +59,7 @@ It is proposed that a [RFC6750](https://datatracker.ietf.org/doc/html/rfc6750) f ``` HTTP/1.1 401 Unauthorized -WWW-Authenticate: Bearer realm="matrix-client.matrix.org", - error="insufficient_scope", - scope="urn:matrix:api:something" +WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" ``` On receipt of such a response the client can then request a new authorization from the issuer as per [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) requesting the additional scope be granted. @@ -72,7 +70,7 @@ For example: ``` HTTP/1.1 401 Unauthorized -WWW-Authenticate: Bearer realm="matrix-client.matrix.org", error="insufficient_scope", scope="urn:matrix:api:something" +WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" Content-Type: application/json { From 23c7638f1fb867ba22a64875c4b0694bc5e7bb5a Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Sun, 31 Jul 2022 19:50:25 +0100 Subject: [PATCH 04/31] Clarifications + update on latest device management proposal --- proposals/2967-api-scopes.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index b3ea15fe5b4..7774995e8d3 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,22 +1,24 @@ # MSC2967: API scope restriction -When a user logs in with a Matrix client, it gives this client full access to their Matrix account. +When a user signs in with a Matrix client, it currently gives this client full access to their Matrix account. This proposal introduces access scopes to allow restricting client access to only part(s) of the Matrix client API. ## Proposal -The [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of OAuth 2.0 to authenticate against a Matrix server. -OAuth 2.0 grants have scopes associated to them and encourage to ask for user consent when a client asks for a new scope that was not granted before. +[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of OAuth 2.0 for a client to authenticate against a Matrix homeserver. -This MSC does not attempt to define all the scopes necessary to cover the whole API, but lays out a base for that. +OAuth 2.0 grants have scopes associated to them and provides a framework for obtaining user consent. + +The framework encourages the practise of obtaining additional use consent when a client asks for a new scope that was not granted previously. + +This MSC does not attempt to define all the scopes necessary to cover all Matrix APIs and use cases, but proposes the structure of a namespace and some specific scopes to cover existing use cases. Additionally it is proposed that a standard approach to error response representation is adopted across the API. This could replace the UIA based responses that exist on some API endpoints today. ### Scope format -URN are widely used formats for OAuth 2.0 scopes. -All scopes related to Matrix must therefore start with `urn:matrix:`. +All scopes related to Matrix should start with `urn:matrix:`. Calls to the Matrix client API, excluding calls that need UIA, must be restricted by scopes prefixed by `urn:matrix:api:`. Calls to endpoints that currently need User-Interactive Authentication (UIA) must be restricted by scopes prefixed by `urn:matrix:sudo:`. @@ -37,20 +39,22 @@ Wildcards can only replace URN segments, e.g. `urn:matrix:a*` is invalid. #### Device handling -With the pre-MSC2964 authentication mechanism, a `device_id` was associated with the access token. -Since there are no such thing as a session in OAuth 2.0, this can be hardly mapped like this. +With the pre-MSC2964 authentication mechanism, a `device_id` was associated with a specific access token. In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism. + +MSC2964 proposes that the client is responsible for generating/allocating a `device_id`. A client can adopt and rehydrate an existing client by asking for its scope on login. + +The client can then bind the `device_id` to the grant by requesting a scope with the format: `urn:matrix:device:`. -`device_id` can be bound to a client session via a scope with this format: `urn:matrix:device:[device_id]`. -If the client does not ask such a scope during the initial login, the authentication server must generate a new `device_id` and give it as a granted scope to the client. -A client can adopt and rehydrate an existing client by asking for its scope on login. This also has a nice side-effect: if the device asked was never used by the client making the request, the authorization server will ask for explicit consent from the user. The authentication server must only grant exactly one device scope for a token. + Wildcards are not allowed under the `urn:matrix:device:` prefix. ### Exact scopes -The exact scopes are intentionally not specified in this MSC. +Exact scopes for the whole API are intentionally not specified in this MSC. + The glob mechanism allows to the existing behaviour during a transition period while allowing further MSCs that introduces those exact scopes. ### Insufficient privilege response @@ -81,9 +85,7 @@ Content-Type: application/json ## Potential issues -The Device ID handling involves some custom logic on the authorization server side. -This means the Matrix server must be involved at some point in the authorization logic, which also involves implementation-specific code for each Matrix server implementation and OAuth 2.0 authentication server implementation. -This is not a problem when the Matrix server acts as the authorization server. +The Device ID handling involves some custom logic on the authorization server side to handle the dynamic scope format. The addition of the `WWW-Authenticate` header could cause issue with some clients. From b609c2bb82646429ade75770ec5123ba179feb2f Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 3 Aug 2022 16:00:02 +0100 Subject: [PATCH 05/31] Revised namespace structure + unstable prefixes --- proposals/2967-api-scopes.md | 82 ++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 7774995e8d3..9c38b05c413 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,4 +1,4 @@ -# MSC2967: API scope restriction +# MSC2967: API scopes When a user signs in with a Matrix client, it currently gives this client full access to their Matrix account. @@ -18,50 +18,64 @@ Additionally it is proposed that a standard approach to error response represent ### Scope format -All scopes related to Matrix should start with `urn:matrix:`. +All scopes related to Matrix should start with `urn:matrix` and use the `:` delimiter for further sub-division. -Calls to the Matrix client API, excluding calls that need UIA, must be restricted by scopes prefixed by `urn:matrix:api:`. -Calls to endpoints that currently need User-Interactive Authentication (UIA) must be restricted by scopes prefixed by `urn:matrix:sudo:`. +| Prefix | Purpose | +| - | - | +| `urn:matrix:client` | For mapping of Client Server API access levels | +| `urn:matrix:device` | For representing device IDs | -Protected resource can have both `read` and `write` operations. -`write` access to a resource implies `read` access to it. -Access to those operations are specified as the scope suffix, e.g. `urn:matrix:api:[resource]:read`. +For future MSCs that build on this namespace unstable sub divisions should be used whilst in development: -#### Globs +e.g. `urn:matrix:com.example.mscXXXX.foo:something` or `urn:matrix:client:com.example.mscXXXX.something` -Scopes used by the Matrix client API support wildcard globs. -`urn:matrix:api:*` gives full access to the API (excluding UIA). -`urn:matrix:api:*:read` gives read-only access to the API. -Access to the `urn:matrix:sudo:*` can be time-restricted and require user re-authentication for sensitive operations. +### Allocated scopes -Top-level wildcards (`urn:matrix:*` or `*`) are not valid and must be rejected by the authentication server. -Wildcards can only replace URN segments, e.g. `urn:matrix:a*` is invalid. +#### Legacy use cases -#### Device handling +To support existing, pre-MSC2964 use cases the following scopes are assigned: -With the pre-MSC2964 authentication mechanism, a `device_id` was associated with a specific access token. In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism. +| Scope | Purpose | Implementation notes | +| - | - | - | +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API (excluding UIA endpoints) | The OP can issue a refresh token for grants with this scope. | +| `urn:matrix:client:uia:*` | Grants full access to all UIA protected endpoints in the Client-Server API | The client should only request this when needed for a specific user operation. The OP should only issue a short-lived (e.g. 30 seconds) access token without a refresh token. | -MSC2964 proposes that the client is responsible for generating/allocating a `device_id`. A client can adopt and rehydrate an existing client by asking for its scope on login. +The intention is that a client would ordinarily only be granted the `urn:matrix:client:api:*` scope and only when the client wishes to call a UIA protected endpoint would the client request an *additional* access token the granted `urn:matrix:client:uia:*` for a limited period of time. -The client can then bind the `device_id` to the grant by requesting a scope with the format: `urn:matrix:device:`. +#### Device ID handling + +Presently a device ID is typically generated by the homeserver and is associated with a specific access token. In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism. + +MSC2964 proposes that the Matrix client is responsible for generating/allocating a device ID. A client can adopt and rehydrate an existing client by asking for its scope on login. This also has a nice side-effect: if the device asked was never used by the client making the request, the authorization server will ask for explicit consent from the user. -The authentication server must only grant exactly one device scope for a token. +The client can then bind the device ID to the grant by requesting a scope with the format: -Wildcards are not allowed under the `urn:matrix:device:` prefix. +| Scope | Purpose | Implementation notes | +| - | - | - | +| `urn:matrix:device:` | bind the given device ID to the grant/access token | The OIDC Provider must only grant exactly one device scope for a token. | -### Exact scopes +For the purpose of this MSC we are assuming that device IDs are as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) and, as such, are already URL safe and so can be represented as a scope without modification. + +### Future scopes Exact scopes for the whole API are intentionally not specified in this MSC. -The glob mechanism allows to the existing behaviour during a transition period while allowing further MSCs that introduces those exact scopes. +It is envisages that the namespace could be further partitioned to support use cases such as read only, write only, limited to one or more rooms etc. + +Some thoughts/ideas for possible scopes are: + +- `urn:matrix:client:api:` or `urn:matrix:client:api::*` - grant limited access to the client API in all rooms. Permissions could be read, write, delete, append. +- `urn:matrix:client:api:read:` - read-only access to the client API for just the named resource. e.g. `urn:matrix:client:api:read:#matrix-auth` + +New MSCs should be created for proposing and discussing such new scopes. ### Insufficient privilege response It is proposed that a [RFC6750](https://datatracker.ietf.org/doc/html/rfc6750) formatted `WWW-Authenticate` response header is used to provide feedback to the client with `error="insufficent_scope"`. -``` +```http HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" ``` @@ -72,7 +86,7 @@ For non-UIA API endpoints the rest of the response would be as per the [standard For example: -``` +```http HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" Content-Type: application/json @@ -85,21 +99,26 @@ Content-Type: application/json ## Potential issues -The Device ID handling involves some custom logic on the authorization server side to handle the dynamic scope format. +The Device ID handling involves a change in where device IDs are generated. Currently a + +some custom logic on the authorization server side to handle the dynamic scope format. The addition of the `WWW-Authenticate` header could cause issue with some clients. ## Alternatives ### Scopes + Scope format could also have an URL format, e.g. `https://matrix.org/api/*/read`. + The URL prefix could either be static (`https://matrix.org`) or dependant on the homeserver (`https://matrix.example.com`). In both cases, the URL could be confused with API endpoints and in the second case it would require discovery to know what scopes to ask. -The actual prefix as well as the `:api:`, `:sudo:` and `:device:` URN parts are open to debate. +The actual namespace prefix and sub divisions are open to debate. ### Insufficient privilege response -The [standard error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used, however this wouldn't work on UIA endpoints which already have a different format response. + +The [standard Client-Server API error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used, however this wouldn't work on UIA endpoints which already have a different format response. A custom HTTP header could be used instead. @@ -109,4 +128,11 @@ TBD ## Unstable prefix -None relevant. +While this feature is in development the following unstable scope prefixes should be used: + +- `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client` +- `urn:matrix:device` --> `urn:matrix:org.matrix.msc2967.device` + +## Dependencies + +- [MSC2964: Delegation of auth from homeserver to OIDC Provider](https://github.com/matrix-org/matrix-spec-proposals/pull/2964) From f07b466b3b2b8dfcb15617f56f639e6a195bdba0 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 3 Aug 2022 17:02:16 +0100 Subject: [PATCH 06/31] Revise prefix for device ID --- proposals/2967-api-scopes.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 9c38b05c413..be595f9ffb4 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,6 +1,6 @@ # MSC2967: API scopes -When a user signs in with a Matrix client, it currently gives this client full access to their Matrix account. +When a user signs in with a Matrix client, it currently gives the client full access to their Matrix account. This proposal introduces access scopes to allow restricting client access to only part(s) of the Matrix client API. @@ -23,7 +23,6 @@ All scopes related to Matrix should start with `urn:matrix` and use the `:` deli | Prefix | Purpose | | - | - | | `urn:matrix:client` | For mapping of Client Server API access levels | -| `urn:matrix:device` | For representing device IDs | For future MSCs that build on this namespace unstable sub divisions should be used whilst in development: @@ -54,7 +53,7 @@ The client can then bind the device ID to the grant by requesting a scope with t | Scope | Purpose | Implementation notes | | - | - | - | -| `urn:matrix:device:` | bind the given device ID to the grant/access token | The OIDC Provider must only grant exactly one device scope for a token. | +| `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The OIDC Provider must only grant exactly one device scope for a token. | For the purpose of this MSC we are assuming that device IDs are as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) and, as such, are already URL safe and so can be represented as a scope without modification. @@ -131,7 +130,6 @@ TBD While this feature is in development the following unstable scope prefixes should be used: - `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client` -- `urn:matrix:device` --> `urn:matrix:org.matrix.msc2967.device` ## Dependencies From 1ce049e72a6a432a34646501530037bc7c703bb4 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 5 Aug 2022 10:08:40 +0100 Subject: [PATCH 07/31] Reference to MSC3861 + cleanup --- proposals/2967-api-scopes.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index be595f9ffb4..5af879597af 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,5 +1,7 @@ # MSC2967: API scopes +This proposal is part of the broader [MSC3861: Matrix architecture change to delegate authentication via OIDC](https://github.com/matrix-org/matrix-spec-proposals/pull/2967). + When a user signs in with a Matrix client, it currently gives the client full access to their Matrix account. This proposal introduces access scopes to allow restricting client access to only part(s) of the Matrix client API. @@ -41,6 +43,8 @@ To support existing, pre-MSC2964 use cases the following scopes are assigned: The intention is that a client would ordinarily only be granted the `urn:matrix:client:api:*` scope and only when the client wishes to call a UIA protected endpoint would the client request an *additional* access token the granted `urn:matrix:client:uia:*` for a limited period of time. +These are referred to as "legacy" because it is envisioned that a client would request more specific actions in future when required. e.g. something like `urn:matrix:client:api:read:*` + #### Device ID handling Presently a device ID is typically generated by the homeserver and is associated with a specific access token. In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism. @@ -61,7 +65,7 @@ For the purpose of this MSC we are assuming that device IDs are as per [MSC1597] Exact scopes for the whole API are intentionally not specified in this MSC. -It is envisages that the namespace could be further partitioned to support use cases such as read only, write only, limited to one or more rooms etc. +It is envisioned that the namespace could be further partitioned to support use cases such as read only, write only, limited to one or more rooms etc. Some thoughts/ideas for possible scopes are: @@ -98,9 +102,7 @@ Content-Type: application/json ## Potential issues -The Device ID handling involves a change in where device IDs are generated. Currently a - -some custom logic on the authorization server side to handle the dynamic scope format. +The Device ID handling involves a change in where device IDs are generated. This is discussed in MSC2964. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OIDC Providers (e.g. Okta and Auth0). The addition of the `WWW-Authenticate` header could cause issue with some clients. From 5c575076cde63ee4b12c07cb0cf217c9941b0c1c Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Thu, 17 Nov 2022 14:50:50 +0000 Subject: [PATCH 08/31] Add scope for guest access and tidy up --- proposals/2967-api-scopes.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 5af879597af..8666e048af8 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -38,6 +38,7 @@ To support existing, pre-MSC2964 use cases the following scopes are assigned: | Scope | Purpose | Implementation notes | | - | - | - | +| `urn:matrix:client:api:guest` | Grants access as a guest to endpoints in the Client-Server API | The OP can issue a refresh token for grants with this scope. | | `urn:matrix:client:api:*` | Grants full access to the Client-Server API (excluding UIA endpoints) | The OP can issue a refresh token for grants with this scope. | | `urn:matrix:client:uia:*` | Grants full access to all UIA protected endpoints in the Client-Server API | The client should only request this when needed for a specific user operation. The OP should only issue a short-lived (e.g. 30 seconds) access token without a refresh token. | @@ -96,7 +97,26 @@ Content-Type: application/json { "errcode": "M_FORBIDDEN", - "error": "Insufficient privilege" + "error": "Insufficient scope" +} +``` + +### User Interactive Auth + +Before calling an API endpoint protected by user interactive authentication the client can check that they already have the scope `urn:matrix:client:uia:*`. + +If they don't have it then they can pre-emptively acquire it ahead of making the API call. + +The Homeserver should enforce the presence of the `urn:matrix:client:uia:*` scope and if not then it would return a response as follows: + +```http +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:client:uia:*" +Content-Type: application/json + +{ + "errcode": "M_FORBIDDEN", + "error": "Insufficient scope" } ``` @@ -104,6 +124,8 @@ Content-Type: application/json The Device ID handling involves a change in where device IDs are generated. This is discussed in MSC2964. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OIDC Providers (e.g. Okta and Auth0). +The requirement that the UIA scope should only be made available for a limited time is likely non-standard for some OPs as well. + The addition of the `WWW-Authenticate` header could cause issue with some clients. ## Alternatives From 5afb697d9b096ab3f3a630a535a1fcb1ed79a6bd Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Thu, 16 Feb 2023 16:03:17 +0000 Subject: [PATCH 09/31] No need for UIA scope --- proposals/2967-api-scopes.md | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 8666e048af8..7a755495281 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -39,10 +39,7 @@ To support existing, pre-MSC2964 use cases the following scopes are assigned: | Scope | Purpose | Implementation notes | | - | - | - | | `urn:matrix:client:api:guest` | Grants access as a guest to endpoints in the Client-Server API | The OP can issue a refresh token for grants with this scope. | -| `urn:matrix:client:api:*` | Grants full access to the Client-Server API (excluding UIA endpoints) | The OP can issue a refresh token for grants with this scope. | -| `urn:matrix:client:uia:*` | Grants full access to all UIA protected endpoints in the Client-Server API | The client should only request this when needed for a specific user operation. The OP should only issue a short-lived (e.g. 30 seconds) access token without a refresh token. | - -The intention is that a client would ordinarily only be granted the `urn:matrix:client:api:*` scope and only when the client wishes to call a UIA protected endpoint would the client request an *additional* access token the granted `urn:matrix:client:uia:*` for a limited period of time. +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The OP can issue a refresh token for grants with this scope. | These are referred to as "legacy" because it is envisioned that a client would request more specific actions in future when required. e.g. something like `urn:matrix:client:api:read:*` @@ -84,9 +81,9 @@ HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" ``` -On receipt of such a response the client can then request a new authorization from the issuer as per [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) requesting the additional scope be granted. +On receipt of such a response the client may then request a new authorization from the issuer as per [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) requesting the additional scope be granted. -For non-UIA API endpoints the rest of the response would be as per the [standard error respponse](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) spec. +The rest of the response would be as per the [standard error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) spec. For example: @@ -101,30 +98,9 @@ Content-Type: application/json } ``` -### User Interactive Auth - -Before calling an API endpoint protected by user interactive authentication the client can check that they already have the scope `urn:matrix:client:uia:*`. - -If they don't have it then they can pre-emptively acquire it ahead of making the API call. - -The Homeserver should enforce the presence of the `urn:matrix:client:uia:*` scope and if not then it would return a response as follows: - -```http -HTTP/1.1 401 Unauthorized -WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:client:uia:*" -Content-Type: application/json - -{ - "errcode": "M_FORBIDDEN", - "error": "Insufficient scope" -} -``` - ## Potential issues -The Device ID handling involves a change in where device IDs are generated. This is discussed in MSC2964. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OIDC Providers (e.g. Okta and Auth0). - -The requirement that the UIA scope should only be made available for a limited time is likely non-standard for some OPs as well. +The Device ID handling involves a change in where device IDs are generated. This is discussed in MSC2964. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OpenID Providers (e.g. Okta and Auth0). The addition of the `WWW-Authenticate` header could cause issue with some clients. @@ -141,13 +117,13 @@ The actual namespace prefix and sub divisions are open to debate. ### Insufficient privilege response -The [standard Client-Server API error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used, however this wouldn't work on UIA endpoints which already have a different format response. +The [standard Client-Server API error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used. A custom HTTP header could be used instead. ## Security considerations -TBD +As we are just representing existing access models there shouldn't be anything special. ## Unstable prefix From 8ec2d7c47647d5b6d107549df75c24ec858b408f Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 28 Jul 2023 06:20:22 -0400 Subject: [PATCH 10/31] Update proposals/2967-api-scopes.md Co-authored-by: Patrick Cloke --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 7a755495281..357d4249c90 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -100,7 +100,7 @@ Content-Type: application/json ## Potential issues -The Device ID handling involves a change in where device IDs are generated. This is discussed in MSC2964. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OpenID Providers (e.g. Okta and Auth0). +The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964). On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OpenID Providers (e.g. Okta and Auth0). The addition of the `WWW-Authenticate` header could cause issue with some clients. From 8539ab2050804a88d075ab408c47ca7f1caa143c Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 10 May 2024 12:23:34 +0100 Subject: [PATCH 11/31] Clarification about encoding of device ID within URN scope --- proposals/2967-api-scopes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 357d4249c90..0cc62c899d0 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -51,13 +51,13 @@ MSC2964 proposes that the Matrix client is responsible for generating/allocating This also has a nice side-effect: if the device asked was never used by the client making the request, the authorization server will ask for explicit consent from the user. -The client can then bind the device ID to the grant by requesting a scope with the format: +The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986) URN in the format: | Scope | Purpose | Implementation notes | | - | - | - | | `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The OIDC Provider must only grant exactly one device scope for a token. | -For the purpose of this MSC we are assuming that device IDs are as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) and, as such, are already URL safe and so can be represented as a scope without modification. +Note that currently the Matrix specification doesn't specify a format for the device ID itself. If the device ID were constrained as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) then it could be directly represented within a URN without further encoding. ### Future scopes From f65aef3952ce0f9656abde251065239e5192ffae Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 4 Sep 2024 18:35:20 +0200 Subject: [PATCH 12/31] Rework MSC - Remove insufficient privilege response - Remove guest scopes - Reword some parts --- proposals/2967-api-scopes.md | 57 +++++------------------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 0cc62c899d0..e79e43769ee 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,6 +1,6 @@ # MSC2967: API scopes -This proposal is part of the broader [MSC3861: Matrix architecture change to delegate authentication via OIDC](https://github.com/matrix-org/matrix-spec-proposals/pull/2967). +This proposal is part of the broader [MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC](https://github.com/matrix-org/matrix-spec-proposals/pull/3861). When a user signs in with a Matrix client, it currently gives the client full access to their Matrix account. @@ -8,15 +8,13 @@ This proposal introduces access scopes to allow restricting client access to onl ## Proposal -[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of OAuth 2.0 for a client to authenticate against a Matrix homeserver. +[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver. OAuth 2.0 grants have scopes associated to them and provides a framework for obtaining user consent. The framework encourages the practise of obtaining additional use consent when a client asks for a new scope that was not granted previously. -This MSC does not attempt to define all the scopes necessary to cover all Matrix APIs and use cases, but proposes the structure of a namespace and some specific scopes to cover existing use cases. - -Additionally it is proposed that a standard approach to error response representation is adopted across the API. This could replace the UIA based responses that exist on some API endpoints today. +This MSC does not attempt to define all the scopes necessary to cover all Matrix APIs and use cases, but proposes the structure of a namespace and a few scopes to cover existing use cases. ### Scope format @@ -32,16 +30,15 @@ e.g. `urn:matrix:com.example.mscXXXX.foo:something` or `urn:matrix:client:com.ex ### Allocated scopes -#### Legacy use cases +#### Full API read/write access -To support existing, pre-MSC2964 use cases the following scopes are assigned: +To support the existing semantic of granting full access to the Matrix C-S API the following scope is assigned: | Scope | Purpose | Implementation notes | | - | - | - | -| `urn:matrix:client:api:guest` | Grants access as a guest to endpoints in the Client-Server API | The OP can issue a refresh token for grants with this scope. | | `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The OP can issue a refresh token for grants with this scope. | -These are referred to as "legacy" because it is envisioned that a client would request more specific actions in future when required. e.g. something like `urn:matrix:client:api:read:*` +In the future, a client would request more specific actions when required. e.g. something like `urn:matrix:client:api:read:*` #### Device ID handling @@ -55,7 +52,7 @@ The client can then bind the device ID to the grant by requesting a scope compri | Scope | Purpose | Implementation notes | | - | - | - | -| `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The OIDC Provider must only grant exactly one device scope for a token. | +| `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The homeserver must only grant exactly one device scope for a token. | Note that currently the Matrix specification doesn't specify a format for the device ID itself. If the device ID were constrained as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) then it could be directly represented within a URN without further encoding. @@ -72,37 +69,9 @@ Some thoughts/ideas for possible scopes are: New MSCs should be created for proposing and discussing such new scopes. -### Insufficient privilege response - -It is proposed that a [RFC6750](https://datatracker.ietf.org/doc/html/rfc6750) formatted `WWW-Authenticate` response header is used to provide feedback to the client with `error="insufficent_scope"`. - -```http -HTTP/1.1 401 Unauthorized -WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" -``` - -On receipt of such a response the client may then request a new authorization from the issuer as per [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) requesting the additional scope be granted. - -The rest of the response would be as per the [standard error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) spec. - -For example: - -```http -HTTP/1.1 401 Unauthorized -WWW-Authenticate: Bearer error="insufficient_scope", scope="urn:matrix:api:something" -Content-Type: application/json - -{ - "errcode": "M_FORBIDDEN", - "error": "Insufficient scope" -} -``` - ## Potential issues -The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964). On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. This is not currently supported by some OpenID Providers (e.g. Okta and Auth0). - -The addition of the `WWW-Authenticate` header could cause issue with some clients. +The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964). On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. ## Alternatives @@ -115,12 +84,6 @@ In both cases, the URL could be confused with API endpoints and in the second ca The actual namespace prefix and sub divisions are open to debate. -### Insufficient privilege response - -The [standard Client-Server API error response](https://spec.matrix.org/v1.2/client-server-api/#standard-error-response) could be used. - -A custom HTTP header could be used instead. - ## Security considerations As we are just representing existing access models there shouldn't be anything special. @@ -130,7 +93,3 @@ As we are just representing existing access models there shouldn't be anything s While this feature is in development the following unstable scope prefixes should be used: - `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client` - -## Dependencies - -- [MSC2964: Delegation of auth from homeserver to OIDC Provider](https://github.com/matrix-org/matrix-spec-proposals/pull/2964) From 660946ab64a1bf158648f1c44ea8beb89dac0e16 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 5 Mar 2025 17:41:21 +0100 Subject: [PATCH 13/31] Update proposals/2967-api-scopes.md Co-authored-by: Travis Ralston --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index e79e43769ee..f1ce70cebc1 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -36,7 +36,7 @@ To support the existing semantic of granting full access to the Matrix C-S API t | Scope | Purpose | Implementation notes | | - | - | - | -| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The OP can issue a refresh token for grants with this scope. | +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The homeserver can issue a refresh token for grants with this scope. | In the future, a client would request more specific actions when required. e.g. something like `urn:matrix:client:api:read:*` From 4dd433faa1f323260be645d81b0a6518bbf7984d Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 13 Mar 2025 17:23:54 +0100 Subject: [PATCH 14/31] Reword as dbkr suggested --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index f1ce70cebc1..c61711fb9e4 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -10,7 +10,7 @@ This proposal introduces access scopes to allow restricting client access to onl [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver. -OAuth 2.0 grants have scopes associated to them and provides a framework for obtaining user consent. +A OAuth 2.0 grant has a scope associated to it which provides a framework for obtaining user consent. The framework encourages the practise of obtaining additional use consent when a client asks for a new scope that was not granted previously. From 79845f534dc5c49bbcb37350802af4aa49c2544a Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 13 Mar 2025 17:28:48 +0100 Subject: [PATCH 15/31] Reword how unstable subdivisions are used --- proposals/2967-api-scopes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index c61711fb9e4..b3eb190fd83 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -24,9 +24,10 @@ All scopes related to Matrix should start with `urn:matrix` and use the `:` deli | - | - | | `urn:matrix:client` | For mapping of Client Server API access levels | -For future MSCs that build on this namespace unstable sub divisions should be used whilst in development: +For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development. -e.g. `urn:matrix:com.example.mscXXXX.foo:something` or `urn:matrix:client:com.example.mscXXXX.something` +For example, if MSCXXX 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 scope, 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`. ### Allocated scopes From 49550fe9dddaa0e92f0bb2c21d8dde647bd87a15 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 13 Mar 2025 17:32:20 +0100 Subject: [PATCH 16/31] Remove confusing sentence --- proposals/2967-api-scopes.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index b3eb190fd83..75bdc8189cb 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -47,8 +47,6 @@ Presently a device ID is typically generated by the homeserver and is associated MSC2964 proposes that the Matrix client is responsible for generating/allocating a device ID. A client can adopt and rehydrate an existing client by asking for its scope on login. -This also has a nice side-effect: if the device asked was never used by the client making the request, the authorization server will ask for explicit consent from the user. - The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986) URN in the format: | Scope | Purpose | Implementation notes | From 14b962cf99f0516b72cf396aede8f64d14a40f64 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 13 Mar 2025 17:34:28 +0100 Subject: [PATCH 17/31] Gather all the links at the bottom of the document --- proposals/2967-api-scopes.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 75bdc8189cb..7fd7c222241 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -1,6 +1,6 @@ # MSC2967: API scopes -This proposal is part of the broader [MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC](https://github.com/matrix-org/matrix-spec-proposals/pull/3861). +This proposal is part of the broader [MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC][MSC3861]. When a user signs in with a Matrix client, it currently gives the client full access to their Matrix account. @@ -8,7 +8,7 @@ This proposal introduces access scopes to allow restricting client access to onl ## Proposal -[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver. +[MSC2964] introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver. A OAuth 2.0 grant has a scope associated to it which provides a framework for obtaining user consent. @@ -37,7 +37,7 @@ To support the existing semantic of granting full access to the Matrix C-S API t | Scope | Purpose | Implementation notes | | - | - | - | -| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The homeserver can issue a refresh token for grants with this scope. | +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The OP can issue a refresh token for grants with this scope. | In the future, a client would request more specific actions when required. e.g. something like `urn:matrix:client:api:read:*` @@ -47,7 +47,7 @@ Presently a device ID is typically generated by the homeserver and is associated MSC2964 proposes that the Matrix client is responsible for generating/allocating a device ID. A client can adopt and rehydrate an existing client by asking for its scope on login. -The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986) URN in the format: +The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986] URN in the format: | Scope | Purpose | Implementation notes | | - | - | - | @@ -70,7 +70,7 @@ New MSCs should be created for proposing and discussing such new scopes. ## Potential issues -The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964). On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. +The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964]. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. ## Alternatives @@ -92,3 +92,7 @@ As we are just representing existing access models there shouldn't be anything s While this feature is in development the following unstable scope prefixes should be used: - `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client` + +[MSC2964]: https://github.com/matrix-org/matrix-spec-proposals/pull/2964 +[MSC3861]: https://github.com/matrix-org/matrix-spec-proposals/pull/3861 +[RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986 From 58f23982f2f74d54168e9b924a2e7021256425d4 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 14 Mar 2025 09:44:12 +0100 Subject: [PATCH 18/31] Tyding up, define exactly how device IDs are handled --- proposals/2967-api-scopes.md | 52 +++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 7fd7c222241..acc57afc54c 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -22,7 +22,7 @@ All scopes related to Matrix should start with `urn:matrix` and use the `:` deli | Prefix | Purpose | | - | - | -| `urn:matrix:client` | For mapping of Client Server API access levels | +| `urn:matrix:client:` | For mapping of Client Server API access levels | For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development. @@ -35,17 +35,19 @@ If it needs to introduce multiple scope, like `urn:matrix:client:foo` and `urn:m To support the existing semantic of granting full access to the Matrix C-S API the following scope is assigned: -| Scope | Purpose | Implementation notes | -| - | - | - | -| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | The OP can issue a refresh token for grants with this scope. | +| Scope | Purpose | +| - | - | +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API | In the future, a client would request more specific actions when required. e.g. something like `urn:matrix:client:api:read:*` #### Device ID handling -Presently a device ID is typically generated by the homeserver and is associated with a specific access token. In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism. +Presently a device ID is typically generated by the homeserver and is associated with a specific series of access tokens. -MSC2964 proposes that the Matrix client is responsible for generating/allocating a device ID. A client can adopt and rehydrate an existing client by asking for its scope on login. +This MSC proposes that the Matrix client is responsible for generating/allocating a device ID. +A client can create a new device ID by generating a random string and asking for its associated scope on login. +A client can adopt and rehydrate an existing client by asking for its scope on login. The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986] URN in the format: @@ -53,7 +55,22 @@ The client can then bind the device ID to the grant by requesting a scope compri | - | - | - | | `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The homeserver must only grant exactly one device scope for a token. | -Note that currently the Matrix specification doesn't specify a format for the device ID itself. If the device ID were constrained as per [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597) then it could be directly represented within a URN without further encoding. +The device ID scope MUST be present *at most* once in the scope. + +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 [RFC3986]: + +> unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~" + +Using this alphabet, a 10 character string is enough to be reasonably unique. +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 used characters allowed by the OAuth 2.0 scope definition in [RFC6749] section 3.3. +It is defined as the following ASCII ranges: `%x21 / %x23-5B / %x5D-7E` +Which is equivalent to: + + - alphanumeric characters (`A-Z`, `a-z`, `0-9`) + - the following characters: `! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ \` { | } ~` ### Future scopes @@ -70,18 +87,31 @@ New MSCs should be created for proposing and discussing such new scopes. ## Potential issues -The Device ID handling involves a change in where device IDs are generated. This is discussed in [MSC2964]. On the OIDC Provider side the device ID proposal requires the use of dynamic scopes. That is, the specific scope is a templated form rather than being static. +The Device ID handling involves a change in where device IDs are generated. +Because the device ID is now generated by the client, it is possible to have a device ID collision. + +Requiring enough entropy on the device ID ensures that the device ID is unique. +With a 66 character alphabet and a 10 character device ID, the probability of a collision between 100 million devices is around 0.3%: + +$$ +N = 66^{10} \\ +K = 10^{8} \\ +P \approx 1 - e^{\frac{K^2}{2N}} \\ +P \approx 0.00318 +$$ + +This does also restrict the possible alphabet of device IDs, which was not restricted before. ## Alternatives ### Scopes -Scope format could also have an URL format, e.g. `https://matrix.org/api/*/read`. +Scope could also have an URL format, e.g. `https://matrix.org/api/*/read`. The URL prefix could either be static (`https://matrix.org`) or dependant on the homeserver (`https://matrix.example.com`). In both cases, the URL could be confused with API endpoints and in the second case it would require discovery to know what scopes to ask. -The actual namespace prefix and sub divisions are open to debate. +The actual namespace prefix and subdivisions are open to debate. ## Security considerations @@ -93,6 +123,8 @@ While this feature is in development the following unstable scope prefixes shoul - `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client` +[MSC1597]: https://github.com/matrix-org/matrix-spec-proposals/pull/1597 [MSC2964]: https://github.com/matrix-org/matrix-spec-proposals/pull/2964 [MSC3861]: https://github.com/matrix-org/matrix-spec-proposals/pull/3861 [RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986 +[RFC6749]: https://datatracker.ietf.org/doc/html/rfc6749 From e7531fa49a30090975d39f39f41224f774696d38 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 14 Mar 2025 09:49:19 +0100 Subject: [PATCH 19/31] Don't use a table for a single row --- proposals/2967-api-scopes.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index acc57afc54c..1ee1dd1cd02 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -18,11 +18,9 @@ This MSC does not attempt to define all the scopes necessary to cover all Matrix ### Scope format -All scopes related to Matrix should start with `urn:matrix` and use the `:` delimiter for further sub-division. +All scopes related to Matrix should start with `urn:matrix:` and use the `:` delimiter for further sub-division. -| Prefix | Purpose | -| - | - | -| `urn:matrix:client:` | For mapping of Client Server API access levels | +Scopes related to mapping of Client-Server API access levels should start with `urn:matrix:client:`. For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development. From acc8e91b3ec06f13dbbbe516454f7ae4eb357aed Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 14 Mar 2025 09:50:00 +0100 Subject: [PATCH 20/31] Typo Co-authored-by: David Baker --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 1ee1dd1cd02..b3ca8d4d047 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -25,7 +25,7 @@ Scopes related to mapping of Client-Server API access levels should start with ` For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development. For example, if MSCXXX 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 scope, 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`. +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`. ### Allocated scopes From 13042035ecc55b37bb9d7aac387f515667811030 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 14 Mar 2025 10:10:03 +0100 Subject: [PATCH 21/31] Fix math rendering --- proposals/2967-api-scopes.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index b3ca8d4d047..12dfa07a11d 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -91,12 +91,10 @@ Because the device ID is now generated by the client, it is possible to have a d Requiring enough entropy on the device ID ensures that the device ID is unique. With a 66 character alphabet and a 10 character device ID, the probability of a collision between 100 million devices is around 0.3%: -$$ -N = 66^{10} \\ -K = 10^{8} \\ -P \approx 1 - e^{\frac{K^2}{2N}} \\ -P \approx 0.00318 -$$ +$$N = 66^{10}$$ +$$K = 10^{8}$$ +$$P \approx 1 - e^{\frac{K^2}{2N}}$$ +$$P \approx 0.00318$$ This does also restrict the possible alphabet of device IDs, which was not restricted before. From 6623b96942007dc35244c0c090ff1854b3d97483 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 14:24:01 +0100 Subject: [PATCH 22/31] Fix the math --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 12dfa07a11d..7c47668a17a 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -93,7 +93,7 @@ With a 66 character alphabet and a 10 character device ID, the probability of a $$N = 66^{10}$$ $$K = 10^{8}$$ -$$P \approx 1 - e^{\frac{K^2}{2N}}$$ +$$P \approx 1 - e^{-\frac{K^2}{2N}}$$ $$P \approx 0.00318$$ This does also restrict the possible alphabet of device IDs, which was not restricted before. From 1ddd733182b798399e58231e05fd199d2559a983 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 14:28:54 +0100 Subject: [PATCH 23/31] Minor rewording on device uniqueness Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 7c47668a17a..b1a5ff12e67 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -60,7 +60,7 @@ It SHOULD only use characters from the unreserved character list defined by [RFC > unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~" -Using this alphabet, a 10 character string is enough to be reasonably unique. +Using this alphabet, a 10 character string is enough to stand a sufficient chance of being unique. 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 used characters allowed by the OAuth 2.0 scope definition in [RFC6749] section 3.3. From a33d1e34641006a9bdc156fbb66cb9a8bc2b6697 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 14:29:30 +0100 Subject: [PATCH 24/31] Simplify wording around the ASCII range Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2967-api-scopes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index b1a5ff12e67..8f9ced683b4 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -63,9 +63,8 @@ It SHOULD only use characters from the unreserved character list defined by [RFC Using this alphabet, a 10 character string is enough to stand a sufficient chance of being unique. 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 used characters allowed by the OAuth 2.0 scope definition in [RFC6749] section 3.3. -It is defined as the following ASCII ranges: `%x21 / %x23-5B / %x5D-7E` -Which is equivalent to: +In any case it MUST only use characters allowed by the OAuth 2.0 scope definition in [RFC6749] section 3.3, +which is defined as the following ASCII ranges: `%x21 / %x23-5B / %x5D-7E`, i.e: - alphanumeric characters (`A-Z`, `a-z`, `0-9`) - the following characters: `! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ \` { | } ~` From 0800ea6ea76f1c7259523036bb833d266988e688 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 16:22:19 +0100 Subject: [PATCH 25/31] Typo Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 8f9ced683b4..a088edce3b8 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -10,7 +10,7 @@ This proposal introduces access scopes to allow restricting client access to onl [MSC2964] introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver. -A OAuth 2.0 grant has a scope associated to it which provides a framework for obtaining user consent. +An OAuth 2.0 grant has a scope associated to it which provides a framework for obtaining user consent. The framework encourages the practise of obtaining additional use consent when a client asks for a new scope that was not granted previously. From a7bb99c00a3f8d9283833b06a0f06441ae753765 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 16:31:56 +0100 Subject: [PATCH 26/31] Scope vs scope token is confusing Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index a088edce3b8..a28d5b8c5ee 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -53,7 +53,7 @@ The client can then bind the device ID to the grant by requesting a scope compri | - | - | - | | `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The homeserver must only grant exactly one device scope for a token. | -The device ID scope MUST be present *at most* once in the scope. +There MUST be *at most* one `urn:matrix:client:device:` token in the requested scope. 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 [RFC3986]: From abbae1ebe7f5fb90f4b4929f102c2bceed6dd9a6 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 18 Mar 2025 16:36:11 +0100 Subject: [PATCH 27/31] Reword how the device ID is requested --- proposals/2967-api-scopes.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index a28d5b8c5ee..e7e6802d37c 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -45,13 +45,10 @@ Presently a device ID is typically generated by the homeserver and is associated This MSC proposes that the Matrix client is responsible for generating/allocating a device ID. A client can create a new device ID by generating a random string and asking for its associated scope on login. -A client can adopt and rehydrate an existing client by asking for its scope on login. +A client can adopt and rehydrate an existing device ID by asking for its associated scope on login. -The client can then bind the device ID to the grant by requesting a scope comprising of a [RFC3986] URN in the format: - -| Scope | Purpose | Implementation notes | -| - | - | - | -| `urn:matrix:client:device:` | bind the given device ID to the grant/access token | The homeserver must only grant exactly one device scope for a token. | +The client can then add the requested device ID to the grant by including following token in the requested scope: +`urn:matrix:client:device:`, where `` is the requested device ID. There MUST be *at most* one `urn:matrix:client:device:` token in the requested scope. From 082625d1cc6ef532d5abaff1a1fc5a3c2a4b9aef Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 25 Mar 2025 16:39:08 +0100 Subject: [PATCH 28/31] Explain why we keep the device ID generation on the client --- proposals/2967-api-scopes.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index e7e6802d37c..1a16e5165ea 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -81,6 +81,8 @@ New MSCs should be created for proposing and discussing such new scopes. ## Potential issues +### Device ID collision + The Device ID handling involves a change in where device IDs are generated. Because the device ID is now generated by the client, it is possible to have a device ID collision. @@ -94,6 +96,20 @@ $$P \approx 0.00318$$ This does also restrict the possible alphabet of device IDs, which was not restricted before. +### Generating the device ID on the client + +This proposal effectively changes where the device ID is generated, from "most of the time on the server" to "every time on the client." + +This doesn't introduce a new mechanism, as clients could already select a device ID instead of letting the server generate one. + +One of the original motivation for this change was to adopt existing OAuth 2.0 mechanisms as much as possible. +This meant not introducing Matrix-specific parameters (hence encoding the device ID in the scope) and not relying on non-standard server behaviour (hence the device ID being generated on the client). + +In retrospect, because the whole proposal requires a Matrix-specific implementation anyway, compatibility with existing off-the-shelf OAuth 2.0 server implementations isn't a goal anymore: +we could adopt a Matrix-specific parameter to specify the device ID, and let the server generate it if it's not provided. + +As generating the device ID on the client hasn't been a problem in practice, this proposal kept it like that to avoid the cost of aligning the implementations. + ## Alternatives ### Scopes From 089a78952b75f04485c7b02caca78476bcf27a23 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 26 Mar 2025 11:53:00 +0100 Subject: [PATCH 29/31] MSCXXXX is a better placeholder Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 1a16e5165ea..0bb18c1da29 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -24,7 +24,7 @@ Scopes related to mapping of Client-Server API access levels should start with ` For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development. -For example, if MSCXXX wants to introduce the `urn:matrix:client:foo` scope, it could use `urn:matrix:client:com.example.mscXXXX.foo` during 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`. ### Allocated scopes From 858b7be965a8238fade9369453d3192920d9b39a Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 26 Mar 2025 12:08:12 +0100 Subject: [PATCH 30/31] The scope MUST have a device ID --- proposals/2967-api-scopes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 0bb18c1da29..16dceacc3c4 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -47,10 +47,10 @@ This MSC proposes that the Matrix client is responsible for generating/allocatin A client can create a new device ID by generating a random string and asking for its associated scope on login. A client can adopt and rehydrate an existing device ID by asking for its associated scope on login. -The client can then add the requested device ID to the grant by including following token in the requested scope: +The client must then add the requested device ID to the grant by including following token in the requested scope: `urn:matrix:client:device:`, where `` is the requested device ID. -There MUST be *at most* one `urn:matrix:client:device:` token in the requested scope. +There MUST be exactly one `urn:matrix:client:device:` token in the requested scope. 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 [RFC3986]: From c9f869096f3183d1fbeea61282d9dc9897e1b043 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 26 Mar 2025 13:23:24 +0100 Subject: [PATCH 31/31] Clarify that device IDs are still unique per user Co-authored-by: Patrick Cloke --- proposals/2967-api-scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2967-api-scopes.md b/proposals/2967-api-scopes.md index 16dceacc3c4..78d22a48b37 100644 --- a/proposals/2967-api-scopes.md +++ b/proposals/2967-api-scopes.md @@ -57,7 +57,7 @@ It SHOULD only use characters from the unreserved character list defined by [RFC > unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~" -Using this alphabet, a 10 character string is enough to stand a sufficient chance of being unique. +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 [RFC6749] section 3.3,