1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Document the admin API (#3038)

Co-authored-by: Hugh Nimmo-Smith <hughns@matrix.org>
This commit is contained in:
Quentin Gliech
2024-08-07 17:41:46 +02:00
committed by GitHub
parent b4eb93558d
commit eb4072f3c3
7 changed files with 302 additions and 28 deletions

View File

@ -14,7 +14,7 @@ This documentation has four main sections:
- The [installation guide](./setup/README.md) will guide you through the process of setting up the `matrix-authentication-service` on your own infrastructure. - The [installation guide](./setup/README.md) will guide you through the process of setting up the `matrix-authentication-service` on your own infrastructure.
- 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. - 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.
- 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/). - 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/).
- The developer documentation is intended for people who want to [contribute to the project](./development/contributing.md). Developers may also be interested in: - The developer documentation is intended for people who want to [contribute to the project](./development/contributing.md). Developers may also be interested in:
- Technical documentation for individual crates: [`rustdoc`](./rustdoc/mas_handlers/) - Technical documentation for individual crates: [`rustdoc`](./rustdoc/mas_handlers/)
- UI components: [`storybook`](./storybook/) - UI components: [`storybook`](./storybook/)

View File

@ -1,4 +1,4 @@
# Summary # Summary
# Introduction # Introduction
@ -21,11 +21,12 @@
- [Policy engine](./topics/policy.md) - [Policy engine](./topics/policy.md)
- [Authorization and sessions](./topics/authorization.md) - [Authorization and sessions](./topics/authorization.md)
- [Use the Admin API](./topics/admin-api.md)
# Reference # Reference
- [Configuration file reference](./reference/configuration.md) - [Configuration file reference](./reference/configuration.md)
- [GraphQL API](./reference/graphql.md) - [Admin API](./api/index.html)
- [OAuth 2.0 scopes](./reference/scopes.md) - [OAuth 2.0 scopes](./reference/scopes.md)
- [Command line tool](./reference/cli/README.md) - [Command line tool](./reference/cli/README.md)
- [`config`](./reference/cli/config.md) - [`config`](./reference/cli/config.md)
@ -40,6 +41,7 @@
- [Contributing](./development/contributing.md) - [Contributing](./development/contributing.md)
- [Architecture](./development/architecture.md) - [Architecture](./development/architecture.md)
- [Database](./development/database.md) - [Database](./development/database.md)
- [Internal GraphQL API](./development/graphql.md)
--- ---

View File

@ -1,11 +1,10 @@
# GraphQL API # Internal GraphQL API
MAS provides a GraphQL API which serves two purposes: > **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.
- it is used by the self-service user interface (usually accessible on `/account/`), for users to manage their own account. 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.
- it can be used with external tools to manage the service.
The endpoint for this API can be discovered through the OpenID Connect discovery document, under the `"org.matrix.matrix-authentication-service.graphql_endpoint` key. The endpoint for this API can be discovered through the OpenID Connect discovery document, under the `org.matrix.matrix-authentication-service.graphql_endpoint` key.
Though it is usually hosted at `https://<mas-host>/graphql`. Though it is usually hosted at `https://<mas-host>/graphql`.
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. 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
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. 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.
[`urn:mas:graphql:*`]: ./scopes.md#urnmasgraphql [`urn:mas:graphql:*`]: ../reference/scopes.md#urnmasgraphql
[`urn:mas:admin`]: ./scopes.md#urnmasadmin [`urn:mas:admin`]: ../reference/scopes.md#urnmasadmin

View File

@ -44,6 +44,8 @@ http:
# Serve the given folder on the /assets/ path # Serve the given folder on the /assets/ path
- name: assets - name: assets
path: ./share/assets/ path: ./share/assets/
# Serve the admin API on the /api/admin/v1/ path. Disabled by default
#- name: adminapi
# List of addresses and ports to listen to # List of addresses and ports to listen to
binds: binds:

View File

