diff --git a/changelogs/application_service/newsfragments/2267.feature b/changelogs/application_service/newsfragments/2267.feature new file mode 100644 index 00000000..92a03203 --- /dev/null +++ b/changelogs/application_service/newsfragments/2267.feature @@ -0,0 +1 @@ +Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). diff --git a/changelogs/client_server/newsfragments/2267.feature b/changelogs/client_server/newsfragments/2267.feature new file mode 100644 index 00000000..92a03203 --- /dev/null +++ b/changelogs/client_server/newsfragments/2267.feature @@ -0,0 +1 @@ +Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). diff --git a/content/application-service-api.md b/content/application-service-api.md index cc2c25ca..5f6b17ab 100644 --- a/content/application-service-api.md +++ b/content/application-service-api.md @@ -428,6 +428,8 @@ imports and similar behaviour). #### Server admin style permissions +{{% changed-in v="1.17" %}} + The homeserver needs to give the application service *full control* over its namespace, both for users and for room aliases. This means that the AS should be able to manage any users and room alias in its namespace. No additional API @@ -444,33 +446,59 @@ achieved by including the `as_token` on a `/register` request, along with a login type of `m.login.application_service` to set the desired user ID without a password. - POST /_matrix/client/v3/register - Authorization: Bearer YourApplicationServiceTokenHere +```http +POST /_matrix/client/v3/register +Authorization: Bearer YourApplicationServiceTokenHere +``` - Content: - { - "type": "m.login.application_service", - "username": "_irc_example" - } +```json +{ + "type": "m.login.application_service", + "username": "_irc_example" +} +``` -Similarly, logging in as users needs API changes in order to allow the AS to -log in without needing the user's password. This is achieved by including the -`as_token` on a `/login` request, along with a login type of -`m.login.application_service`: +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Servers MUST still allow application services to use the `/register` endpoint +with a login type of `m.login.application_service` even if they don't support +the [Legacy Authentication API](/client-server-api/#legacy-api). + +In that case application services MUST set the `"inhibit_login": true` parameter +as they cannot use it to log in as users. If the `inhibit_login` parameter is +not set to `true`, the server MUST return a 400 HTTP status code with an +`M_APPSERVICE_LOGIN_UNSUPPORTED` error code. +{{% /boxes/note %}} + +Similarly, logging in as users using the [Legacy authentication API](/client-server-api/#legacy-api) +needs API changes in order to allow the AS to log in without needing the user's +password. This is achieved by including the `as_token` on a `/login` request, +along with a login type of `m.login.application_service`: {{% added-in v="1.2" %}} - POST /_matrix/client/v3/login - Authorization: Bearer YourApplicationServiceTokenHere +```http +POST /_matrix/client/v3/login +Authorization: Bearer YourApplicationServiceTokenHere +``` - Content: - { - "type": "m.login.application_service", - "identifier": { - "type": "m.id.user", - "user": "_irc_example" - } - } +```json +{ + "type": "m.login.application_service", + "identifier": { + "type": "m.id.user", + "user": "_irc_example" + } +} +``` + +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Application services MUST NOT use the `/login` endpoint if the server doesn't +support the Legacy authentication API. If `/login` is called with the +`m.login.application_service` login type the server MUST return a 400 HTTP +status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. +{{% /boxes/note %}} Application services which attempt to create users or aliases *outside* of their defined namespaces, or log in as users outside of their defined @@ -512,6 +540,38 @@ client-server endpoint. {{% http-api spec="client-server" api="appservice_room_directory" %}} +#### Device management + +{{% added-in v="1.17" %}} + +Application services need to be able to create and delete devices to manage the +encryption for their users without having to rely on `/login`, which also +generates an access token for the user, and which might not be available for +homeservers that only support the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + +##### Creating devices + +Application services can use the [`PUT /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#put_matrixclientv3devicesdeviceid) +endpoint to create new devices. + +##### Deleting devices + +The following endpoints used to delete devices MUST NOT require [User-Interactive +Authentication](/client-server-api/#user-interactive-authentication-api) when +used by an application service: + +* [`DELETE /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#delete_matrixclientv3devicesdeviceid) +* [`POST /_matrix/client/v3/delete_devices`](/client-server-api/#post_matrixclientv3delete_devices) + +#### Cross-signing + +{{% added-in v="1.17" %}} + +Appservices need to be able to verify themselves and replace their cross-signing +keys, so the [`POST /_matrix/client/v3/keys/device_signing/upload`](/client-server-api/#post_matrixclientv3keysdevice_signingupload) +endpoint MUST NOT require [User-Interactive Authentication](/client-server-api/#user-interactive-authentication-api) +when used by an application service, even if cross-signing keys already exist. + ### Referencing messages from a third-party network Application services should include an `external_url` in the `content` diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 2460776f..4c76d6a5 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -477,8 +477,7 @@ the API that was used to obtain their current access token. {{% boxes/note %}} Currently the OAuth 2.0 API doesn't cover all the use cases of the legacy API, -such as automated applications that cannot use a web browser, or -user management by [application services](application-service-api/#server-admin-style-permissions). +such as automated applications that cannot use a web browser. {{% /boxes/note %}} ### Authentication API discovery @@ -502,6 +501,12 @@ user must do that directly in the homeserver's web UI. However, the client can signal to the homeserver that the user wishes to create a new account with the [`prompt=create`](#user-registration) parameter during authorization. +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Application services can use the `/register` endpoint to create users regardless +of the authentication API supported by the homeserver. +{{% /boxes/note %}} + ### Login With the legacy API, a client can obtain an access token by using one of the @@ -1562,6 +1567,10 @@ If the access token does correspond to an appservice, but the user id does not lie within its namespace then the homeserver will respond with an errcode of `M_EXCLUSIVE`. +{{% added-in v="1.17" %}} If this login type is used and the server doesn't +support logging in via the Legacy authentication API, it MUST return a 400 HTTP +status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. + ##### Login Fallback If a client does not recognize any or all login flows it can use the diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml index ec490b2a..f340bd59 100644 --- a/data/api/client-server/cross_signing.yaml +++ b/data/api/client-server/cross_signing.yaml @@ -21,13 +21,17 @@ paths: x-addedInMatrixVersion: "1.1" x-changedInMatrixVersion: "1.11": UIA is not always required for this endpoint. + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. summary: Upload cross-signing keys. description: |- Publishes cross-signing keys for the user. - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. - User-Interactive Authentication MUST be performed, except in these cases: + User-Interactive Authentication MUST be performed for regular clients, except in these cases: - there is no existing cross-signing master key uploaded to the homeserver, OR - there is an existing cross-signing master key and it exactly matches the cross-signing master key provided in the request body. If there are any additional diff --git a/data/api/client-server/device_management.yaml b/data/api/client-server/device_management.yaml index 1b245e78..94dde899 100644 --- a/data/api/client-server/device_management.yaml +++ b/data/api/client-server/device_management.yaml @@ -87,8 +87,21 @@ paths: tags: - Device management put: - summary: Update a device - description: Updates the metadata on the given device. + summary: Create or update a device + x-changedInMatrixVersion: + "1.17": The ability to create new devices was added. + description: |- + Updates the metadata on the given device, or creates a new device. + + The ability to create new devices is only available to application + services: regular clients may only update existing devices. + + When a new device was created, the homeserver MUST return a 201 HTTP + status code. It MUST return a 200 HTTP status code if a device was + updated. + + This endpoint is rate-limited for device creation. Servers MAY use login + rate limits. operationId: updateDevice security: - accessTokenQuery: [] @@ -127,19 +140,34 @@ paths: examples: response: value: {} + "201": + description: |- + The device was successfully created by the application service. + content: + application/json: + schema: + type: object + examples: + response: + value: {} "404": description: The current user has no device with the given ID. tags: - Device management delete: summary: Delete a device + x-changedInMatrixVersion: + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. description: |- - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. Deletes the given device, and invalidates any access token associated with it. {{% boxes/warning %}} - Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). {{% /boxes/warning %}} operationId: deleteDevice @@ -190,13 +218,18 @@ paths: /delete_devices: post: summary: Bulk deletion of devices + x-changedInMatrixVersion: + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. description: |- - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. Deletes the given devices, and invalidates any access token associated with them. {{% boxes/warning %}} - Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). {{% /boxes/warning %}} operationId: deleteDevices diff --git a/data/api/client-server/login.yaml b/data/api/client-server/login.yaml index 4eba954e..7251d4ff 100644 --- a/data/api/client-server/login.yaml +++ b/data/api/client-server/login.yaml @@ -243,8 +243,13 @@ paths: } } "400": - description: Part of the request was invalid. For example, the login type may - not be recognised. + description: |- + Part of the request was invalid. For example, the login type may not be recognised. + + Specific error codes used with this status code include: + * {{% added-in v="1.17" %}} `M_APPSERVICE_LOGIN_UNSUPPORTED`: an application service + used the `m.login.application_service` type, but the server doesn't support logging + in via the Legacy authentication API. content: application/json: schema: diff --git a/data/api/client-server/registration.yaml b/data/api/client-server/registration.yaml index e7ede561..7a923f9e 100644 --- a/data/api/client-server/registration.yaml +++ b/data/api/client-server/registration.yaml @@ -60,6 +60,18 @@ paths: Any user ID returned by this API must conform to the grammar given in the [Matrix specification](/appendices/#user-identifiers). + + {{% boxes/note %}} + {{% added-in v="1.17" %}} + Even if the server doesn't support the Legacy authentication API, it + MUST support this endpoint for application services to be able to + [create users](/application-service-api/#server-admin-style-permissions). + + In that case application services MUST set the `"inhibit_login": true` + parameter as they cannot use it to log in as users. If the + `inhibit_login` parameter is not set to `true`, the server MUST return a + 400 HTTP status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. + {{% /boxes/note %}} operationId: register parameters: - in: query @@ -203,6 +215,9 @@ paths: * `M_INVALID_USERNAME` : The desired user ID is not a valid user name. * `M_EXCLUSIVE` : The desired user ID is in the exclusive namespace claimed by an application service. + * {{% added-in v="1.17" %}} `M_APPSERVICE_LOGIN_UNSUPPORTED`: an application service + used the `m.login.application_service` type without setting `inhibit_login` to `true`, + but the server doesn't support logging in via the Legacy authentication API. These errors may be returned at any stage of the registration process, including after authentication if the requested user ID was registered