add spec for refresh tokens

pull/1056/head
Hubert Chathi 3 years ago
parent fd2d5b8a49
commit 1f81587154

@ -71,7 +71,7 @@ These error codes can be returned by any API endpoint:
Forbidden access, e.g. joining a room without permission, failed login. Forbidden access, e.g. joining a room without permission, failed login.
`M_UNKNOWN_TOKEN` `M_UNKNOWN_TOKEN`
The access token specified was not recognised. The access or refresh token specified was not recognised.
An additional response parameter, `soft_logout`, might be present on the An additional response parameter, `soft_logout`, might be present on the
response for 401 HTTP status codes. See [the soft logout response for 401 HTTP status codes. See [the soft logout
@ -314,7 +314,8 @@ Most API endpoints require the user to identify themselves by presenting
previously obtained credentials in the form of an `access_token` query previously obtained credentials in the form of an `access_token` query
parameter or through an Authorization Header of `Bearer $access_token`. parameter or through an Authorization Header of `Bearer $access_token`.
An access token is typically obtained via the [Login](#login) or An access token is typically obtained via the [Login](#login) or
[Registration](#account-registration-and-management) processes. [Registration](#account-registration-and-management) processes. Access tokens
can expire; a new access token can be generated by using a refresh token.
{{% boxes/note %}} {{% boxes/note %}}
This specification does not mandate a particular format for the access This specification does not mandate a particular format for the access
@ -336,42 +337,92 @@ to prevent the access token being leaked in access/HTTP logs. The query
string should only be used in cases where the `Authorization` header is string should only be used in cases where the `Authorization` header is
inaccessible for the client. inaccessible for the client.
When credentials are required but missing or invalid, the HTTP call will {{% changed-in v="1.3" %}} When credentials are required but missing or
return with a status of 401 and the error code, `M_MISSING_TOKEN` or invalid, the HTTP call will return with a status of 401 and the error code,
`M_UNKNOWN_TOKEN` respectively. `M_MISSING_TOKEN` or `M_UNKNOWN_TOKEN` respectively. Note that an error code
of `M_UNKNOWN_TOKEN` could mean one of four things:
1. the access token was never valid.
2. the access token has been logged out.
3. the access token has been [soft logged out](#soft-logout).
4. the access token [needs to be refreshed](#refreshing-access-tokens).
When a client receives an error code of `M_UNKNOWN_TOKEN`, it should:
- attempt to [refresh the token](#refreshing-access-tokens), if it has a refresh
token;
- if [`soft_logout`](#soft-logout) is set to `true`, it can offer to
re-log in the user, retaining any of the client's persisted
information;
- otherwise, consider the user as having been logged out.
### Relationship between access tokens and devices ### Relationship between access tokens and devices
Client [devices](../index.html#devices) are closely related to access Client [devices](../index.html#devices) are closely related to access
tokens. Matrix servers should record which device each access token is tokens and refresh tokens. Matrix servers should record which device
assigned to, so that subsequent requests can be handled correctly. each access token and refresh token are assigned to, so that
subsequent requests can be handled correctly. When a refresh token is
used to generate a new access token and refresh token, the new access
and refresh tokens are now bound to the device associated with the
initial refresh token.
By default, the [Login](#login) and [Registration](#account-registration-and-management) By default, the [Login](#login) and [Registration](#account-registration-and-management)
processes auto-generate a new `device_id`. A client is also free to processes auto-generate a new `device_id`. A client is also free to
generate its own `device_id` or, provided the user remains the same, generate its own `device_id` or, provided the user remains the same,
reuse a device: in either case the client should pass the `device_id` in reuse a device: in either case the client should pass the `device_id` in
the request body. If the client sets the `device_id`, the server will the request body. If the client sets the `device_id`, the server will
invalidate any access token previously assigned to that device. There is invalidate any access and refresh tokens previously assigned to that device.
therefore at most one active access token assigned to each device at any
one time. ### Refreshing access tokens
{{% added-in v="1.3" %}}
Access tokens can expire after a certain amount of time. Any HTTP
calls that use an expired access token will return with an error code
`M_UNKNOWN_TOKEN`, preferably with `soft_logout: true`. When a client
receives this error and it has a refresh token, it should attempt to
refresh the access token by calling `/refresh`. Clients can also
refresh their access token at any time, even if it has not yet
expired. If the token refresh succeeds, it should use the new token
for future requests, and can re-try previously-failed requests with
the new token. When an access token is refreshed, a new refresh token
may be returned; if a new refresh token is given, the old refresh
token will be invalidated, and the new refresh token should be used
when the access token needs to be refreshed.
If the token refresh fails, then the client can treat it as a [soft
logout](#soft-logout), if the error response included a `soft_logout:
true` property, and attempt to obtain a new access token by re-logging
in. If the error response does not include a `soft_logout: true`
property, the client should consider the user as being logged out.
Handling of clients that do not support refresh tokens is up to the
homeserver; clients indicate their support for refresh tokens by
including a `refresh_token: true` property in the request body of the
`/login` and `/register` endpoints. For example, homeservers may allow
the use of non-expiring access tokens, or may expire access tokens
anyways and rely on soft logout behaviour on clients that don't
support refreshing.
### Soft logout ### Soft logout
When a request fails due to a 401 status code per above, the server can A client can be in a "soft logout" state if the server requires
include an extra response parameter, `soft_logout`, to indicate if the re-authentication before continuing, but does not want to invalidate
client's persisted information can be retained. This defaults to the client's session. That is, any persisted state held by the client,
`false`, indicating that the server has destroyed the session. Any such as encryption keys and device information, must not be reused and
persisted state held by the client, such as encryption keys and device must be discarded, and can be re-used if the client successfully
information, must not be reused and must be discarded. re-authenticates.
When `soft_logout` is true, the client can acquire a new access token by The server indicates that the client is in a soft logout state by
specifying the device ID it is already using to the login API. In most including a `soft_logout: true` parameter in an `M_UNKNOWN_TOKEN`
cases a `soft_logout: true` response indicates that the user's session error response; the `soft_logout` parameter defaults to `false`.
has expired on the server-side and the user simply needs to provide
their credentials again.
In either case, the client's previously known access token will no A client that receives such a response can try to [refresh its access
longer function. token](#refreshing-access-tokens), if it has a refresh token
available. If it does not have a refresh token available, or
refreshing fails with `soft_logout: true`, the client can acquire a
new access token by specifying the device ID it is already using to
the login API.
### User-Interactive Authentication API ### User-Interactive Authentication API
@ -1105,6 +1156,8 @@ errcode of `M_EXCLUSIVE`.
{{% http-api spec="client-server" api="login" %}} {{% http-api spec="client-server" api="login" %}}
{{% http-api spec="client-server" api="refresh" %}}
{{% http-api spec="client-server" api="logout" %}} {{% http-api spec="client-server" api="logout" %}}
#### Login Fallback #### Login Fallback

@ -1,5 +1,6 @@
# Copyright 2016 OpenMarket Ltd # Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd # Copyright 2018 New Vector Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -133,6 +134,11 @@ paths:
description: |- description: |-
A display name to assign to the newly-created device. Ignored A display name to assign to the newly-created device. Ignored
if `device_id` corresponds to a known device. if `device_id` corresponds to a known device.
refresh_token:
type: boolean
description: |-
If true, the client supports refresh tokens.
x-addedInMatrixVersion: "1.3"
required: ["type"] required: ["type"]
responses: responses:
@ -142,6 +148,8 @@ paths:
application/json: { application/json: {
"user_id": "@cheeky_monkey:matrix.org", "user_id": "@cheeky_monkey:matrix.org",
"access_token": "abc123", "access_token": "abc123",
"refresh_token": "def456",
"expires_in_ms": 60000,
"device_id": "GHTYAJCE", "device_id": "GHTYAJCE",
"well_known": { "well_known": {
"m.homeserver": { "m.homeserver": {
@ -163,6 +171,23 @@ paths:
description: |- description: |-
An access token for the account. An access token for the account.
This access token can then be used to authorize other requests. This access token can then be used to authorize other requests.
refresh_token:
type: string
description: |-
A refresh token for the account. This token can be used to
obtain a new access token when it expires by calling the
`/refresh` endpoint.
x-addedInMatrixVersion: "1.3"
expires_in_ms:
type: integer
description: |-
The lifetime of the access token, in milliseconds. Once
the access token has expired a new access token can be
obtained by using the provided refresh token. If no
refresh token is provided, the client will need re-log in
to obtain a new access token. If not given, the client can
assume that the access token will not expire.
x-addedInMatrixVersion: "1.3"
home_server: home_server:
type: string type: string
description: |- description: |-

@ -0,0 +1,107 @@
# Copyright 2022 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
swagger: '2.0'
info:
title: "Matrix Client-Server Registration and Login API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/v3
consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/refresh":
post:
x-addedInMatrixVersion: "1.3"
summary: Refresh an access token
description: |-
Refresh an access token. Clients should use the returned access token
when making subsequent API calls, and store the returned refresh token
(if given) in order to refresh the new access token when necessary.
After an access token has been refreshed, a server can choose to
invalidate the old access token immediately, or can choose not to, for
example if the access token would expire soon anyways. Clients should
not make any assumptions about the old access token still being valid,
and should use the newly provided access token instead.
Note that this endpoint does not require authentication, since
authentication is provided via the refresh token.
Application Service identity assertion is disabled for this endpoint.
operationId: refresh
parameters:
- in: body
name: body
required: true
schema:
type: object
example: {
"refresh_token": "some_token"
}
properties:
refresh_token:
type: string
description: The refresh token
responses:
200:
description: A new access token and refresh token were generated.
examples:
application/json: {
"access_token": "a_new_token",
"expires_in_ms": 60000,
"refresh_token": "another_new_token"
}
schema:
type: object
properties:
access_token:
type: string
description: |-
The new access token to use.
refresh_token:
type: string
description: |-
The new refresh token to use when the access token needs to
be refreshed again. If not given, the old refresh token can
be re-used.
expires_in_ms:
type: integer
description: |-
The lifetime of the access token, in milliseconds. If not
given, the client can assume that the access token will not
expire.
required:
- access_token
401:
description: |-
The provided token was unknown, or has already been used.
examples:
application/json: {
"errcode": "M_UNKNOWN_TOKEN",
"error": "Soft logged out",
"soft_logout": true
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"

@ -1,4 +1,5 @@
# Copyright 2016 OpenMarket Ltd # Copyright 2016 OpenMarket Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -127,6 +128,11 @@ paths:
returned from this call, therefore preventing an automatic returned from this call, therefore preventing an automatic
login. Defaults to false. login. Defaults to false.
example: false example: false
refresh_token:
type: boolean
description: |-
If true, the client supports refresh tokens.
x-addedInMatrixVersion: "1.3"
responses: responses:
200: 200:
description: The account has been registered. description: The account has been registered.
@ -152,6 +158,27 @@ paths:
An access token for the account. An access token for the account.
This access token can then be used to authorize other requests. This access token can then be used to authorize other requests.
Required if the `inhibit_login` option is false. Required if the `inhibit_login` option is false.
refresh_token:
type: string
description: |-
A refresh token for the account. This token can be used to
obtain a new access token when it expires by calling the
`/refresh` endpoint.
Omitted if the `inhibit_login` option is false.
x-addedInMatrixVersion: "1.3"
expires_in_ms:
type: integer
description: |-
The lifetime of the access token, in milliseconds. Once
the access token has expired a new access token can be
obtained by using the provided refresh token. If no
refresh token is provided, the client will need re-log in
to obtain a new access token. If not given, the client can
assume that the access token will not expire.
Omitted if the `inhibit_login` option is false.
x-addedInMatrixVersion: "1.3"
home_server: home_server:
type: string type: string
description: |- description: |-

Loading…
Cancel
Save