Skip to content
This repository was archived by the owner on Sep 10, 2024. It is now read-only.

Commit eb4072f

Browse files
sandhosehughns
andauthored
Document the admin API (#3038)
Co-authored-by: Hugh Nimmo-Smith <[email protected]>
1 parent b4eb935 commit eb4072f

File tree

7 files changed

+302
-28
lines changed

7 files changed

+302
-28
lines changed

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ This documentation has four main sections:
1414

1515
- The [installation guide](./setup/README.md) will guide you through the process of setting up the `matrix-authentication-service` on your own infrastructure.
1616
- The topics sections goes into more details about how the service works, like the [policy engine](./topics/policy.md) and how [authorization sessions](./topics/authorization.md) are managed.
17-
- The reference documentation covers [configuration options](./reference/configuration.md), the [GraphQL API](./reference/graphql.md), the [scopes](./reference/scopes.md) supported by the service, and the [command line interface](./reference/cli/).
17+
- The reference documentation covers [configuration options](./reference/configuration.md), the [Admin API](./api/index.html), the [scopes](./reference/scopes.md) supported by the service, and the [command line interface](./reference/cli/).
1818
- The developer documentation is intended for people who want to [contribute to the project](./development/contributing.md). Developers may also be interested in:
1919
- Technical documentation for individual crates: [`rustdoc`](./rustdoc/mas_handlers/)
2020
- UI components: [`storybook`](./storybook/)

docs/SUMMARY.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Summary
1+
# Summary
22

33
# Introduction
44

@@ -21,11 +21,12 @@
2121

2222
- [Policy engine](./topics/policy.md)
2323
- [Authorization and sessions](./topics/authorization.md)
24+
- [Use the Admin API](./topics/admin-api.md)
2425

2526
# Reference
2627

2728
- [Configuration file reference](./reference/configuration.md)
28-
- [GraphQL API](./reference/graphql.md)
29+
- [Admin API](./api/index.html)
2930
- [OAuth 2.0 scopes](./reference/scopes.md)
3031
- [Command line tool](./reference/cli/README.md)
3132
- [`config`](./reference/cli/config.md)
@@ -40,6 +41,7 @@
4041
- [Contributing](./development/contributing.md)
4142
- [Architecture](./development/architecture.md)
4243
- [Database](./development/database.md)
44+
- [Internal GraphQL API](./development/graphql.md)
4345

4446
---
4547

docs/reference/graphql.md renamed to docs/development/graphql.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
# GraphQL API
1+
# Internal GraphQL API
22

3-
MAS provides a GraphQL API which serves two purposes:
3+
> **Note:** This API used to be the way for external tools to interact with MAS. However, **external usage is now deprecated** in favour of the REST based [Admin API](../topics/admin-api.md). External access to this API will be removed in a future release.
44
5-
- it is used by the self-service user interface (usually accessible on `/account/`), for users to manage their own account.
6-
- it can be used with external tools to manage the service.
5+
MAS uses an internal GraphQL API which is used by the self-service user interface (usually accessible on `/account/`), for users to manage their own account.
76

8-
The endpoint for this API can be discovered through the OpenID Connect discovery document, under the `"org.matrix.matrix-authentication-service.graphql_endpoint` key.
7+
The endpoint for this API can be discovered through the OpenID Connect discovery document, under the `org.matrix.matrix-authentication-service.graphql_endpoint` key.
98
Though it is usually hosted at `https://<mas-host>/graphql`.
109

1110
GraphQL uses [a self-describing schema](https://github.com/matrix-org/matrix-authentication-service/blob/main/frontend/schema.graphql), which means that the API can be explored in tools like the GraphQL Playground.
@@ -23,5 +22,5 @@ With only this scope, the session will be authorized as the user who owns the ac
2322

2423
To get full access to the GraphQL API, the access token must have the [`urn:mas:admin`] scope in addition to the [`urn:mas:graphql:*`] scope.
2524

26-
[`urn:mas:graphql:*`]: ./scopes.md#urnmasgraphql
27-
[`urn:mas:admin`]: ./scopes.md#urnmasadmin
25+
[`urn:mas:graphql:*`]: ../reference/scopes.md#urnmasgraphql
26+
[`urn:mas:admin`]: ../reference/scopes.md#urnmasadmin

docs/reference/configuration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ http:
4444
# Serve the given folder on the /assets/ path
4545
- name: assets
4646
path: ./share/assets/
47+
# Serve the admin API on the /api/admin/v1/ path. Disabled by default
48+
#- name: adminapi
4749

4850
# List of addresses and ports to listen to
4951
binds:

docs/reference/scopes.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ The [default policy](../topics/policy.md#authorization-requests) shipped with MA
88
- [`urn:matrix:org.matrix.msc2967.client:device:[device id]`](#urnmatrixorgmatrixmsc2967clientdevicedevice-id)
99
- [`urn:matrix:org.matrix.msc2967.client:guest`](#urnmatrixorgmatrixmsc2967clientguest)
1010
- [`urn:synapse:admin:*`](#urnsynapseadmin)
11-
- [`urn:mas:graphql:*`](#urnmasgraphql)
1211
- [`urn:mas:admin`](#urnmasadmin)
12+
- [`urn:mas:graphql:*`](#urnmasgraphql)
1313

1414
## OpenID Connect scopes
1515

@@ -79,19 +79,9 @@ It allows:
7979

8080
MAS also has a few scopes that are specific to the MAS implementation.
8181

82-
### `urn:mas:graphql:*`
83-
84-
This scope grants access to the whole MAS [GraphQL API].
85-
What permission the session has on the API is determined by the entity that the session is authorized as.
86-
When [authorized as a user](../topics/authorization.md#authorized-as-a-user-or-authorized-as-a-client) (and without the `mas:urn:admin` scope), this will usually allow querying and mutating the user's own data.
87-
88-
The default policy allows any client and any user to request this scope.
89-
9082
### `urn:mas:admin`
9183

92-
This scope allows full access to the MAS [GraphQL API].
93-
It requires the `urn:mas:graphql:*` scope to be present in the request.
94-
This allows the authenticated entity to perform any operation on the API, regardless of whether the entity owns the data or not.
84+
This scope grants full access to the MAS [Admin API].
9585

9686
The default policy doesn't allow everyone to request this scope.
9787
It allows:
@@ -102,9 +92,20 @@ It allows:
10292
- for the "client credentials" grant:
10393
- clients that are listed in the [`policy.data.admin_clients`](../reference/configuration.md#policy) configuration option
10494

95+
### `urn:mas:graphql:*`
96+
97+
This scope grants access to the whole MAS [Internal GraphQL API].
98+
What permission the session has on the API is determined by the entity that the session is authorized as.
99+
When [authorized as a user](../topics/authorization.md#authorized-as-a-user-or-authorized-as-a-client) (and without the `mas:urn:admin` scope), this will usually allow querying and mutating the user's own data.
100+
101+
The default policy allows any client and any user to request this scope.
102+
103+
However, as noted in the [Internal GraphQL API] documentation, access to the Internal GraphQL API from outside of MAS itself is deprecated in favour of the [Admin API].
104+
105105
[authorization code]: ../topics/authorization.md#authorization-code-grant
106106
[device authorization]: ../topics/authorization.md#device-authorization-grant
107-
[GraphQL API]: ./graphql.md
107+
[Internal GraphQL API]: ../development/graphql.md
108+
[Admin API]: ../topics/admin-api.md
108109
[Synapse admin API]: https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html
109110
[OpenID Connect Core 1.0]: https://openid.net/specs/openid-connect-core-1_0.html
110111
[MSC2967]: https://github.com/matrix-org/matrix-spec-proposals/pull/2967

docs/topics/admin-api.md

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# Admin API
2+
3+
MAS provides a REST-like API for administrators to manage the service.
4+
This API is intended to build tools on top of MAS, and is only available to administrators.
5+
6+
> **Note:** This Admin API is now the correct way for external tools to interact with MAS. External access to the [Internal GraphQL API](../development/graphql.md) is deprecated and will be removed in a future release.
7+
8+
## Enabling the API
9+
10+
The API isn't exposed by default, and must be added to either a public or a private HTTP listener.
11+
It is considered safe to expose the API to the public, as access to it is gated by the `urn:mas:admin` scope.
12+
13+
To enable the API, tweak the [`http.listeners`](../reference/configuration.md#httplisteners) configuration section to add the `adminapi` resource:
14+
15+
```yaml
16+
http:
17+
listeners:
18+
- name: web
19+
resources:
20+
# Other public resources
21+
- name: discovery
22+
#
23+
- name: adminapi
24+
binds:
25+
- address: "[::]:8080"
26+
# or to a separate, internal listener:
27+
- name: internal
28+
resources:
29+
# Other internal resources
30+
- name: health
31+
- name: prometheus
32+
#
33+
- name: adminapi
34+
binds:
35+
- host: localhost
36+
port: 8081
37+
```
38+
39+
## Reference documentation
40+
41+
The API is documented using the [OpenAPI specification](https://spec.openapis.org/oas/v3.1.0).
42+
The API schema is available [here](../api/spec.json).
43+
This schema can be viewed in tools like Swagger UI, available [here](../api/).
44+
45+
If admin API is enabled, MAS will also serve the specification at `/api/spec.json`, with a Swagger UI available at `/api/doc/`.
46+
47+
## Authentication
48+
49+
All requests to the admin API are gated using access tokens obtained using OAuth 2.0 grants.
50+
They must have the [`urn:mas:admin`](../reference/scopes.md#urnmasadmin) scope.
51+
52+
### User-interactive tools
53+
54+
If the intent is to build admin tools where the administrator logs in themselves, interactive grants like the [authorization code] grant or the [device authorization] grant should be used.
55+
56+
In this case, whether the user can request admin access or not is defined by the `can_request_admin` attribute of the user.
57+
58+
To try it out in Swagger UI, a client can be defined statically in the configuration file like this:
59+
60+
```yaml
61+
clients:
62+
- client_id: 01J44Q10GR4AMTFZEEF936DTCM
63+
# For the authorization_code grant, Swagger UI uses the client_secret_post authentication method
64+
client_auth_method: client_secret_post
65+
client_secret: wie9oh2EekeeDeithei9Eipaeh2sohte
66+
redirect_uris:
67+
# The Swagger UI callback in the hosted documentation
68+
- https://matrix-org.github.io/matrix-authentication-service/api/oauth2-redirect.html
69+
# The Swagger UI callback hosted by the service
70+
- https://mas.example.com/api/doc/oauth2-redirect
71+
```
72+
73+
Then, in Swagger UI, click on the "Authorize" button.
74+
In the modal, enter the client ID and client secret **in the `authorizationCode` section**, select the `urn:mas:admin` scope and click on the "Authorize" button.
75+
76+
### Automated tools
77+
78+
If the intent is to build tools that are not meant to be used by humans, the client credentials grant should be used.
79+
80+
In this case, the client must be listed in the [`policy.data.admin_clients`](../reference/configuration.md#policy) configuration option.
81+
82+
```yaml
83+
policy:
84+
data:
85+
admin_clients:
86+
- 01J44QC8BCY7FCFM7WGHQGKMTJ
87+
```
88+
89+
To try it out in Swagger UI, a client can be defined statically in the configuration file like this:
90+
91+
```yaml
92+
clients:
93+
- client_id: 01J44QC8BCY7FCFM7WGHQGKMTJ
94+
# For the client_credentials grant, Swagger UI uses the client_secret_basic authentication method
95+
client_auth_method: client_secret_basic
96+
client_secret: eequie6Oth4Ip2InahT5zuQu8OuPohLi
97+
```
98+
99+
Then, in Swagger UI, click on the "Authorize" button.
100+
In the modal, enter the client ID and client secret **in the `clientCredentials` section**, select the `urn:mas:admin` scope and click on the "Authorize" button.
101+
102+
103+
## General API shape
104+
105+
The API takes inspiration from the [JSON API](https://jsonapi.org/) specification for its request and response shapes.
106+
107+
### Single resource
108+
109+
When querying a single resource, the response is generally shaped like this:
110+
111+
```json
112+
{
113+
"data": {
114+
"type": "type-of-the-resource",
115+
"id": "unique-id-for-the-resource",
116+
"attributes": {
117+
"some-attribute": "some-value"
118+
},
119+
"links": {
120+
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
121+
}
122+
},
123+
"links": {
124+
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
125+
}
126+
}
127+
```
128+
129+
### List of resources
130+
131+
When querying a list of resources, the response is generally shaped like this:
132+
133+
```json
134+
{
135+
"meta": {
136+
"count": 42
137+
},
138+
"data": [
139+
{
140+
"type": "type-of-the-resource",
141+
"id": "unique-id-for-the-resource",
142+
"attributes": {
143+
"some-attribute": "some-value"
144+
},
145+
"links": {
146+
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
147+
}
148+
},
149+
{ "...": "..." },
150+
{ "...": "..." }
151+
],
152+
"links": {
153+
"self": "/api/admin/v1/type-of-the-resource?page[first]=10&page[after]=some-id",
154+
"first": "/api/admin/v1/type-of-the-resource?page[first]=10",
155+
"last": "/api/admin/v1/type-of-the-resource?page[last]=10",
156+
"next": "/api/admin/v1/type-of-the-resource?page[first]=10&page[after]=some-id",
157+
"prev": "/api/admin/v1/type-of-the-resource?page[last]=10&page[before]=some-id"
158+
}
159+
}
160+
```
161+
162+
The `meta` will have the total number of items in it, and the `links` object contains the links to the next and previous pages, if any.
163+
164+
Pagination is cursor-based, where the ID of items is used as the cursor.
165+
Resources can be paginated forwards using the `page[after]` and `page[first]` parameters, and backwards using the `page[before]` and `page[last]` parameters.
166+
167+
### Error responses
168+
169+
Error responses will use a 4xx or 5xx status code, with the following shape:
170+
171+
```json
172+
{
173+
"errors": [
174+
{
175+
"title": "Error title"
176+
}
177+
]
178+
}
179+
```
180+
181+
Well-known error codes are not yet specified.
182+
183+
## Example
184+
185+
With the following configuration:
186+
187+
```yaml
188+
clients:
189+
- client_id: 01J44RKQYM4G3TNVANTMTDYTX6
190+
client_auth_method: client_secret_basic
191+
client_secret: phoo8ahneir3ohY2eigh4xuu6Oodaewi
192+
193+
policy:
194+
data:
195+
admin_clients:
196+
- 01J44RKQYM4G3TNVANTMTDYTX6
197+
```
198+
199+
`curl` example to list the users that are not locked and have the `can_request_admin` flag set to `true`:
200+
201+
```bash
202+
CLIENT_ID=01J44RKQYM4G3TNVANTMTDYTX6
203+
CLIENT_SECRET=phoo8ahneir3ohY2eigh4xuu6Oodaewi
204+
205+
# Get an access token
206+
curl \
207+
-u "$CLIENT_ID:$CLIENT_SECRET" \
208+
-d "grant_type=client_credentials&scope=urn:mas:admin" \
209+
https://mas.example.com/oauth2/token \
210+
| jq -r '.access_token' \
211+
| read -r ACCESS_TOKEN
212+
213+
# List users (The -g flag prevents curl from interpreting the brackets in the URL)
214+
curl \
215+
-g \
216+
-H "Authorization: Bearer $ACCESS_TOKEN" \
217+
'https://mas.example.com/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100' \
218+
| jq
219+
```
220+
221+
<details>
222+
<summary>
223+
Sample output
224+
</summary>
225+
226+
```json
227+
{
228+
"meta": {
229+
"count": 2
230+
},
231+
"data": [
232+
{
233+
"type": "user",
234+
"id": "01J2KDPHTZYW3TAT1SKVAD63SQ",
235+
"attributes": {
236+
"username": "kilgore-trout",
237+
"created_at": "2024-07-12T12:11:46.911578Z",
238+
"locked_at": null,
239+
"can_request_admin": true
240+
},
241+
"links": {
242+
"self": "/api/admin/v1/users/01J2KDPHTZYW3TAT1SKVAD63SQ"
243+
}
244+
},
245+
{
246+
"type": "user",
247+
"id": "01J3G5W8MRMBJ93ZYEGX2BN6NK",
248+
"attributes": {
249+
"username": "quentin",
250+
"created_at": "2024-07-23T16:13:04.024378Z",
251+
"locked_at": null,
252+
"can_request_admin": true
253+
},
254+
"links": {
255+
"self": "/api/admin/v1/users/01J3G5W8MRMBJ93ZYEGX2BN6NK"
256+
}
257+
}
258+
],
259+
"links": {
260+
"self": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100",
261+
"first": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100",
262+
"last": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[last]=100"
263+
}
264+
}
265+
```
266+
267+
</details>
268+
269+
[authorization code]: ../topics/authorization.md#authorization-code-grant
270+
[device authorization]: ../topics/authorization.md#device-authorization-grant

0 commit comments

Comments
 (0)