Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC2967: API scopes #2967

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
95 changes: 95 additions & 0 deletions proposals/2967-api-scopes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# 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).

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.

## 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.

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 a few scopes to cover existing use cases.

### Scope format

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 |

For future MSCs that build on this namespace unstable sub divisions should be used whilst in development:

e.g. `urn:matrix:com.example.mscXXXX.foo:something` or `urn:matrix:client:com.example.mscXXXX.something`

### Allocated scopes

#### Full API read/write access

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. |

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still true after refresh tokens (MSC2918)? I thought we did a bunch of work in Synapse related to this recently, but maybe I'm confusing different types of tokens.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In OAuth 2.0 there is no such thing as a session and so a mapping cannot be handled using the same mechanism.

In OIDC they define a sid (Session ID) claim within the id_token in the Front-Channel Logout spec (also referenced in other specs)

I would also like to mention that since clients are expected to use dynamic registration, client_ids resemble device IDs quite a bit


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 |
| - | - | - |
| `urn:matrix:client:device:<device ID>` | 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.

### Future scopes

Exact scopes for the whole API are intentionally not specified in this MSC.

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:

- `urn:matrix:client:api:<permission>` or `urn:matrix:client:api:<permission>:*` - grant limited access to the client API in all rooms. Permissions could be read, write, delete, append.
- `urn:matrix:client:api:read:<resource>` - 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.

## 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.

## 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 namespace prefix and sub divisions are open to debate.

## Security considerations

As we are just representing existing access models there shouldn't be anything special.

## Unstable prefix

While this feature is in development the following unstable scope prefixes should be used:

- `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client`