Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions proposals/4341-device-authorization-grant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# MSC4341: Support for RFC 8628 Device Authorization Grant

The current [OAuth 2.0 API](https://spec.matrix.org/v1.15/client-server-api/#oauth-20-api) requires the user to complete
authentication using a web browser on the device where the Matrix client is running.

This can be problematic if the device does not have a built in web browser or the user wishes to use a different device.
It also causes issues in scenarios where catching the redirect back to the client is hard, like in CLI apps, or
desktop apps with no redirect custom schemes.

[RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628) defines the OAuth 2.0 Device Authorization Grant which can be
used for this purpose.

## Proposal

Add the [RFC 8628 OAuth 2.0 Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) to the [list of supported
grant types](https://spec.matrix.org/v1.15/client-server-api/#grant-types) in the Client-Server API.

This grant requires the client to know the following authorization server metadata:

- `grant_types_supported` - this would include `urn:ietf:params:oauth:grant-type:device_code`
- `device_authorization_endpoint` - this would be added to the [table of fields for the 200 response](https://spec.matrix.org/v1.15/client-server-api/#server-metadata-discovery)
- `token_endpoint` - this is already included in the spec

To use this grant, homeservers and clients MUST:

- Support the device authorization grant as per RFC 8628.
- Support the refresh token grant.

The [login flow section](https://spec.matrix.org/v1.15/client-server-api/#login-flow) would need to be updated to
reflect that more than one login grant type exists.

As with the existing authorization code grant, when authorization is granted to a client, the homeserver MUST issue a
refresh token to the client in addition to the access token.

The access token and refresh token should have the same lifetime constraints as described for the authorization
code grant in the current [spec](https://spec.matrix.org/v1.15/client-server-api/#refresh-token-grant).

### Sample flow

The user wishes to login to a Matrix client on a device that doesn't have a web browser built in (e.g. a TV), but wishes
to complete the login on another device (e.g. a smartphone).

1. The Matrix client [discovers the OAuth 2.0 server metadata](https://spec.matrix.org/v1.15/client-server-api/#server-metadata-discovery).

This step is as per the current Matrix spec, but as per [RFC 8628 section 4](https://datatracker.ietf.org/doc/html/rfc8628#section-4)
it should include the value `urn:ietf:params:oauth:grant-type:device_code` in the `grant_types_supported` field and specify
a `device_authorization_endpoint` field.

2. The Matrix client [registers itself as a client with the homeserver](https://spec.matrix.org/v1.15/client-server-api/#client-registration).

This step is as per the current Matrix spec.

3. The Matrix client sends a Device Authorization Request to the `device_authorization_endpoint` as per [RFC 8628 section 3.1](https://datatracker.ietf.org/doc/html/rfc8628#section-3.1).

The `client_id` should be as per the registration step above, and the `scope` as described in the current [spec](https://spec.matrix.org/v1.15/client-server-api/#scope).

e.g.

```http
POST /oauth2/device HTTP/1.1
Host: account.matrix.org
Content-Type: application/x-www-form-urlencoded

client_id=my_client_id&scope=urn%3Amatrix%3Aclient%3Aapi%3A%2A%20urn%3Amatrix%3Aclient%3Adevice%3AABCDEGH
```

4. The homeserver responds to the Matrix client with the Device Authorization Response as per [RFC 8628 section 3.2](https://datatracker.ietf.org/doc/html/rfc8628#section-3.2).

For example:

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code": "WDJB-MJHT",
"verification_uri": "https://account.matrix.org/link",
"verification_uri_complete": "https://account.matrix.org/link?user_code=WDJB-MJHT",
"expires_in": 1800,
"interval": 5
}
```

It is recommended that the server provides a `verification_uri_complete` such that the user does not need to type in the
`user_code`.

5. The Matrix client device conveys the returned `verification_uri_complete` (and/or `verification_uri`+`user_code`) to
the user.

Exactly how the client does this depends on the specific device characteristics and use case.

For example, for a CLI application the `verification_uri` and `user_code` could be displayed as text for the user to
type into their other device.

Or, another example would be the `verification_uri_complete` (with fallback to the `verification_uri`) could be encoded
and displayed as a QR code for scanning on the other device (e.g. on a TV).

6. The user opens the `verification_uri_complete` (or `verification_uri`) on their other device that has a web browser.

The user then completes authentication and authorization for the login.

7. Whilst the user is doing this, the Matrix client starts polling the `token_endpoint` for an outcome.

Frequency of polling is determined by the `interval` value returned in the Device Authorization Response from step 4.

The poll request made by the client is the Device Access Token Request from [RFC 8628 section 3.4](https://datatracker.ietf.org/doc/html/rfc8628#section-3.4).

e.g.

```http
POST /oauth2/token HTTP/1.1
Host: account.matrix.org
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS&client_id=my_client_id
```

The server in turn responds with the Device Access Token Response as per [RFC 8628 section 3.5](https://datatracker.ietf.org/doc/html/rfc8628#section-3.5).

Whilst the authorization is still outstanding a `authorization_pending` (or `slow_down` in the case of rate limiting)
error code will be returned.

If the authorization is rejected then the `access_denied` error code will be returned.

If the authorization does not complete within the `expires_in` timeframe then the `expired_token` error code will be returned.

For a successful authorization the response will be an access token and refresh token as described in the current Matrix
[spec](https://spec.matrix.org/v1.15/client-server-api/#login-flow).

8. The Matrix client refreshes the access token with the refresh token grant when it expires.

This is as per the current spec.

9. The Matrix client revokes the tokens when the users wants to log out of the client.

This is as per the current spec.

## Potential issues

Some literature refers to the Device Authorization Grant as the
[Device Code](https://oauth.net/2/grant-types/device-code/) grant type or [Device Flow](https://curity.io/resources/learn/oauth-device-flow/).
This MSC uses the name from the actual RFC.

Otherwise, none identified.

## Alternatives

I'm not aware of any other standardised OAuth grant types that would be suitable as an alternative.

### Requiring support for the new grant type

We could make it mandatory that new grant type is supported by Matrix homeservers.

As currently proposed it is optional and discoverable via the `grant_types_supported` metadata.

### Make `verification_uri_complete` be mandatory

RFC 8628 makes makes `verification_uri_complete` optional, but we could make it mandatory. This could improve the UX for some
use cases.

## Security considerations

[RFC 8628 section 5](https://datatracker.ietf.org/doc/html/rfc8628#section-5) contains various security considerations
that homeserver and client implementors should consider.

Additionally, [RFC 9700](https://datatracker.ietf.org/doc/html/rfc9700) Best Current Practice for OAuth 2.0 Security
mentions clickjacking as a consideration for the server and advises on appropriate measures.

## Unstable prefix

Although the response from the server metadata discovery endpoint is modified, because
[we already defined it](https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv1auth_metadata) as being
[RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414) it isn't appropriate to introduce unstable prefixes.

## Dependencies

None.