Skip to content

Commit d83a46e

Browse files
sandhosehughnstonkku107richvdhanoadragon453
authored
MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix (#2966)
* OAuth 2.0 Dynamic Registration MSC * contacts is required non-empty * Make client_uri mandatory * 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 * Mention the `token_endpoint_auth_method` client metadata * Update proposals/2966-oauth2-dynamic-registration.md Co-authored-by: Tonkku <4409524+tonkku107@users.noreply.github.com> * State that the homeserver should display the tos_uri and policy_uri * Make the wording for the refresh token clearer * Clarify that native callbacks with no slashes are allowed * Give an example where the server ignores an unsupported grant type * Add security considerations * must -> MUST, should -> SHOULD, may -> MAY * Clarify the client should store the client_id * Simplify definition of client_uri, already covered by the RFC * Explain the point of the MSC earlier Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Remove empty section * Explicitly state that the client_uri is required * Apply suggestions from code review Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Fix the web/native client sub-sub-sub sections * Clarify the localhost port-less redirect URIs * The server should return a 201 on successful registration * Explain better the restrictions on URIs * Allow custom ports in the redirect URI * Client regs won't grow exponentially * Explain how to mitigate the problem of client registrations growing over time. * Add missing metadata in the dynamic registration response * Make 'metadata localization' its own sub-sub-sub-sub-section Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> * Server may still deduplicate registrations Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> * Suggest different strategies to mitigate the growing number of client registrations * Let the server delete client registrations that have no active sessions * Really, shoud MUST do a new client reg * Make sure the summary doesn't sound authoritative * Put the links at the end of the file * Explain what is Matrix-specific, what is not --------- Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com> Co-authored-by: Tonkku <4409524+tonkku107@users.noreply.github.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
1 parent 52db4c6 commit d83a46e

File tree

1 file changed

+267
-0
lines changed

1 file changed

+267
-0
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
# MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix
2+
3+
This proposal is part of the broader [MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC][MSC3861].
4+
5+
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.
6+
7+
In brief, once a client has obtained the homeserver's OAuth 2.0 metadata per [MSC2965], and before it can initiate an authorization request per [MSC2964], the client needs a `client_id`, which it can obtain by registering itself with that homeserver.
8+
9+
## Proposal
10+
11+
### Prerequisites
12+
13+
This proposal requires the client to know the following authorization server metadata about the homeserver:
14+
15+
- `registration_endpoint`: the URL where the client is able to register itself.
16+
17+
The discovery of the above metadata is out of scope for this MSC and is currently covered by [MSC2965].
18+
19+
### Client metadata
20+
21+
In OAuth 2.0, clients have a set of metadata values associated with their client identifier at an authorization server.
22+
These values are used to describe the client to the user and define how the client interacts with the authorization server.
23+
24+
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.
25+
26+
None of the metadata values are specific to Matrix: they are all registered by various specificaitons in the [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.
27+
28+
29+
#### `client_uri` and relationship with other URIs
30+
31+
Per [RFC 7591](https://tools.ietf.org/html/rfc7591), the `client_uri` MUST point to a valid web page that SHOULD give the user more information about the client.
32+
This URL MUST use the `https` scheme and SHOULD NOT require authentication to access.
33+
It MUST NOT use a user or password in the authority component of the URI.
34+
35+
The `client_uri` is required and the server MAY reject client registrations with an invalid or missing `client_uri`.
36+
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`.
37+
The port number, path and query components MAY be different.
38+
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`.
39+
40+
#### User-visible metadata values
41+
42+
The following metadata values SHOULD be used by clients to help users identify the client:
43+
44+
- `client_name`: Human-readable name of the client to be presented to the user
45+
- `logo_uri`: URL that references a logo for the client
46+
- `tos_uri`: URL that points to a human-readable terms of service document for the client
47+
- `policy_uri`: URL that points to a human-readable policy document for the client
48+
49+
All the URIs MUST use the `https` scheme and use the `client_uri` as a common base, as defined by the previous section.
50+
51+
If provided by the client, the homeserver SHOULD show or link to the `tos_uri` and `policy_uri` to the user.
52+
They MUST NOT use a user or password in the authority component of the URI.
53+
They MUST point to a valid web page and SHOULD NOT require authentication to access.
54+
55+
All of these metadata values are optional.
56+
57+
##### Metadata localization
58+
59+
As per [RFC 7591 sec. 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), these metadata values MAY be localized.
60+
For example:
61+
62+
```json
63+
{
64+
"client_name": "Digital mailbox",
65+
"client_name#en-US": "Digital mailbox",
66+
"client_name#en-GB": "Digital postbox",
67+
"client_name#fr": "Boîte aux lettres numérique",
68+
"tos_uri": "https://example.com/tos.html",
69+
"tos_uri#fr": "https://example.com/fr/tos.html",
70+
"policy_uri": "https://example.com/policy.html",
71+
"policy_uri#fr": "https://example.com/fr/policy.html"
72+
}
73+
```
74+
75+
#### Metadata values required by the OAuth 2.0 authorization grant flow
76+
77+
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]:
78+
79+
- `redirect_uris`: Array of redirection URIs for use in redirect-based flows
80+
- `response_types`: Array of the OAuth 2.0 response types that the client may use
81+
- `grant_types`: Array of OAuth 2.0 grant types that the client may use
82+
- `token_endpoint_auth_method`: String indicator of the requested authentication method for the token endpoint
83+
84+
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.
85+
86+
To use this grant:
87+
88+
- the `redirect_uris` MUST have at least one value
89+
- the `response_types` MUST include `code`
90+
- the `grant_types` MUST include `authorization_code` and `refresh_token`
91+
92+
#### Redirect URI validation
93+
94+
The redirect URI plays a critical role in validating the authenticity of the client.
95+
The client 'proves' its identity by demonstrating that it controls the redirect URI.
96+
This is why it is critical to have strict validation of the redirect URI.
97+
98+
The `application_type` metadata is used to determine the type of client.
99+
It defaults to `web` if not present, and can be set to `native` to indicate that the client is a native application.
100+
101+
In all cases, the redirect URI MUST NOT have a fragment component.
102+
103+
##### Web clients
104+
105+
`web` clients can use redirect URIs that:
106+
107+
- MUST use the `https` scheme
108+
- MUST NOT use a user or password in the authority component of the URI
109+
- MUST use the client URI as a common base for the authority component, as defined previously
110+
- MAY include an `application/x-www-form-urlencoded` formatted query component
111+
112+
Examples of valid redirect URIs (with `https://example.com/` as the client URI):
113+
114+
- `https://example.com/callback`
115+
- `https://app.example.com/callback`
116+
- `https://example.com:5173/?query=value`
117+
118+
Examples of invalid redirect URIs (with `https://example.com/` as the client URI):
119+
120+
- `https://example.com/callback#fragment`
121+
- `http://example.com/callback`
122+
- `http://localhost/`
123+
124+
##### Native clients
125+
126+
`native` clients can use three types of redirect URIs:
127+
128+
1. Private-Use URI Scheme:
129+
- 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:/`.
130+
- 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.
131+
2. "http" URIs on the loopback interface:
132+
- it MUST use the `http` scheme
133+
- the host part MUST be `localhost`, `127.0.0.1`, or `[::1]`
134+
- it MUST have no port in the registered redirect URI. The homeserver MUST then accept any port number during the authorization flow.
135+
3. Claimed "https" Scheme URI:
136+
- some operating systems allow apps to claim "https" scheme URIs in the domains they control
137+
- 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
138+
- the same rules as for `web` clients apply
139+
140+
These restrictions are the same as defined by [RFC8252 sec. 7](https://tools.ietf.org/html/rfc8252#section-7).
141+
142+
Examples of valid redirect URIs (with `https://example.com/` as the client URI):
143+
144+
- `com.example.app:/callback`
145+
- `com.example:/`
146+
- `com.example:callback`
147+
- `http://localhost/callback`
148+
- `http://127.0.0.1/callback`
149+
- `http://[::1]/callback`
150+
151+
Examples of invalid redirect URIs (with `https://example.com/` as the client URI):
152+
153+
- `example:/callback`
154+
- `com.example.app://callback`
155+
- `https://localhost/callback`
156+
- `http://localhost:1234/callback`
157+
158+
### Dynamic client registration
159+
160+
Before initiating an authorization flow, the client MUST advertise its metadata to the homeserver to get back a `client_id`.
161+
162+
This is done through the `registration_endpoint` as described by [RFC7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3).
163+
164+
**Note**: Nothing in the usage of the `registration_endpoint` is specific to Matrix. The behaviours described here are the same as the ones defined in [RFC7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3).
165+
166+
To register, the client sends an HTTP POST to the `registration_endpoint` with its metadata as JSON in the body.
167+
For example, the client could send the following registration request:
168+
169+
```http
170+
POST /register HTTP/1.1
171+
Content-Type: application/json
172+
Accept: application/json
173+
Server: auth.example.com
174+
```
175+
176+
```json
177+
{
178+
"client_name": "My App",
179+
"client_name#fr": "Mon application",
180+
"client_uri": "https://example.com/",
181+
"logo_uri": "https://example.com/logo.png",
182+
"tos_uri": "https://example.com/tos.html",
183+
"tos_uri#fr": "https://example.com/fr/tos.html",
184+
"policy_uri": "https://example.com/policy.html",
185+
"policy_uri#fr": "https://example.com/fr/policy.html",
186+
"redirect_uris": ["https://app.example.com/callback"],
187+
"token_endpoint_auth_method": "none",
188+
"response_types": ["code"],
189+
"grant_types": [
190+
"authorization_code",
191+
"refresh_token",
192+
"urn:ietf:params:oauth:grant-type:token-exchange"
193+
],
194+
"application_type": "web"
195+
}
196+
```
197+
198+
The server MUST ignore `grant_types` and `response_types` that it does not understand.
199+
200+
Upon successful registration, the server replies with an *HTTP 201 Created* response, with a JSON object containing the allocated `client_id` and all the registered metadata values.
201+
202+
With the previous registration request, the server would reply with:
203+
204+
```json
205+
{
206+
"client_id": "s6BhdRkqt3",
207+
"client_name": "My App",
208+
"client_uri": "https://example.com/",
209+
"logo_uri": "https://example.com/logo.png",
210+
"tos_uri": "https://example.com/tos.html",
211+
"policy_uri": "https://example.com/policy.html",
212+
"redirect_uris": ["https://app.example.com/callback"],
213+
"token_endpoint_auth_method": "none",
214+
"response_types": ["code"],
215+
"grant_types": ["authorization_code", "refresh_token"],
216+
"application_type": "web"
217+
}
218+
```
219+
220+
**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.
221+
222+
The client MUST store the `client_id` for future use.
223+
224+
To avoid the number of client registrations growing over time, the server MAY choose to delete client registrations that don't have an active session.
225+
The server MUST NOT delete client registrations that have an active session.
226+
227+
Clients MUST perform a new client registration at the start of each authorization flow.
228+
229+
## Potential issues
230+
231+
Because each client on each user device will do its own registration, they may all have different `client_id`s.
232+
This means that the server may store the same client registration multiple times, which could lead to a large number of client registrations.
233+
234+
This can be mitigated by de-duplicating client registrations that have identical metadata.
235+
By doing so, different users on different devices using the same client can share a single `client_id`, reducing the overall number of registrations.
236+
237+
A subsequent MSC could be proposed to reliably identify multiple instances of the same client beyond a strict comparison using signed client metadata.
238+
239+
## Alternatives
240+
241+
An alternative approach would be to have the client host a JSON file containing its metadata and use that URL as the `client_id`.
242+
This is what the [*OAuth Client ID Metadata Document* draft](https://datatracker.ietf.org/doc/html/draft-parecki-oauth-client-id-metadata-document) proposes.
243+
244+
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.
245+
246+
## Security considerations
247+
248+
The restrictions on the metadata values laid out in this MSC are a best effort to prevent client impersonation, but they are not flawless.
249+
250+
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.
251+
If a client-related domain name hosts an open redirector, it could be used to impersonate the client.
252+
253+
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.
254+
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.
255+
256+
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.
257+
258+
## Unstable prefix
259+
260+
None relevant.
261+
262+
[RFC7591]: https://tools.ietf.org/html/rfc7591
263+
[RFC7592]: https://tools.ietf.org/html/rfc7592
264+
[RFC9126]: https://tools.ietf.org/html/rfc9126
265+
[MSC2964]: https://github.com/matrix-org/matrix-spec-proposals/pull/2964
266+
[MSC2965]: https://github.com/matrix-org/matrix-spec-proposals/pull/2965
267+
[MSC3861]: https://github.com/matrix-org/matrix-spec-proposals/pull/3861

0 commit comments

Comments
 (0)