Merge pull request #1056 from uhoreg/refresh_token_spec
Add spec for refresh tokens
This commit is contained in:
commit
8d82366cf2
5 changed files with 239 additions and 21 deletions
1
changelogs/client_server/newsfragments/1056.feature
Normal file
1
changelogs/client_server/newsfragments/1056.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Add refresh tokens, per [MSC2918](https://github.com/matrix-org/matrix-spec-proposals/pull/2918).
|
|
@ -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.
|
||||
|
||||
`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
|
||||
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
|
||||
parameter or through an Authorization Header of `Bearer $access_token`.
|
||||
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 %}}
|
||||
This specification does not mandate a particular format for the access
|
||||
|
@ -338,40 +339,94 @@ inaccessible for the client.
|
|||
|
||||
When credentials are required but missing or invalid, the HTTP call will
|
||||
return with a status of 401 and the error code, `M_MISSING_TOKEN` or
|
||||
`M_UNKNOWN_TOKEN` respectively.
|
||||
`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. {{< added-in v="1.3" >}} 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
|
||||
|
||||
Client [devices](../index.html#devices) are closely related to access
|
||||
tokens. Matrix servers should record which device each access token is
|
||||
assigned to, so that subsequent requests can be handled correctly.
|
||||
tokens and refresh tokens. Matrix servers should record which device
|
||||
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)
|
||||
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,
|
||||
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
|
||||
invalidate any access token previously assigned to that device. There is
|
||||
therefore at most one active access token assigned to each device at any
|
||||
one time.
|
||||
invalidate any access and refresh tokens previously assigned to that device.
|
||||
|
||||
### 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`](#post_matrixclientv3refresh). Clients can also refresh their
|
||||
access token at any time, even if it has not yet expired. If the token refresh
|
||||
succeeds, the client 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.
|
||||
|
||||
The old refresh token remains valid until the new access token or refresh token
|
||||
is used, at which point the old refresh token is revoked. This ensures that if
|
||||
a client fails to receive or persist the new tokens, it will be able to repeat
|
||||
the refresh operation.
|
||||
|
||||
If the token refresh fails and the error response included a `soft_logout:
|
||||
true` property, then the client can treat it as a [soft logout](#soft-logout)
|
||||
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`](#post_matrixclientv3login) and
|
||||
[`/register`](#post_matrixclientv3register) 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
|
||||
|
||||
When a request fails due to a 401 status code per above, the server can
|
||||
include an extra response parameter, `soft_logout`, to indicate if the
|
||||
client's persisted information can be retained. This defaults to
|
||||
`false`, indicating that the server has destroyed the session. Any
|
||||
A client can be in a "soft logout" state if the server requires
|
||||
re-authentication before continuing, but does not want to invalidate the
|
||||
client's session. The server indicates that the client is in a soft logout
|
||||
state by including a `soft_logout: true` parameter in an `M_UNKNOWN_TOKEN`
|
||||
error response; the `soft_logout` parameter defaults to `false`. If the
|
||||
`soft_logout` parameter is omitted or is `false`, this means the server has
|
||||
destroyed the session and the client should not reuse it. That is, any
|
||||
persisted state held by the client, such as encryption keys and device
|
||||
information, must not be reused and must be discarded.
|
||||
information, must not be reused and must be discarded. If `soft_logout` is
|
||||
`true` the client can reuse any persisted state.
|
||||
|
||||
When `soft_logout` is true, the client can acquire a new access token by
|
||||
specifying the device ID it is already using to the login API. In most
|
||||
cases a `soft_logout: true` response indicates that the user's session
|
||||
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
|
||||
longer function.
|
||||
{{% changed-in v="1.3" %}} A client that receives such a response can try to
|
||||
[refresh its access 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
|
||||
|
||||
|
@ -1105,6 +1160,8 @@ errcode of `M_EXCLUSIVE`.
|
|||
|
||||
{{% http-api spec="client-server" api="login" %}}
|
||||
|
||||
{{% http-api spec="client-server" api="refresh" %}}
|
||||
|
||||
{{% http-api spec="client-server" api="logout" %}}
|
||||
|
||||
#### Login Fallback
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright 2016 OpenMarket 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");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -133,6 +134,11 @@ paths:
|
|||
description: |-
|
||||
A display name to assign to the newly-created device. Ignored
|
||||
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"]
|
||||
|
||||
responses:
|
||||
|
@ -142,6 +148,8 @@ paths:
|
|||
application/json: {
|
||||
"user_id": "@cheeky_monkey:matrix.org",
|
||||
"access_token": "abc123",
|
||||
"refresh_token": "def456",
|
||||
"expires_in_ms": 60000,
|
||||
"device_id": "GHTYAJCE",
|
||||
"well_known": {
|
||||
"m.homeserver": {
|
||||
|
@ -163,6 +171,23 @@ paths:
|
|||
description: |-
|
||||
An access token for the account.
|
||||
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 to 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:
|
||||
type: string
|
||||
description: |-
|
||||
|
|
108
data/api/client-server/refresh.yaml
Normal file
108
data/api/client-server/refresh.yaml
Normal file
|
@ -0,0 +1,108 @@
|
|||
# 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
|
||||
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.
|
||||
|
||||
The old refresh token remains valid until the new access token or refresh token
|
||||
is used, at which point the old refresh token is revoked.
|
||||
|
||||
Note that this endpoint does not require authentication via an
|
||||
access token. 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 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.
|
||||
|
@ -127,6 +128,11 @@ paths:
|
|||
returned from this call, therefore preventing an automatic
|
||||
login. Defaults to false.
|
||||
example: false
|
||||
refresh_token:
|
||||
type: boolean
|
||||
description: |-
|
||||
If true, the client supports refresh tokens.
|
||||
x-addedInMatrixVersion: "1.3"
|
||||
responses:
|
||||
200:
|
||||
description: The account has been registered.
|
||||
|
@ -152,6 +158,27 @@ paths:
|
|||
An access token for the account.
|
||||
This access token can then be used to authorize other requests.
|
||||
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 to 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:
|
||||
type: string
|
||||
description: |-
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue