From 1b1bcddd7dace3d237895dfae28032fa6405135e Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 14 Jan 2021 18:11:58 +0100 Subject: [PATCH 01/14] OAuth 2.0 Dynamic Registration MSC --- proposals/2966-oauth2-dynamic-registration.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 proposals/2966-oauth2-dynamic-registration.md diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md new file mode 100644 index 00000000000..b91c4182113 --- /dev/null +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -0,0 +1,99 @@ +# MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix + +[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) defines how client should login against a Matrix server using OAuth 2.0. +It assumes the client is known to the authentication server. + +This MSC specifies how Matrix clients should leverage OAuth 2.0 Dynamic Client Registration Protocol ([RFC 7591](https://tools.ietf.org/html/rfc7591)) to register themselves before initiating the login flow. + +## Proposal + +If a Matrix server wants to be used by any third-party client, its authentication server must allow dynamic registration of OAuth 2.0 clients. +The client registration endpoint is advertised in the OIDC discovery document and can be used as per [RFC 7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3). + +### Client metadata + +When registering itself, a client must provide a list of metadata about itself. + +As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), some of those metadata values may be localized. + +```json +{ + "client_name": "Digital mailbox", + "client_name#en-US": "Digital mailbox", + "client_name#en-GB": "Digital postbox", + "client_name#fr": "Boîte aux lettres numérique" +} +``` + +Some of those metadatas are optional in the RFC but required in this context. + +| Name | Description | Behaviour | Localizable | +| ---------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------- | +| `client_name` | Human-readable name of the client to be presented to the user | Required | Yes | +| `client_uri` | URL of a web page providing information about the client | Optional | Yes | +| `logo_uri` | URL that references a logo for the client | Optional | Yes | +| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required | No | +| `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | +| `policy_uri` | URL that points to a human-readable policy document for the client | Required | Yes | +| `redirect_uris` | Array of redirection URIs for use in redirect-based flows | Required with the `authorization_code` grant ype | No | +| `response_types` | Array of the OAuth 2.0 response types that the client may use | Defaults to `["code"]` | No | +| `grant_types` | Array of OAuth 2.0 grant types that the client may use | Defaults to `["authorization_code"]` | No | + +Other metadata registered in the IANA [OAuth Dynamic Client Registration Metadata](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata) registry might be used and supported by Matrix servers and clients. + +### User consent + +When authorizing a third-party client for the first time, the authorization server must ask for explicit user consent and display as much information, preferably localized, about the client as possible. +This includes informations about the publisher, the clients terms of service and its policy. + +The consent screen must include a human-readable list of the scopes requested by the client. + +### Metadata signature + +To securely identify themselves, clients must send a digitally signed version of their metadata. +This is done by encoding the client metadata in a JWT and signing it. + +In addition the client metadata mentioned earlier, the JWT payload must include the following: + +- `iss`: the entity signing the token. This must allow the authorization server to discover the JWT keys of the issuer. +- `iat`: the timestamp when the JWT was signed +- `exp`: a timestamp after which the JWT isn't valid anymore +- `software_id`: a random string uniquely identifying this instance. A random UUIDv4 is suggested for this field + +This allows client to securely update their metadata without being considered as a new client and re-asking user consent. + +The `software_id` is used to uniquely identify a client and ensure the same `client_id` is returned on subsequent registration. +Each `software_id` is tied to the issuer (`iss`) and therefore subsequent registration must be signed by the same issuer. + +The issuer keys can be retrieved using its [OIDC discovery document](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) (`/.well-known/openid-configuration`) or its [authorization server metadata](https://tools.ietf.org/html/rfc8414) (`/.well-known/oauth-authorization-server`). +The issuer does not have to be an actual authorization server, but its metadata can include human-readable informations about the issuer. +Those informations can be displayed on the user consent screen to tell the user about the client's publisher. + +The JWT payload may also include a `software_version` claim denoting the version of the client being registered. +This field should be treated as an opaque string by the authorization server. + +A Matrix server may choose to only allow signed client to be registered. +It might also have an list of trusted issuers for software statements and only allow those to restrict third-party clients. + +## Potential issues + +It is unclear how metadata updates should be handled. +If a client changes its `redirect_uris`, should the old ones be considered for a period of time? +If multiple versions of the same client coexist at the same time, should older versions of the software be able to override the metadata of the newer version? + +If an authorization server allows unsigned clients, the number of client registration might explode exponentially. +At the same time, only allowing signed clients can make client development significantly harder. + +## Alternatives + +None relevant. + +## Security considerations + +Nothing prevents intentional collisions in `software_id`. +An attacker could register a `software_id` of another client before its first registration, blocking it from registration. +The registration endpoint should be rate-limited and the failed registration monitored by server administrators to detect such abuses. + +## Unstable prefix + +None relevant. From d923a45acbace52d56da97eee4c618c738ca0d80 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Thu, 7 Sep 2023 14:31:15 +0100 Subject: [PATCH 02/14] contacts is required non-empty --- proposals/2966-oauth2-dynamic-registration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index b91c4182113..ce564e19157 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -32,7 +32,7 @@ Some of those metadatas are optional in the RFC but required in this context. | `client_name` | Human-readable name of the client to be presented to the user | Required | Yes | | `client_uri` | URL of a web page providing information about the client | Optional | Yes | | `logo_uri` | URL that references a logo for the client | Optional | Yes | -| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required | No | +| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required, non-empty | No | | `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | | `policy_uri` | URL that points to a human-readable policy document for the client | Required | Yes | | `redirect_uris` | Array of redirection URIs for use in redirect-based flows | Required with the `authorization_code` grant ype | No | From 2bdcc4afb535dc3da32080ad3ec172e385369f78 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Thu, 7 Sep 2023 16:14:13 +0100 Subject: [PATCH 03/14] Make client_uri mandatory --- proposals/2966-oauth2-dynamic-registration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index ce564e19157..df8248cdcb1 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -30,7 +30,7 @@ Some of those metadatas are optional in the RFC but required in this context. | Name | Description | Behaviour | Localizable | | ---------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------- | | `client_name` | Human-readable name of the client to be presented to the user | Required | Yes | -| `client_uri` | URL of a web page providing information about the client | Optional | Yes | +| `client_uri` | URL of a web page providing information about the client | Required | Yes | | `logo_uri` | URL that references a logo for the client | Optional | Yes | | `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required, non-empty | No | | `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | From 32c9ead532c0b98c0025c4d7b8e4210b31d85293 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 12 Sep 2024 17:18:54 +0200 Subject: [PATCH 04/14] Rework MSC - makes some metadata optional - better explain how each metadata field is used - better explain what the restrictions on redirect_uris are - remove the signed metadata part - mention the client metadata JSON document alternative --- proposals/2966-oauth2-dynamic-registration.md | 238 ++++++++++++++---- 1 file changed, 185 insertions(+), 53 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index df8248cdcb1..806c21347de 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -1,99 +1,231 @@ # MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix -[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) defines how client should login against a Matrix server using OAuth 2.0. -It assumes the client is known to the authentication server. +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 MSC specifies how Matrix clients should leverage OAuth 2.0 Dynamic Client Registration Protocol ([RFC 7591](https://tools.ietf.org/html/rfc7591)) to register themselves before initiating the login flow. +This MSC specifies how Matrix clients should leverage the OAuth 2.0 Dynamic Client Registration Protocol ([RFC 7591](https://tools.ietf.org/html/rfc7591)) to register themselves before initiating an authorization flow. ## Proposal -If a Matrix server wants to be used by any third-party client, its authentication server must allow dynamic registration of OAuth 2.0 clients. -The client registration endpoint is advertised in the OIDC discovery document and can be used as per [RFC 7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3). +### Prerequisites + +This proposal requires the client to know the following authorization server metadata about the homeserver: + + - `registration_endpoint`: the URL where the user is able to access the client registration endpoint. + +The discovery of the above metadata is out of scope for this MSC and is currently covered by [MSC2965](https://github.com/matrix-org/matrix-doc/pull/2965). ### Client metadata -When registering itself, a client must provide a list of metadata about itself. +In OAuth 2.0, clients have a set of metadata values associated with their client identifier at an authorization server. +These values are used to describe the client to the user and define how the client interacts with the authorization server. + +This MSC specifies what metadata values are required by the Matrix specification and how a client can register itself with a Matrix homeserver to get a client identifier. + +The metadata names are registered in the IANA [OAuth Dynamic Client Registration Metadata](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata) registry, and normative definitions of them are available in their respective RFCs in the registry. + +#### Localizable metadata + +#### `client_uri` and relationship with other URIs + +The `client_uri` metadata is required to be a valid URI. +This URI must use the `https` scheme. + +The host part of the URI must be a public hostname that is not a [public suffix](https://publicsuffix.org). +IP addresses and private hostnames like `localhost` are not allowed. + +It is recommended that the `client_uri` is a web page that provides information about the client. +This page should be able to be accessed without requiring authentication. + +This URI is a common base for all the other URIs in the metadata: those must be either on the same host or on a subdomain of the host of the `client_uri`. +For example, if the `client_uri` is `https://example.com/`, then one of the `redirect_uris` can be `https://example.com/callback` or `https://app.example.com/callback`, but not `https://app.com/callback`. + +#### User-visible metadata values + +The following metadata values should be used by clients to help users identify the client: -As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), some of those metadata values may be localized. + - `client_name`: Human-readable name of the client to be presented to the user + - `logo_uri`: URL that references a logo for the client + - `tos_uri`: URL that points to a human-readable terms of service document for the client + - `policy_uri`: URL that points to a human-readable policy document for the client + +All the URIs must use the `https` scheme and use the `client_uri` as a common base. + +All of these metadata values are optional. + +As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), these metadata values may be localized. +For example: ```json { "client_name": "Digital mailbox", "client_name#en-US": "Digital mailbox", "client_name#en-GB": "Digital postbox", - "client_name#fr": "Boîte aux lettres numérique" + "client_name#fr": "Boîte aux lettres numérique", + "tos_uri": "https://example.com/tos.html", + "tos_uri#fr": "https://example.com/fr/tos.html", + "policy_uri": "https://example.com/policy.html", + "policy_uri#fr": "https://example.com/fr/policy.html" } ``` -Some of those metadatas are optional in the RFC but required in this context. +#### Metadata values required by the OAuth 2.0 authorization grant flow -| Name | Description | Behaviour | Localizable | -| ---------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------- | -| `client_name` | Human-readable name of the client to be presented to the user | Required | Yes | -| `client_uri` | URL of a web page providing information about the client | Required | Yes | -| `logo_uri` | URL that references a logo for the client | Optional | Yes | -| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required, non-empty | No | -| `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | -| `policy_uri` | URL that points to a human-readable policy document for the client | Required | Yes | -| `redirect_uris` | Array of redirection URIs for use in redirect-based flows | Required with the `authorization_code` grant ype | No | -| `response_types` | Array of the OAuth 2.0 response types that the client may use | Defaults to `["code"]` | No | -| `grant_types` | Array of OAuth 2.0 grant types that the client may use | Defaults to `["authorization_code"]` | No | +The following metadata values are required to be present to use the OAuth 2.0 authorization code grant, as described in [MSC2964]: -Other metadata registered in the IANA [OAuth Dynamic Client Registration Metadata](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata) registry might be used and supported by Matrix servers and clients. + - `redirect_uris`: Array of redirection URIs for use in redirect-based flows + - `response_types`: Array of the OAuth 2.0 response types that the client may use + - `grant_types`: Array of OAuth 2.0 grant types that the client may use -### User consent +To use this grant, along with refresh tokens: -When authorizing a third-party client for the first time, the authorization server must ask for explicit user consent and display as much information, preferably localized, about the client as possible. -This includes informations about the publisher, the clients terms of service and its policy. + - the `redirect_uris` must have at least one value + - the `response_types` must include `code` + - the `grant_types` must include `authorization_code` and `refresh_token` -The consent screen must include a human-readable list of the scopes requested by the client. +#### Redirect URI validation -### Metadata signature +The redirect URI plays a critical role in validating the authenticity of the client. +The client 'proves' its identity by demonstrating that it controls the redirect URI. +This is why it is critical to have strict validation of the redirect URI. -To securely identify themselves, clients must send a digitally signed version of their metadata. -This is done by encoding the client metadata in a JWT and signing it. +The `application_type` metadata is used to determine the type of client. +It defaults to `web` if not present, and can be set to `native` to indicate that the client is a native application. -In addition the client metadata mentioned earlier, the JWT payload must include the following: +In all cases, the redirect URI must not have a fragment component. -- `iss`: the entity signing the token. This must allow the authorization server to discover the JWT keys of the issuer. -- `iat`: the timestamp when the JWT was signed -- `exp`: a timestamp after which the JWT isn't valid anymore -- `software_id`: a random string uniquely identifying this instance. A random UUIDv4 is suggested for this field +#### Web clients -This allows client to securely update their metadata without being considered as a new client and re-asking user consent. +`web` clients can use redirect URIs that: -The `software_id` is used to uniquely identify a client and ensure the same `client_id` is returned on subsequent registration. -Each `software_id` is tied to the issuer (`iss`) and therefore subsequent registration must be signed by the same issuer. + - must use the `https` scheme + - must omit the port (to use the default port for https: 443) + - must not use a user or password in the authority component of the URI + - must use the client URI as a common base for the authority component -The issuer keys can be retrieved using its [OIDC discovery document](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) (`/.well-known/openid-configuration`) or its [authorization server metadata](https://tools.ietf.org/html/rfc8414) (`/.well-known/oauth-authorization-server`). -The issuer does not have to be an actual authorization server, but its metadata can include human-readable informations about the issuer. -Those informations can be displayed on the user consent screen to tell the user about the client's publisher. +Examples of valid redirect URIs (with `https://example.com/` as the client URI): -The JWT payload may also include a `software_version` claim denoting the version of the client being registered. -This field should be treated as an opaque string by the authorization server. + - `https://example.com/callback` + - `https://app.example.com/callback` + - `https://example.com/?query=value` -A Matrix server may choose to only allow signed client to be registered. -It might also have an list of trusted issuers for software statements and only allow those to restrict third-party clients. +Examples of invalid redirect URIs (with `https://example.com/` as the client URI): -## Potential issues + - `https://example.com/callback#fragment` + - `https://example.com:8080/callback` + - `http://example.com/callback` + - `http://localhost/` + +#### Native clients + +`native` clients can use three types of redirect URIs: + + 1. Private-Use URI Scheme: + - the scheme must be prefixed with the client URI hostname in reverse-DNS notation. For example, if the client URI is `https://example.com/`, then a valid custom URI scheme would be `com.example.app:/`. + - the URI must not have an authority component. This means it should have a single slash after the scheme, with no hostname, username, or port. + 2. "http" URIs on the loopback interface: + - it must use the `http` scheme + - the host part must be `localhost`, `127.0.0.1`, or `[::1]` + - it must have no port registered. The homeserver will then accept any port number during the authorization flow. + 3. Claimed "https" Scheme URI: + - some operating systems allow apps to claim "https" scheme URIs in the domains they control + - when the browser encounters a claimed URI, instead of the page being loaded in the browser, the native app is launched with the URI supplied as a launch parameter + - the same rules as for `web` clients apply + +These restrictions are the same as defined by [RFC8252 sec. 7](https://tools.ietf.org/html/rfc8252#section-7). + +Examples of valid redirect URIs (with `https://example.com/` as the client URI): + + - `com.example.app:/callback` + - `com.example:/` + - `http://localhost/callback` + - `http://127.0.0.1/callback` + - `http://[::1]/callback` + +Examples of invalid redirect URIs (with `https://example.com/` as the client URI): + + - `example:/callback` + - `com.example.com://callback` + - `https://localhost/callback` + - `http://localhost:1234/callback` -It is unclear how metadata updates should be handled. -If a client changes its `redirect_uris`, should the old ones be considered for a period of time? -If multiple versions of the same client coexist at the same time, should older versions of the software be able to override the metadata of the newer version? +### Dynamic client registration -If an authorization server allows unsigned clients, the number of client registration might explode exponentially. -At the same time, only allowing signed clients can make client development significantly harder. +Before initiating an authorization flow, the client must advertise its metadata to the homeserver to get back a `client_id`. + +This is done through the `registration_endpoint` as described by [RFC7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3). + +To register, the client sends an HTTP POST to the `registration_endpoint` with its metadata as JSON in the body. +For example, the client could send the following registration request: + +```http +POST /register HTTP/1.1 +Content-Type: application/json +Accept: application/json +Server: auth.example.com +``` + +```json +{ + "client_name": "My App", + "client_name#fr": "Mon application", + "client_uri": "https://example.com/", + "logo_uri": "https://example.com/logo.png", + "tos_uri": "https://example.com/tos.html", + "tos_uri#fr": "https://example.com/fr/tos.html", + "policy_uri": "https://example.com/policy.html", + "policy_uri#fr": "https://example.com/fr/policy.html", + "redirect_uris": ["https://app.example.com/callback"], + "response_types": ["code"], + "grant_types": ["authorization_code", "refresh_token"], + "application_type": "web" +} +``` + +The server replies with a JSON object containing the `client_id` allocated, as well as all the metadata values that the server registered. + +With the previous registration request, the server would reply with: + +```json +{ + "client_id": "s6BhdRkqt3", + "client_name": "My App", + + + "client_uri": "https://example.com/", + "logo_uri": "https://example.com/logo.png", + "tos_uri": "https://example.com/tos.html", + "policy_uri": "https://example.com/policy.html", + "redirect_uris": ["https://app.example.com/callback"], + "response_types": ["code"], + "grant_types": ["authorization_code", "refresh_token"], + "application_type": "web" +} +``` + +**Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. + +The client must store the `client_id` for future use. + +## Potential issues + +Because each client on each user device will do its own registration, they will all have different `client_id`s. +This means that the number of client registrations will grow exponentially. +A subsequent MSC could be proposed to identify multiple instances of the same client using signed client metadata. ## Alternatives -None relevant. +An alternative approach would be to have the client host a JSON file containing its metadata and use that URL as the `client_id`. +This is what the following [*OAuth Client ID Metadata Document* draft](https://datatracker.ietf.org/doc/html/draft-parecki-oauth-client-id-metadata-document) proposes. + +This approach has the advantage of being able to use the same `client_id` for different instances of the same client, but it has the disadvantage of requiring the client to host a JSON file on its own domain, as well as difficulties in handling updates to the metadata. ## Security considerations -Nothing prevents intentional collisions in `software_id`. -An attacker could register a `software_id` of another client before its first registration, blocking it from registration. -The registration endpoint should be rate-limited and the failed registration monitored by server administrators to detect such abuses. +TBD ## Unstable prefix None relevant. + +[RFC7591]: https://tools.ietf.org/html/rfc7591 +[MSC2964]: https://github.com/matrix-org/matrix-spec-proposals/pull/2964 From 1ba6ce9ca1372689a6ef5e015cbc75c18bdcdb36 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 9 Dec 2024 09:56:38 +0100 Subject: [PATCH 05/14] Mention the `token_endpoint_auth_method` client metadata --- proposals/2966-oauth2-dynamic-registration.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index 806c21347de..7f5a395017d 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -75,6 +75,9 @@ The following metadata values are required to be present to use the OAuth 2.0 au - `redirect_uris`: Array of redirection URIs for use in redirect-based flows - `response_types`: Array of the OAuth 2.0 response types that the client may use - `grant_types`: Array of OAuth 2.0 grant types that the client may use + - `token_endpoint_auth_method`: String indicator of the requested authentication method for the token endpoint + +The homeserver must support the `none` value for the `token_endpoint_auth_method`, as most Matrix clients are client-side only, do not have a server component, and therefore are public clients. To use this grant, along with refresh tokens: @@ -175,6 +178,7 @@ Server: auth.example.com "policy_uri": "https://example.com/policy.html", "policy_uri#fr": "https://example.com/fr/policy.html", "redirect_uris": ["https://app.example.com/callback"], + "token_endpoint_auth_method": "none", "response_types": ["code"], "grant_types": ["authorization_code", "refresh_token"], "application_type": "web" From 6eb5fdfbc438b8c0e4e12981f8dc82071098a872 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 9 Dec 2024 09:59:31 +0100 Subject: [PATCH 06/14] Update proposals/2966-oauth2-dynamic-registration.md Co-authored-by: Tonkku <4409524+tonkku107@users.noreply.github.com> --- proposals/2966-oauth2-dynamic-registration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index 7f5a395017d..b0e94fc49ac 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -10,7 +10,7 @@ This MSC specifies how Matrix clients should leverage the OAuth 2.0 Dynamic Clie This proposal requires the client to know the following authorization server metadata about the homeserver: - - `registration_endpoint`: the URL where the user is able to access the client registration endpoint. + - `registration_endpoint`: the URL where the client is able to register itself. The discovery of the above metadata is out of scope for this MSC and is currently covered by [MSC2965](https://github.com/matrix-org/matrix-doc/pull/2965). From a67a2e84e8434f4159f82a1c8f8d403fb1b11979 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 16 Jan 2025 13:42:08 +0100 Subject: [PATCH 07/14] State that the homeserver should display the tos_uri and policy_uri --- proposals/2966-oauth2-dynamic-registration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index b0e94fc49ac..d9af0e04522 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -50,6 +50,8 @@ The following metadata values should be used by clients to help users identify t All the URIs must use the `https` scheme and use the `client_uri` as a common base. +If provided by the client, the homeserver should show or link to the `tos_uri` and `policy_uri` to the user. + All of these metadata values are optional. As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), these metadata values may be localized. From d9fd175cc6f59083b514b786c24c251ab75bec09 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 16 Jan 2025 13:42:33 +0100 Subject: [PATCH 08/14] Make the wording for the refresh token clearer --- proposals/2966-oauth2-dynamic-registration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index d9af0e04522..c7ae23cb18e 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -72,7 +72,7 @@ For example: #### Metadata values required by the OAuth 2.0 authorization grant flow -The following metadata values are required to be present to use the OAuth 2.0 authorization code grant, as described in [MSC2964]: +The following metadata values are required to be present to use the OAuth 2.0 authorization code grant and refresh token grant, as described in [MSC2964]: - `redirect_uris`: Array of redirection URIs for use in redirect-based flows - `response_types`: Array of the OAuth 2.0 response types that the client may use @@ -81,7 +81,7 @@ The following metadata values are required to be present to use the OAuth 2.0 au The homeserver must support the `none` value for the `token_endpoint_auth_method`, as most Matrix clients are client-side only, do not have a server component, and therefore are public clients. -To use this grant, along with refresh tokens: +To use this grant: - the `redirect_uris` must have at least one value - the `response_types` must include `code` From a7ddac2674ce4fd987cf18a5edc9a91dc847b39f Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 16 Jan 2025 13:43:20 +0100 Subject: [PATCH 09/14] Clarify that native callbacks with no slashes are allowed --- proposals/2966-oauth2-dynamic-registration.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index c7ae23cb18e..44041c95eac 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -126,11 +126,11 @@ Examples of invalid redirect URIs (with `https://example.com/` as the client URI 1. Private-Use URI Scheme: - the scheme must be prefixed with the client URI hostname in reverse-DNS notation. For example, if the client URI is `https://example.com/`, then a valid custom URI scheme would be `com.example.app:/`. - - the URI must not have an authority component. This means it should have a single slash after the scheme, with no hostname, username, or port. + - the URI must not have an authority component. This means that it must have either a single slash or none immediately following the scheme, with no hostname, username, or port. 2. "http" URIs on the loopback interface: - it must use the `http` scheme - the host part must be `localhost`, `127.0.0.1`, or `[::1]` - - it must have no port registered. The homeserver will then accept any port number during the authorization flow. + - it must have no port registered. The homeserver must then accept any port number during the authorization flow. 3. Claimed "https" Scheme URI: - some operating systems allow apps to claim "https" scheme URIs in the domains they control - when the browser encounters a claimed URI, instead of the page being loaded in the browser, the native app is launched with the URI supplied as a launch parameter @@ -142,6 +142,7 @@ Examples of valid redirect URIs (with `https://example.com/` as the client URI): - `com.example.app:/callback` - `com.example:/` + - `com.example:callback` - `http://localhost/callback` - `http://127.0.0.1/callback` - `http://[::1]/callback` @@ -149,7 +150,7 @@ Examples of valid redirect URIs (with `https://example.com/` as the client URI): Examples of invalid redirect URIs (with `https://example.com/` as the client URI): - `example:/callback` - - `com.example.com://callback` + - `com.example.app://callback` - `https://localhost/callback` - `http://localhost:1234/callback` From 4deb3c8520cb540521f1c9cdd0682ced6cfcc9fc Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 16 Jan 2025 13:47:39 +0100 Subject: [PATCH 10/14] Give an example where the server ignores an unsupported grant type --- proposals/2966-oauth2-dynamic-registration.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index 44041c95eac..b08886e2f83 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -183,12 +183,17 @@ Server: auth.example.com "redirect_uris": ["https://app.example.com/callback"], "token_endpoint_auth_method": "none", "response_types": ["code"], - "grant_types": ["authorization_code", "refresh_token"], + "grant_types": [ + "authorization_code", + "refresh_token", + "urn:ietf:params:oauth:grant-type:token-exchange" + ], "application_type": "web" } ``` The server replies with a JSON object containing the `client_id` allocated, as well as all the metadata values that the server registered. +It must ignore fields, `grant_types` and `response_types` that are not understood by the server. With the previous registration request, the server would reply with: @@ -196,8 +201,6 @@ With the previous registration request, the server would reply with: { "client_id": "s6BhdRkqt3", "client_name": "My App", - - "client_uri": "https://example.com/", "logo_uri": "https://example.com/logo.png", "tos_uri": "https://example.com/tos.html", @@ -209,7 +212,7 @@ With the previous registration request, the server would reply with: } ``` -**Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. +**Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. The server also does not support the `urn:ietf:params:oauth:grant-type:token-exchange` grant type, which is why it is not present in the response. The client must store the `client_id` for future use. From 0e2f0f132f2baeef935842abee80d53e0c84e22c Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 17 Jan 2025 10:08:36 +0100 Subject: [PATCH 11/14] Add security considerations --- proposals/2966-oauth2-dynamic-registration.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index b08886e2f83..8ca7edba58e 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -231,7 +231,15 @@ This approach has the advantage of being able to use the same `client_id` for di ## Security considerations -TBD +The restrictions on the metadata values laid out in this MSC are a best effort to prevent client impersonation, but they are not flawless. + +For web clients, it relies on the client's ability to prove ownership of the redirect URI, which can be guaranteed to some extent by sane DNS management and its use of TLS. +If a client-related domain name hosts an open redirector, it could be used to impersonate the client. + +For native clients, because they can use private-use URI schemes and localhost redirectors, it relies more on the underlying operating system's security model and their application distribution model. +A good example of this is if a mobile client distributed through an app store registers the `app.acme.corp:` scheme in an effort to impersonate "ACME Corp's" app, then "ACME Corp" would have a valid case to take down the malicious app from the app store. + +In both cases, it is crucial for the server to strictly enforce these restrictions and to show as much information about the client as possible to the user so they can make an informed decision. ## Unstable prefix From 2a20e6ded402ad52ea8fc776fb7d19432ab13995 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 22 Jan 2025 13:46:52 +0100 Subject: [PATCH 12/14] must -> MUST, should -> SHOULD, may -> MAY --- proposals/2966-oauth2-dynamic-registration.md | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index 8ca7edba58e..a6094bfd5bf 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -2,7 +2,7 @@ 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 MSC specifies how Matrix clients should leverage the OAuth 2.0 Dynamic Client Registration Protocol ([RFC 7591](https://tools.ietf.org/html/rfc7591)) to register themselves before initiating an authorization flow. +This MSC specifies how Matrix clients SHOULD leverage the OAuth 2.0 Dynamic Client Registration Protocol ([RFC 7591](https://tools.ietf.org/html/rfc7591)) to register themselves before initiating an authorization flow. ## Proposal @@ -28,33 +28,33 @@ The metadata names are registered in the IANA [OAuth Dynamic Client Registration #### `client_uri` and relationship with other URIs The `client_uri` metadata is required to be a valid URI. -This URI must use the `https` scheme. +This URI MUST use the `https` scheme. -The host part of the URI must be a public hostname that is not a [public suffix](https://publicsuffix.org). +The host part of the URI MUST be a public hostname that is not a [public suffix](https://publicsuffix.org). IP addresses and private hostnames like `localhost` are not allowed. It is recommended that the `client_uri` is a web page that provides information about the client. -This page should be able to be accessed without requiring authentication. +This page SHOULD be able to be accessed without requiring authentication. -This URI is a common base for all the other URIs in the metadata: those must be either on the same host or on a subdomain of the host of the `client_uri`. +This URI is a common base for all the other URIs in the metadata: those MUST be either on the same host or on a subdomain of the host of the `client_uri`. For example, if the `client_uri` is `https://example.com/`, then one of the `redirect_uris` can be `https://example.com/callback` or `https://app.example.com/callback`, but not `https://app.com/callback`. #### User-visible metadata values -The following metadata values should be used by clients to help users identify the client: +The following metadata values SHOULD be used by clients to help users identify the client: - `client_name`: Human-readable name of the client to be presented to the user - `logo_uri`: URL that references a logo for the client - `tos_uri`: URL that points to a human-readable terms of service document for the client - `policy_uri`: URL that points to a human-readable policy document for the client -All the URIs must use the `https` scheme and use the `client_uri` as a common base. +All the URIs MUST use the `https` scheme and use the `client_uri` as a common base. -If provided by the client, the homeserver should show or link to the `tos_uri` and `policy_uri` to the user. +If provided by the client, the homeserver SHOULD show or link to the `tos_uri` and `policy_uri` to the user. All of these metadata values are optional. -As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), these metadata values may be localized. +As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), these metadata values MAY be localized. For example: ```json @@ -79,13 +79,13 @@ The following metadata values are required to be present to use the OAuth 2.0 au - `grant_types`: Array of OAuth 2.0 grant types that the client may use - `token_endpoint_auth_method`: String indicator of the requested authentication method for the token endpoint -The homeserver must support the `none` value for the `token_endpoint_auth_method`, as most Matrix clients are client-side only, do not have a server component, and therefore are public clients. +The homeserver MUST support the `none` value for the `token_endpoint_auth_method`, as most Matrix clients are client-side only, do not have a server component, and therefore are public clients. To use this grant: - - the `redirect_uris` must have at least one value - - the `response_types` must include `code` - - the `grant_types` must include `authorization_code` and `refresh_token` + - the `redirect_uris` MUST have at least one value + - the `response_types` MUST include `code` + - the `grant_types` MUST include `authorization_code` and `refresh_token` #### Redirect URI validation @@ -96,16 +96,16 @@ This is why it is critical to have strict validation of the redirect URI. The `application_type` metadata is used to determine the type of client. It defaults to `web` if not present, and can be set to `native` to indicate that the client is a native application. -In all cases, the redirect URI must not have a fragment component. +In all cases, the redirect URI MUST not have a fragment component. #### Web clients `web` clients can use redirect URIs that: - - must use the `https` scheme - - must omit the port (to use the default port for https: 443) - - must not use a user or password in the authority component of the URI - - must use the client URI as a common base for the authority component + - MUST use the `https` scheme + - MUST omit the port (to use the default port for https: 443) + - MUST not use a user or password in the authority component of the URI + - MUST use the client URI as a common base for the authority component Examples of valid redirect URIs (with `https://example.com/` as the client URI): @@ -125,12 +125,12 @@ Examples of invalid redirect URIs (with `https://example.com/` as the client URI `native` clients can use three types of redirect URIs: 1. Private-Use URI Scheme: - - the scheme must be prefixed with the client URI hostname in reverse-DNS notation. For example, if the client URI is `https://example.com/`, then a valid custom URI scheme would be `com.example.app:/`. - - the URI must not have an authority component. This means that it must have either a single slash or none immediately following the scheme, with no hostname, username, or port. + - the scheme MUST be prefixed with the client URI hostname in reverse-DNS notation. For example, if the client URI is `https://example.com/`, then a valid custom URI scheme would be `com.example.app:/`. + - the URI MUST not have an authority component. This means that it MUST have either a single slash or none immediately following the scheme, with no hostname, username, or port. 2. "http" URIs on the loopback interface: - - it must use the `http` scheme - - the host part must be `localhost`, `127.0.0.1`, or `[::1]` - - it must have no port registered. The homeserver must then accept any port number during the authorization flow. + - it MUST use the `http` scheme + - the host part MUST be `localhost`, `127.0.0.1`, or `[::1]` + - it MUST have no port registered. The homeserver MUST then accept any port number during the authorization flow. 3. Claimed "https" Scheme URI: - some operating systems allow apps to claim "https" scheme URIs in the domains they control - when the browser encounters a claimed URI, instead of the page being loaded in the browser, the native app is launched with the URI supplied as a launch parameter @@ -156,7 +156,7 @@ Examples of invalid redirect URIs (with `https://example.com/` as the client URI ### Dynamic client registration -Before initiating an authorization flow, the client must advertise its metadata to the homeserver to get back a `client_id`. +Before initiating an authorization flow, the client MUST advertise its metadata to the homeserver to get back a `client_id`. This is done through the `registration_endpoint` as described by [RFC7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3). @@ -193,7 +193,7 @@ Server: auth.example.com ``` The server replies with a JSON object containing the `client_id` allocated, as well as all the metadata values that the server registered. -It must ignore fields, `grant_types` and `response_types` that are not understood by the server. +It MUST ignore fields, `grant_types` and `response_types` that are not understood by the server. With the previous registration request, the server would reply with: @@ -214,7 +214,7 @@ With the previous registration request, the server would reply with: **Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. The server also does not support the `urn:ietf:params:oauth:grant-type:token-exchange` grant type, which is why it is not present in the response. -The client must store the `client_id` for future use. +The client MUST store the `client_id` for future use. ## Potential issues From c7e55ec3f98d6991f7ad4a4c035fb15f01945198 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 22 Jan 2025 13:47:21 +0100 Subject: [PATCH 13/14] Clarify the client should store the client_id --- proposals/2966-oauth2-dynamic-registration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index a6094bfd5bf..713d2da628e 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -215,6 +215,7 @@ With the previous registration request, the server would reply with: **Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. The server also does not support the `urn:ietf:params:oauth:grant-type:token-exchange` grant type, which is why it is not present in the response. The client MUST store the `client_id` for future use. +It SHOULD reuse the `client_id` for all future authorization requests done against the same homeserver. ## Potential issues From fe4ef694d5ec62fb4cfb44b983c02a80884e45ad Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 22 Jan 2025 13:57:46 +0100 Subject: [PATCH 14/14] Simplify definition of client_uri, already covered by the RFC --- proposals/2966-oauth2-dynamic-registration.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/proposals/2966-oauth2-dynamic-registration.md b/proposals/2966-oauth2-dynamic-registration.md index 713d2da628e..632fb2f0bb6 100644 --- a/proposals/2966-oauth2-dynamic-registration.md +++ b/proposals/2966-oauth2-dynamic-registration.md @@ -27,14 +27,8 @@ The metadata names are registered in the IANA [OAuth Dynamic Client Registration #### `client_uri` and relationship with other URIs -The `client_uri` metadata is required to be a valid URI. -This URI MUST use the `https` scheme. - -The host part of the URI MUST be a public hostname that is not a [public suffix](https://publicsuffix.org). -IP addresses and private hostnames like `localhost` are not allowed. - -It is recommended that the `client_uri` is a web page that provides information about the client. -This page SHOULD be able to be accessed without requiring authentication. +Per [RFC 7591](https://tools.ietf.org/html/rfc7591), the `client_uri` MUST be a valid URL that SHOULD give the user more information about the client. +This URL SHOULD NOT require authentication to access. This URI is a common base for all the other URIs in the metadata: those MUST be either on the same host or on a subdomain of the host of the `client_uri`. For example, if the `client_uri` is `https://example.com/`, then one of the `redirect_uris` can be `https://example.com/callback` or `https://app.example.com/callback`, but not `https://app.com/callback`.