Skip to content

Commit b2ea1a7

Browse files
sandhosehughnsclokepturt2livedbkr
authored
MSC2967: API scopes (#2967)
* API Scopes MSC * Proposed insufficient privilege response format * Remove realm as not required * Clarifications + update on latest device management proposal * Revised namespace structure + unstable prefixes * Revise prefix for device ID * Reference to MSC3861 + cleanup * Add scope for guest access and tidy up * No need for UIA scope * Update proposals/2967-api-scopes.md Co-authored-by: Patrick Cloke <clokep@users.noreply.github.com> * Clarification about encoding of device ID within URN scope * Rework MSC - Remove insufficient privilege response - Remove guest scopes - Reword some parts * Update proposals/2967-api-scopes.md Co-authored-by: Travis Ralston <travpc@gmail.com> * Reword as dbkr suggested * Reword how unstable subdivisions are used * Remove confusing sentence * Gather all the links at the bottom of the document * Tyding up, define exactly how device IDs are handled * Don't use a table for a single row * Typo Co-authored-by: David Baker <dbkr@users.noreply.github.com> * Fix math rendering * Fix the math * Minor rewording on device uniqueness Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Simplify wording around the ASCII range Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Typo Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Scope vs scope token is confusing Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Reword how the device ID is requested * Explain why we keep the device ID generation on the client * MSCXXXX is a better placeholder Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> * The scope MUST have a device ID * Clarify that device IDs are still unique per user Co-authored-by: Patrick Cloke <clokep@users.noreply.github.com> --------- Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com> Co-authored-by: Patrick Cloke <clokep@users.noreply.github.com> Co-authored-by: Travis Ralston <travpc@gmail.com> Co-authored-by: David Baker <dbkr@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 d83a46e commit b2ea1a7

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

proposals/2967-api-scopes.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# MSC2967: API scopes
2+
3+
This proposal is part of the broader [MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC][MSC3861].
4+
5+
When a user signs in with a Matrix client, it currently gives the client full access to their Matrix account.
6+
7+
This proposal introduces access scopes to allow restricting client access to only part(s) of the Matrix client API.
8+
9+
## Proposal
10+
11+
[MSC2964] introduces the usage of the OAuth 2.0 authorization code grant to authenticate against a Matrix homeserver.
12+
13+
An OAuth 2.0 grant has a scope associated to it which provides a framework for obtaining user consent.
14+
15+
The framework encourages the practise of obtaining additional use consent when a client asks for a new scope that was not granted previously.
16+
17+
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.
18+
19+
### Scope format
20+
21+
All scopes related to Matrix should start with `urn:matrix:` and use the `:` delimiter for further sub-division.
22+
23+
Scopes related to mapping of Client-Server API access levels should start with `urn:matrix:client:`.
24+
25+
For future MSCs that build on this namespace, unstable subdivisions should be used whilst in development.
26+
27+
For example, if MSCXXXX wants to introduce the `urn:matrix:client:foo` scope, it could use `urn:matrix:client:com.example.mscXXXX.foo` during development.
28+
If it needs to introduce multiple scopes, like `urn:matrix:client:foo` and `urn:matrix:client:bar`, it could use `urn:matrix:client:com.example.mscXXXX:foo` and `urn:matrix:client:com.example.mscXXXX:bar`.
29+
30+
### Allocated scopes
31+
32+
#### Full API read/write access
33+
34+
To support the existing semantic of granting full access to the Matrix C-S API the following scope is assigned:
35+
36+
| Scope | Purpose |
37+
| - | - |
38+
| `urn:matrix:client:api:*` | Grants full access to the Client-Server API |
39+
40+
In the future, a client would request more specific actions when required. e.g. something like `urn:matrix:client:api:read:*`
41+
42+
#### Device ID handling
43+
44+
Presently a device ID is typically generated by the homeserver and is associated with a specific series of access tokens.
45+
46+
This MSC proposes that the Matrix client is responsible for generating/allocating a device ID.
47+
A client can create a new device ID by generating a random string and asking for its associated scope on login.
48+
A client can adopt and rehydrate an existing device ID by asking for its associated scope on login.
49+
50+
The client must then add the requested device ID to the grant by including following token in the requested scope:
51+
`urn:matrix:client:device:<device ID>`, where `<device ID>` is the requested device ID.
52+
53+
There MUST be exactly one `urn:matrix:client:device:<device ID>` token in the requested scope.
54+
55+
When generating a new device ID, the client SHOULD generate a random string with enough entropy.
56+
It SHOULD only use characters from the unreserved character list defined by [RFC3986]:
57+
58+
> unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~"
59+
60+
Using this alphabet, a 10 character string is enough to stand a sufficient chance of being unique per user.
61+
The homeserver MAY reject a request for a device ID that is not long enough or contains characters outside the unreserved list.
62+
63+
In any case it MUST only use characters allowed by the OAuth 2.0 scope definition in [RFC6749] section 3.3,
64+
which is defined as the following ASCII ranges: `%x21 / %x23-5B / %x5D-7E`, i.e:
65+
66+
- alphanumeric characters (`A-Z`, `a-z`, `0-9`)
67+
- the following characters: `! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ \` { | } ~`
68+
69+
### Future scopes
70+
71+
Exact scopes for the whole API are intentionally not specified in this MSC.
72+
73+
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.
74+
75+
Some thoughts/ideas for possible scopes are:
76+
77+
- `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.
78+
- `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`
79+
80+
New MSCs should be created for proposing and discussing such new scopes.
81+
82+
## Potential issues
83+
84+
### Device ID collision
85+
86+
The Device ID handling involves a change in where device IDs are generated.
87+
Because the device ID is now generated by the client, it is possible to have a device ID collision.
88+
89+
Requiring enough entropy on the device ID ensures that the device ID is unique.
90+
With a 66 character alphabet and a 10 character device ID, the probability of a collision between 100 million devices is around 0.3%:
91+
92+
$$N = 66^{10}$$
93+
$$K = 10^{8}$$
94+
$$P \approx 1 - e^{-\frac{K^2}{2N}}$$
95+
$$P \approx 0.00318$$
96+
97+
This does also restrict the possible alphabet of device IDs, which was not restricted before.
98+
99+
### Generating the device ID on the client
100+
101+
This proposal effectively changes where the device ID is generated, from "most of the time on the server" to "every time on the client."
102+
103+
This doesn't introduce a new mechanism, as clients could already select a device ID instead of letting the server generate one.
104+
105+
One of the original motivation for this change was to adopt existing OAuth 2.0 mechanisms as much as possible.
106+
This meant not introducing Matrix-specific parameters (hence encoding the device ID in the scope) and not relying on non-standard server behaviour (hence the device ID being generated on the client).
107+
108+
In retrospect, because the whole proposal requires a Matrix-specific implementation anyway, compatibility with existing off-the-shelf OAuth 2.0 server implementations isn't a goal anymore:
109+
we could adopt a Matrix-specific parameter to specify the device ID, and let the server generate it if it's not provided.
110+
111+
As generating the device ID on the client hasn't been a problem in practice, this proposal kept it like that to avoid the cost of aligning the implementations.
112+
113+
## Alternatives
114+
115+
### Scopes
116+
117+
Scope could also have an URL format, e.g. `https://matrix.org/api/*/read`.
118+
119+
The URL prefix could either be static (`https://matrix.org`) or dependant on the homeserver (`https://matrix.example.com`).
120+
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.
121+
122+
The actual namespace prefix and subdivisions are open to debate.
123+
124+
## Security considerations
125+
126+
As we are just representing existing access models there shouldn't be anything special.
127+
128+
## Unstable prefix
129+
130+
While this feature is in development the following unstable scope prefixes should be used:
131+
132+
- `urn:matrix:client` --> `urn:matrix:org.matrix.msc2967.client`
133+
134+
[MSC1597]: https://github.com/matrix-org/matrix-spec-proposals/pull/1597
135+
[MSC2964]: https://github.com/matrix-org/matrix-spec-proposals/pull/2964
136+
[MSC3861]: https://github.com/matrix-org/matrix-spec-proposals/pull/3861
137+
[RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986
138+
[RFC6749]: https://datatracker.ietf.org/doc/html/rfc6749

0 commit comments

Comments
 (0)