@ -8,8 +8,8 @@ The [default policy](../topics/policy.md#authorization-requests) shipped with MA
- [`urn:matrix:org.matrix.msc2967.client:device:[device id]`](#urnmatrixorgmatrixmsc2967clientdevicedevice-id) - [`urn:matrix:org.matrix.msc2967.client:device:[device id]`](#urnmatrixorgmatrixmsc2967clientdevicedevice-id)
- [`urn:matrix:org.matrix.msc2967.client:guest`](#urnmatrixorgmatrixmsc2967clientguest) - [`urn:matrix:org.matrix.msc2967.client:guest`](#urnmatrixorgmatrixmsc2967clientguest)
- [`urn:synapse:admin:*`](#urnsynapseadmin) - [`urn:synapse:admin:*`](#urnsynapseadmin)
- [`urn:mas:graphql:*`](#urnmasgraphql)
- [`urn:mas:admin`](#urnmasadmin) - [`urn:mas:admin`](#urnmasadmin)
- [`urn:mas:graphql:*`](#urnmasgraphql)
## OpenID Connect scopes ## OpenID Connect scopes
@ -79,19 +79,9 @@ It allows:
MAS also has a few scopes that are specific to the MAS implementation. MAS also has a few scopes that are specific to the MAS implementation.
### `urn:mas:graphql:*`
This scope grants access to the whole MAS [GraphQL API].
What permission the session has on the API is determined by the entity that the session is authorized as.
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.
The default policy allows any client and any user to request this scope.
### `urn:mas:admin` ### `urn:mas:admin`
This scope allows full access to the MAS [GraphQL API]. This scope grants full access to the MAS [Admin API].
It requires the `urn:mas:graphql:*` scope to be present in the request.
This allows the authenticated entity to perform any operation on the API, regardless of whether the entity owns the data or not.
The default policy doesn't allow everyone to request this scope. The default policy doesn't allow everyone to request this scope.
It allows: It allows:
@ -102,9 +92,20 @@ It allows:
- for the "client credentials" grant: - for the "client credentials" grant:
- clients that are listed in the [`policy.data.admin_clients`](../reference/configuration.md#policy) configuration option - clients that are listed in the [`policy.data.admin_clients`](../reference/configuration.md#policy) configuration option
### `urn:mas:graphql:*`
This scope grants access to the whole MAS [Internal GraphQL API].
What permission the session has on the API is determined by the entity that the session is authorized as.
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.
The default policy allows any client and any user to request this scope.
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].
[authorization code]: ../topics/authorization.md#authorization-code-grant [authorization code]: ../topics/authorization.md#authorization-code-grant
[device authorization]: ../topics/authorization.md#device-authorization-grant [device authorization]: ../topics/authorization.md#device-authorization-grant
[GraphQL API]: ./graphql.md [Internal GraphQL API]: ../development/graphql.md
[Admin API]: ../topics/admin-api.md
[Synapse admin API]: https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html [Synapse admin API]: https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html
[OpenID Connect Core 1.0]: https://openid.net/specs/openid-connect-core-1_0.html [OpenID Connect Core 1.0]: https://openid.net/specs/openid-connect-core-1_0.html
[MSC2967]: https://github.com/matrix-org/matrix-spec-proposals/pull/2967 [MSC2967]: https://github.com/matrix-org/matrix-spec-proposals/pull/2967

270
docs/topics/admin-api.md Normal file
View File

@ -0,0 +1,270 @@
# Admin API
MAS provides a REST-like API for administrators to manage the service.
This API is intended to build tools on top of MAS, and is only available to administrators.
> **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.
## Enabling the API
The API isn't exposed by default, and must be added to either a public or a private HTTP listener.
It is considered safe to expose the API to the public, as access to it is gated by the `urn:mas:admin` scope.
To enable the API, tweak the [`http.listeners`](../reference/configuration.md#httplisteners) configuration section to add the `adminapi` resource:
```yaml
http:
listeners:
- name: web
resources:
# Other public resources
- name: discovery
# …
- name: adminapi
binds:
- address: "[::]:8080"
# or to a separate, internal listener:
- name: internal
resources:
# Other internal resources
- name: health
- name: prometheus
# …
- name: adminapi
binds:
- host: localhost
port: 8081
```
## Reference documentation
The API is documented using the [OpenAPI specification](https://spec.openapis.org/oas/v3.1.0).
The API schema is available [here](../api/spec.json).
This schema can be viewed in tools like Swagger UI, available [here](../api/).
If admin API is enabled, MAS will also serve the specification at `/api/spec.json`, with a Swagger UI available at `/api/doc/`.
## Authentication
All requests to the admin API are gated using access tokens obtained using OAuth 2.0 grants.
They must have the [`urn:mas:admin`](../reference/scopes.md#urnmasadmin) scope.
### User-interactive tools
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.
In this case, whether the user can request admin access or not is defined by the `can_request_admin` attribute of the user.
To try it out in Swagger UI, a client can be defined statically in the configuration file like this:
```yaml
clients:
- client_id: 01J44Q10GR4AMTFZEEF936DTCM
# For the authorization_code grant, Swagger UI uses the client_secret_post authentication method
client_auth_method: client_secret_post
client_secret: wie9oh2EekeeDeithei9Eipaeh2sohte
redirect_uris:
# The Swagger UI callback in the hosted documentation
- https://matrix-org.github.io/matrix-authentication-service/api/oauth2-redirect.html
# The Swagger UI callback hosted by the service
- https://mas.example.com/api/doc/oauth2-redirect
```
Then, in Swagger UI, click on the "Authorize" button.
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.
### Automated tools
If the intent is to build tools that are not meant to be used by humans, the client credentials grant should be used.
In this case, the client must be listed in the [`policy.data.admin_clients`](../reference/configuration.md#policy) configuration option.
```yaml
policy:
data:
admin_clients:
- 01J44QC8BCY7FCFM7WGHQGKMTJ
```
To try it out in Swagger UI, a client can be defined statically in the configuration file like this:
```yaml
clients:
- client_id: 01J44QC8BCY7FCFM7WGHQGKMTJ
# For the client_credentials grant, Swagger UI uses the client_secret_basic authentication method
client_auth_method: client_secret_basic
client_secret: eequie6Oth4Ip2InahT5zuQu8OuPohLi
```
Then, in Swagger UI, click on the "Authorize" button.
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.
## General API shape
The API takes inspiration from the [JSON API](https://jsonapi.org/) specification for its request and response shapes.
### Single resource
When querying a single resource, the response is generally shaped like this:
```json
{
"data": {
"type": "type-of-the-resource",
"id": "unique-id-for-the-resource",
"attributes": {
"some-attribute": "some-value"
},
"links": {
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
}
},
"links": {
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
}
}
```
### List of resources
When querying a list of resources, the response is generally shaped like this:
```json
{
"meta": {
"count": 42
},
"data": [
{
"type": "type-of-the-resource",
"id": "unique-id-for-the-resource",
"attributes": {
"some-attribute": "some-value"
},
"links": {
"self": "/api/admin/v1/type-of-the-resource/unique-id-for-the-resource"
}
},
{ "...": "..." },
{ "...": "..." }
],
"links": {
"self": "/api/admin/v1/type-of-the-resource?page[first]=10&page[after]=some-id",
"first": "/api/admin/v1/type-of-the-resource?page[first]=10",
"last": "/api/admin/v1/type-of-the-resource?page[last]=10",
"next": "/api/admin/v1/type-of-the-resource?page[first]=10&page[after]=some-id",
"prev": "/api/admin/v1/type-of-the-resource?page[last]=10&page[before]=some-id"
}
}
```
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.
Pagination is cursor-based, where the ID of items is used as the cursor.
Resources can be paginated forwards using the `page[after]` and `page[first]` parameters, and backwards using the `page[before]` and `page[last]` parameters.
### Error responses
Error responses will use a 4xx or 5xx status code, with the following shape:
```json
{
"errors": [
{
"title": "Error title"
}
]
}
```
Well-known error codes are not yet specified.
## Example
With the following configuration:
```yaml
clients:
- client_id: 01J44RKQYM4G3TNVANTMTDYTX6
client_auth_method: client_secret_basic
client_secret: phoo8ahneir3ohY2eigh4xuu6Oodaewi
policy:
data:
admin_clients:
- 01J44RKQYM4G3TNVANTMTDYTX6
```
`curl` example to list the users that are not locked and have the `can_request_admin` flag set to `true`:
```bash
CLIENT_ID=01J44RKQYM4G3TNVANTMTDYTX6
CLIENT_SECRET=phoo8ahneir3ohY2eigh4xuu6Oodaewi
# Get an access token
curl \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials&scope=urn:mas:admin" \
https://mas.example.com/oauth2/token \
| jq -r '.access_token' \
| read -r ACCESS_TOKEN
# List users (The -g flag prevents curl from interpreting the brackets in the URL)
curl \
-g \
-H "Authorization: Bearer $ACCESS_TOKEN" \
'https://mas.example.com/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100' \
| jq
```
<details>
<summary>
Sample output
</summary>
```json
{
"meta": {
"count": 2
},
"data": [
{
"type": "user",
"id": "01J2KDPHTZYW3TAT1SKVAD63SQ",
"attributes": {
"username": "kilgore-trout",
"created_at": "2024-07-12T12:11:46.911578Z",
"locked_at": null,
"can_request_admin": true
},
"links": {
"self": "/api/admin/v1/users/01J2KDPHTZYW3TAT1SKVAD63SQ"
}
},
{
"type": "user",
"id": "01J3G5W8MRMBJ93ZYEGX2BN6NK",
"attributes": {
"username": "quentin",
"created_at": "2024-07-23T16:13:04.024378Z",
"locked_at": null,
"can_request_admin": true
},
"links": {
"self": "/api/admin/v1/users/01J3G5W8MRMBJ93ZYEGX2BN6NK"
}
}
],
"links": {
"self": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100",
"first": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[first]=100",
"last": "/api/admin/v1/users?filter[can_request_admin]=true&filter[status]=active&page[last]=100"
}
}
```
</details>
[authorization code]: ../topics/authorization.md#authorization-code-grant
[device authorization]: ../topics/authorization.md#device-authorization-grant

View File

@ -86,11 +86,11 @@ the API can be requested by a session which has the [`urn:mas:graphql:*`] and th
MAS supports a few different authorization grants for OAuth 2.0 sessions. MAS supports a few different authorization grants for OAuth 2.0 sessions.
Whilst this section won't go into the technical details of how those grants work, it's important to understand what they are and what they are used for. Whilst this section won't go into the technical details of how those grants work, it's important to understand what they are and what they are used for.
| Grant type | Entity | User interaction | Matrix C-S API | Synapse admin API |  MAS GraphQL API | | Grant type | Entity | User interaction | Matrix C-S API | Synapse Admin API | MAS Admin API | MAS Internal GraphQL API |
| --------------------------------------------------- | ------ | ---------------- | -------------- | ----------------- | ---------------- | | --------------------------------------------------- | ------ | ---------------- | -------------- | ----------------- | ------------- | ------------------------ |
| [Authorization code](#authorization-code-grant) | User | Same device | Yes | Yes | Yes | | [Authorization code](#authorization-code-grant) | User | Same device | Yes | Yes | Yes | Yes |
| [Device authorization](#device-authorization-grant) | User | Other device | Yes | Yes | Yes | | [Device authorization](#device-authorization-grant) | User | Other device | Yes | Yes | Yes | Yes |
| [Client credentials](#client-credentials-grant) | Client | None | No | No[^admin] | No | | [Client credentials](#client-credentials-grant) | Client | None | No | No[^admin] | Yes | Yes |
[^admin]: The Synapse admin API doesn't strictly require a user, but Synapse doesn't support client-only sessions yet. In the future, it will be possible to leverage the client credentials grant to access the Synapse admin API. [^admin]: The Synapse admin API doesn't strictly require a user, but Synapse doesn't support client-only sessions yet. In the future, it will be possible to leverage the client credentials grant to access the Synapse admin API.