Skip to content
Merged
Changes from 14 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a2e9656
API Scopes MSC
sandhose Jan 14, 2021
544d75b
Proposed insufficient privilege response format
hughns May 16, 2022
d49f2d8
Remove realm as not required
hughns May 18, 2022
23c7638
Clarifications + update on latest device management proposal
hughns Jul 31, 2022
b609c2b
Revised namespace structure + unstable prefixes
hughns Aug 3, 2022
f07b466
Revise prefix for device ID
hughns Aug 3, 2022
1ce049e
Reference to MSC3861 + cleanup
hughns Aug 5, 2022
5c57507
Add scope for guest access and tidy up
hughns Nov 17, 2022
5afb697
No need for UIA scope
hughns Feb 16, 2023
8ec2d7c
Update proposals/2967-api-scopes.md
hughns Jul 28, 2023
8539ab2
Clarification about encoding of device ID within URN scope
hughns May 10, 2024
0666b24
Merge branch 'matrix-org:main' into msc/sandhose/api-scopes
sandhose Sep 3, 2024
f65aef3
Rework MSC
sandhose Sep 4, 2024
660946a
Update proposals/2967-api-scopes.md
sandhose Mar 5, 2025
4dd433f
Reword as dbkr suggested
sandhose Mar 13, 2025
79845f5
Reword how unstable subdivisions are used
sandhose Mar 13, 2025
49550fe
Remove confusing sentence
sandhose Mar 13, 2025
14b962c
Gather all the links at the bottom of the document
sandhose Mar 13, 2025
58f2398
Tyding up, define exactly how device IDs are handled
sandhose Mar 14, 2025
e7531fa
Don't use a table for a single row
sandhose Mar 14, 2025
acc8e91
Typo
sandhose Mar 14, 2025
1304203
Fix math rendering
sandhose Mar 14, 2025
6623b96
Fix the math
sandhose Mar 18, 2025
1ddd733
Minor rewording on device uniqueness
sandhose Mar 18, 2025
a33d1e3
Simplify wording around the ASCII range
sandhose Mar 18, 2025
0800ea6
Typo
sandhose Mar 18, 2025
a7bb99c
Scope vs scope token is confusing
sandhose Mar 18, 2025
abbae1e
Reword how the device ID is requested
sandhose Mar 18, 2025
082625d
Explain why we keep the device ID generation on the client
sandhose Mar 25, 2025
089a789
MSCXXXX is a better placeholder
sandhose Mar 26, 2025
858b7be
The scope MUST have a device ID
sandhose Mar 26, 2025
c9f8690
Clarify that device IDs are still unique per user
sandhose Mar 26, 2025
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
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 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:*`

#### Device ID handling
Copy link
Member

Choose a reason for hiding this comment

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

Hm. I'm surprised that the specifics of the Device ID handling scope is included in this MSC, which otherwise is the framework for defining scopes in general. Is this because this scope is compulsory for OIDC to work? If so, we should say so. If not, at the least, we should say that the scope is defined here as a concrete example of how scopes would work... or failing that, split it into a separate MSC.

If it /is/ primarily intended example of the framework, it just feels a bit weird to also be speccing specific behaviour at the same time - wouldn't it be better to give a fake example, and then clearly separate the Device ID management proposal somehow?

I have a feeling i've missed something here that explains why this isn't completely out of place :D

Copy link
Member Author

Choose a reason for hiding this comment

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

At a high level, this MSC defines two things:

  • a general shape for scopes (including future ones with unstable prefixes)
  • an initial set of scopes: one for wide access to the C-S API, another to specify the device

I have to include somewhere that it is now always the responsibility of the client to allocate a device, but I'm unsure where the right place for this is?

Copy link
Member

Choose a reason for hiding this comment

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

it's fine here imho


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.

Copy link
Member Author

Choose a reason for hiding this comment

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

Technically yes, in practice no as MSC2918-style refresh tokens are almost not adopted by anyone. Is it worth clarifying here?


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

Choose a reason for hiding this comment

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

The client can then bind the device ID to the grant

What does this actually mean in practice? For example, does it mean that when I call /sync using an access token corresponding to this grant, then I will receive to-device messages sent to the given device ID? If so, can you say so explicitly?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm unclear whether this MSC should define what being associated to a particular device means? This is binding (or creating) a 'Matrix device' as defined by the spec; I don't think the impact it has on the rest of the C-S API should be defined in this MSC?

Copy link
Member

Choose a reason for hiding this comment

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

the problem is that the words "bind" and "grant" do not currently appear in the matrix spec (at least in this context), so yes, I think we do need to define this better. My question above about to-device messages is an important one, which I'm still not clear on the answer to.

If my assumptions are correct, then we could fix this by adding something along the lines of:

Once the device ID is bound to the grant in this way, any access tokens corresponding to the grant are also associated with the given device ID. This means, for example, that /sync calls made with an access token corresponding to the grant will return to-device messages sent to the given device ID.

Copy link
Member Author

@sandhose sandhose Mar 18, 2025

Choose a reason for hiding this comment

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

Once the device ID is bound to the grant

This makes it sound like 'binding' is dynamic though?

I've reworded the whole section to avoid this problem, removing the unnecessary 1-row table as well in abbae1e, wdyt?


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