diff --git a/proposals/3882-login-token-request.md b/proposals/3882-login-token-request.md new file mode 100644 index 00000000..7372ad97 --- /dev/null +++ b/proposals/3882-login-token-request.md @@ -0,0 +1,177 @@ +# MSC3882: Allow an existing session to sign in a new session + +In [MSC3906](https://github.com/matrix-org/matrix-spec-proposals/pull/3906) a proposal is made to allow a user to login +on a new device using an existing device by means of scanning a QR code. + +In order to support the above proposal a mechanism is needed where by the new device can obtain a new access token that +it can use with the Client-Server API. + +It is proposed that the current `m.login.token` mechanism is extended to allow the issuance of a login token by an +existing client session. + +## Proposal + +### New API endpoint POST /login/get_token + +Add a new optional POST endpoint to the Client-Server API that issues a single-use, time-limited `m.login.token` token: + +`POST /_matrix/client/v1/login/get_token` + +The client should send an empty JSON object for the body of the `POST` request (apart from +the `auth` property used in user-interactive authentication). + +As detailed in the security selection below, this new endpoint should be protected by user interactive authentication +(UIA) as detailed in the existing +["User-interactive API in the REST API"](https://spec.matrix.org/v1.5/client-server-api/#user-interactive-api-in-the-rest-api) +section of the spec. + +Once UIA has been completed a `200` response with JSON body is returned. The body contains the following fields: + +- `login_token` - required, the token to use with `m.login.token` +- `expires_in_ms` - required, how long until the token expires in milliseconds + +An example response is as follows: + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "login_token": "", + "expires_in_ms": 120000 +} +``` + +This token can then be used as per the existing [Login spec](https://spec.matrix.org/v1.6/client-server-api/#login) as follows: + +```http +POST /_matrix/client/v3/login HTTP/1.1 +Content-Type: application/json +``` + +```json +{ + "type": "m.login.token", + "token": "" +} +``` + +### Determining the availability of the new API endpoint + +As this new API endpoint is optional, clients should determine whether the endpoint is available +before prompting the user to try using it. + +There are two usage scenarios to consider: + +1. The user wishes to sign in on a Matrix client. +2. The user wishes to use an already signed in Matrix client to sign in another client. + +In scenario 2 the client is already authenticated. For scenario 1 the client is not yet authenticated. + +#### Scenario 1: The user wishes to sign in on a Matrix client + +The client wants to determine if it *may* be possible to sign in by getting a login token from an +existing session. + +It is proposed that the unauthenticated client can determine if the new API endpoint *may* be available +as part of the existing +[`GET /_matrix/client/v3/login`](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3login) +API endpoint. + +As the `m.login.token` mechanism is used to redeem the login token, the client can first determine if the +`m.login.token` is advertised as a flow in the `GET /_matrix/client/v3/login` response. Then it can check a +new boolean field `get_login_token` to determine if the capability *may* be available. + +An example of the proposed `GET /_matrix/client/v3/login` response is: + +```json +{ + "flow": [ + { + "type": "m.login.token", + "get_login_token": true + } + ] +} +``` + +In this case the mechanism could be available and so the client could prompt the user to try using it. + +#### Scenario 2: The user wishes to use an already signed in Matrix client to sign in another client + +The client is already authenticated. The client can determine whether it is able and allowed to sign in +another client by checking the +[capabilities](https://spec.matrix.org/v1.6/client-server-api/#capabilities-negotiation) +advertised by the homeserver. + +The unauthenticated client can also determine whether the new API endpoint is available +via the [capability negotiation](https://spec.matrix.org/v1.6/client-server-api/#capabilities-negotiation) +mechanism. + +The homeserver can then decide on a per user basis if the capability is available or not. For example, +it could implement a policy based on some risk criteria around the user’s account, session, or device. + +A new capability `m.get_login_token` is proposed. This capability has a single boolean flag, `enabled`, to +denote whether the `/login/get_token` API is available or not. + +An example of the capability API’s response for this capability is: + +```json +{ + "capabilities": { + "m.get_login_token": { + "enabled": true + } + } +} +``` + +## Potential issues + +None identified. + +## Alternatives + +If Matrix was already using OIDC as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) then we +could use the device authorization grant flow which allows for a new device to be signed in using an existing device. + +## Security considerations + +A malicious client could use the mechanism to spawn more than one session. The following mitigations should be applied: + +1. The homeserver must only allow the token to be used for a single login. If the user wishes to sign in multiple + additional clients a token must be issued for each client. + +2. The homeserver should enforce +[user interactive authentication](https://spec.matrix.org/v1.6/client-server-api/#user-interactive-authentication-api) +by default for the new endpoint. The purpose being that consent is obtained from the user for each additional client. + +3. The homeserver should enforce rate-limiting in accordance with the existing +[spec](https://spec.matrix.org/v1.6/client-server-api/#rate-limiting). It may be appropriate for the homeserver admin to +to configure a low limit ("low" relative to other enforced limits). For example, a rate of once per minute could be appropriate. + +n.b. A homeserver admin may deem that they have suitable protections in place and offer the endpoint without UIA auth as described +in the existing spec: + +> A request to an endpoint that uses User-Interactive Authentication never succeeds without auth. Homeservers may allow requests +> that don’t require auth by offering a stage with only the m.login.dummy auth type, but they must still give a 401 response to +> requests with no auth data. + +## Unstable prefix + +While this feature is in development the following unstable prefixes should be used: + +- API endpoint `/_matrix/client/v1/login/get_token` => `/_matrix/client/unstable/org.matrix.msc3882/login/get_token` +- capability `m.get_login_token` => `org.matrix.msc3882.get_login_token` +- login flow field `get_login_token` => `org.matrix.msc3882.get_login_token` + +For reference - an earlier revision of this proposal used an unstable endpoint of +`/_matrix/client/unstable/org.matrix.msc3882/login/token` with an unstable feature advertised +in the response to `GET /_matrix/client/versions` as `org.matrix.msc3882` +set to `true`. This may be referred to as "revision zero" in existing implementations. + +## Dependencies + +None.