From b65043873b61039d481478fb238f028706694c2b Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Thu, 25 Nov 2021 13:50:13 +0000 Subject: [PATCH 01/13] Initial attempt at documentation. Diagram missing for now. --- .../user_authentication/refresh_tokens.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/usage/configuration/user_authentication/refresh_tokens.md diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md new file mode 100644 index 000000000000..97ebf731dfc7 --- /dev/null +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -0,0 +1,124 @@ +# Refresh Tokens + +Synapse supports refresh tokens since version 1.49 (some earlier versions had support for an earlier, experimental draft of [MSC2918] which is not compatible). + + +[MSC2918]: https://github.com/matrix-org/matrix-doc/blob/main/proposals/2918-refreshtokens.md#msc2918-refresh-tokens + + +## Background and motivation + +Synapse users' sessions are identified by **access tokens**; access tokens are +issued to users on login and the access token is then used to identify the user +and device making subsequent requests. + +Traditionally, these access tokens were eternally valid (at least until the user +explicitly chose to log out). + +In some cases, it may be desirable for these access tokens to expire so that the +potential damage caused by leaking an access token is reduced. +On the other hand, forcing a user to re-authenticate (log in again) often might +be too much of an inconvenience. + +**Refresh tokens** are a mechanism to avoid some of this inconvenience whilst +still getting most of the benefits of short access token lifetimes. + +When refresh tokens are in use, both an access token and a refresh token will be +issued to users on login. The access token will expire after a predetermined amount +of time, but otherwise works in the same way as before. When the access token is +close to expiring (or has expired), the user's client should present the homeserver +(Synapse) with the refresh token. + +The homeserver will then generate a new access token and refresh token for the user +and return them. The old refresh token is invalidated and can not be used again*. + +Finally, refresh tokens also make it possible for sessions to be logged out if they +are inactive for too long; see the configuration guide below. + + +*To prevent issues if clients lose connection half-way through refreshing a token, +the refresh token is only invalidated once the new access token has been used at +least once. For all intents and purposes, the above simplification is sufficient. + + +## Caveats + +There are some caveats: + +* If a third party gets both your access token and refresh token, they will be able to + continue to enjoy access to your session. + * This is still an improvement because you (the user) will notice when *your* + session expires and you're not able to use your refresh token. + That would be a giveaway that someone else has compromised your session. + You would be able to log in again and terminate that session. + Previously (with long-length access tokens), a third party that has your access + token could go undetected for a very long time. +* Clients need to implement support for refresh tokens in order for them to be a + useful mechanism. + * It is up to homeserver administrators if they want to issue long-lived access + tokens to clients not implementing refresh tokens. + * For compatibility, it is likely that they should at least until client support + is widespread. + * Users with clients that support refresh tokens will still benefit from the + added security; it's not possible to downgrade a session to using long-lived + access tokens so this effectively gives users the choice. + * In a closed environment where all users use known clients, this may not be + an issue as the homeserver administrator can know if the clients have refresh + token support. + + +## Configuration Guide + +The following configuration options, in the `registration` section, are related: + +* `session_lifetime`: maximum length of a session, even if it's refreshed. + In other words, the client must log in again after this time period. + In most cases, this can be unset (infinite) or set to a long time (years or months). +* `refreshable_access_token_lifetime`: lifetime of access tokens that are created + by clients supporting refresh tokens. + This should be short; a good value might be 5 minutes (`5m`). +* `nonrefreshable_access_token_lifetime`: lifetime of access tokens that are created + by clients which don't support refresh tokens. + Make this short if you want to force use of refresh tokens. + Make this long if you don't want to inconvenience users of clients which don't + support refresh tokens. +* `refresh_token_lifetime`: lifetime of refresh tokens. + Unless you want to log inactive sessions out, it is often fine to use a long + value here or even leave it unset (infinite). + Beware that making it too short will inconvenience clients that do not connect + very often, including mobile clients and clients of infrequent users. + + +### Using refresh token expiry to log out inactive sessions + +If you'd like to force sessions to be logged out upon inactivity, you can enable +refreshable access token expiry and refresh token expiry. + +Assuming that clients keep their access token valid whilst they are active, and +that you set `refresh_token_lifetime` to some value *R* and +`refreshable_access_token_lifetime` to some value *A* (which is not bigger than *R*), +then: + 1. sessions may become logged out if they are inactive for more than *R - A*. + (Explanation: if a client goes offline just before it was about to refresh its + access token, then it must come online before the refresh token expires.) + 2. sessions will always become logged out if they are inactive for more than *R*. + (Explanation: if a client refreshes its access token just before going offline, + then returns just before the refresh token expires, it will be able to continue + its session.) + +Clients are able to refresh more frequently than strictly necessary in order to +avoid the case described by point (1) above. + +As an example, if refresh tokens are configured to expire after 20 minutes and +access tokens are configured to expire after 5 minutes, then sessions will definitely +end if inactive for 20 minutes, but may end if inactive for as few as 15 minutes. + + +Note: this will only affect sessions using refresh tokens. You may wish to +set a short `nonrefreshable_access_token_lifetime` to prevent this being bypassed +by clients that do not support refresh tokens. + + +## Diagram + + From 0af540e43a803269e3ffa4200280d6f931c83970 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Thu, 25 Nov 2021 13:51:04 +0000 Subject: [PATCH 02/13] Add Refresh Tokens to docs summary --- docs/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index cdedf8bccc28..23b663aa2717 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -30,6 +30,7 @@ - [SSO Mapping Providers](sso_mapping_providers.md) - [Password Auth Providers](password_auth_providers.md) - [JSON Web Tokens](jwt.md) + - [Refresh Tokens](usage/configuration/user_authentication/refresh_tokens.md) - [Registration Captcha](CAPTCHA_SETUP.md) - [Application Services](application_services.md) - [Server Notices](server_notices.md) From 6c2256fd6419a8a1211a9080e77a0b58843c73d3 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Thu, 25 Nov 2021 13:51:54 +0000 Subject: [PATCH 03/13] Newsfile Signed-off-by: Olivier Wilkinson (reivilibre) --- changelog.d/11427.doc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/11427.doc diff --git a/changelog.d/11427.doc b/changelog.d/11427.doc new file mode 100644 index 000000000000..01cdfcf2b7e4 --- /dev/null +++ b/changelog.d/11427.doc @@ -0,0 +1 @@ +Document the usage of refresh tokens. \ No newline at end of file From 95fe78ee0b2698229f6f6f014008265af8a6571a Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Fri, 3 Dec 2021 15:59:24 +0000 Subject: [PATCH 04/13] Add further reading for refresh tokens (OAuth 2) --- docs/usage/configuration/user_authentication/refresh_tokens.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 97ebf731dfc7..471f92362aa0 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -22,6 +22,8 @@ be too much of an inconvenience. **Refresh tokens** are a mechanism to avoid some of this inconvenience whilst still getting most of the benefits of short access token lifetimes. +Refresh tokens are also a concept present in OAuth 2 — further reading is available +[here](https://datatracker.ietf.org/doc/html/rfc6749#section-1.5). When refresh tokens are in use, both an access token and a refresh token will be issued to users on login. The access token will expire after a predetermined amount From 90f18b681b9506fd4963bf2055f9f6a02a660291 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Fri, 3 Dec 2021 16:02:12 +0000 Subject: [PATCH 05/13] Note that inactivity expiry happens before the natural expiry --- docs/usage/configuration/user_authentication/refresh_tokens.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 471f92362aa0..fd6255f9d82a 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -35,7 +35,8 @@ The homeserver will then generate a new access token and refresh token for the u and return them. The old refresh token is invalidated and can not be used again*. Finally, refresh tokens also make it possible for sessions to be logged out if they -are inactive for too long; see the configuration guide below. +are inactive for too long, before the session naturally ends; see the configuration +guide below. *To prevent issues if clients lose connection half-way through refreshing a token, From e6104a8acfbdf16560b298e098216f02b671fc28 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Mon, 6 Dec 2021 12:20:13 +0000 Subject: [PATCH 06/13] Note that access tokens should be kept secret --- .../usage/configuration/user_authentication/refresh_tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index fd6255f9d82a..4ff96d9b120f 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -9,8 +9,8 @@ Synapse supports refresh tokens since version 1.49 (some earlier versions had su ## Background and motivation Synapse users' sessions are identified by **access tokens**; access tokens are -issued to users on login and the access token is then used to identify the user -and device making subsequent requests. +issued to users on login. Each session gets a unique access token which identifies +it; the access token must be kept secret as it grants access to the user's account. Traditionally, these access tokens were eternally valid (at least until the user explicitly chose to log out). From 4e1359fbc7291552f66ff6a6a6a975e544036a0c Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Mon, 6 Dec 2021 12:22:45 +0000 Subject: [PATCH 07/13] Use 'long-lived' rather than 'long-length' --- docs/usage/configuration/user_authentication/refresh_tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 4ff96d9b120f..47c6f3611702 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -54,7 +54,7 @@ There are some caveats: session expires and you're not able to use your refresh token. That would be a giveaway that someone else has compromised your session. You would be able to log in again and terminate that session. - Previously (with long-length access tokens), a third party that has your access + Previously (with long-lived access tokens), a third party that has your access token could go undetected for a very long time. * Clients need to implement support for refresh tokens in order for them to be a useful mechanism. From 9303f8ca91af15d18628534d071c91f9d2201e06 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Mon, 6 Dec 2021 12:29:46 +0000 Subject: [PATCH 08/13] Note that you can choose to set NRAT lifetimes to be short for security --- .../configuration/user_authentication/refresh_tokens.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 47c6f3611702..866f86ad326d 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -60,14 +60,15 @@ There are some caveats: useful mechanism. * It is up to homeserver administrators if they want to issue long-lived access tokens to clients not implementing refresh tokens. - * For compatibility, it is likely that they should at least until client support + * For compatibility, it is likely that they should, at least until client support is widespread. * Users with clients that support refresh tokens will still benefit from the added security; it's not possible to downgrade a session to using long-lived access tokens so this effectively gives users the choice. * In a closed environment where all users use known clients, this may not be an issue as the homeserver administrator can know if the clients have refresh - token support. + token support. In that case, the non-refreshable access token lifetime + may be set to a short duration so that a similar level of security is provided. ## Configuration Guide @@ -82,7 +83,7 @@ The following configuration options, in the `registration` section, are related: This should be short; a good value might be 5 minutes (`5m`). * `nonrefreshable_access_token_lifetime`: lifetime of access tokens that are created by clients which don't support refresh tokens. - Make this short if you want to force use of refresh tokens. + Make this short if you want to effectively force use of refresh tokens. Make this long if you don't want to inconvenience users of clients which don't support refresh tokens. * `refresh_token_lifetime`: lifetime of refresh tokens. From 8583224410bb925755429247d569f3dbbb0f4a05 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Mon, 6 Dec 2021 12:30:20 +0000 Subject: [PATCH 09/13] Note that the options only apply to new tokens --- docs/usage/configuration/user_authentication/refresh_tokens.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 866f86ad326d..ca97f7d99a7b 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -92,6 +92,9 @@ The following configuration options, in the `registration` section, are related: Beware that making it too short will inconvenience clients that do not connect very often, including mobile clients and clients of infrequent users. +**Note:** All these options only apply to newly-created tokens (i.e. tokens +obtained from logging in or from refreshing), so won't apply retroactively. + ### Using refresh token expiry to log out inactive sessions From 3e2f56ac3ea0e05dd0ebed0af9048c59c9b87823 Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Mon, 6 Dec 2021 12:30:39 +0000 Subject: [PATCH 10/13] Overhaul the calculation section --- .../user_authentication/refresh_tokens.md | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index ca97f7d99a7b..9a9331caddbd 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -101,31 +101,35 @@ obtained from logging in or from refreshing), so won't apply retroactively. If you'd like to force sessions to be logged out upon inactivity, you can enable refreshable access token expiry and refresh token expiry. -Assuming that clients keep their access token valid whilst they are active, and -that you set `refresh_token_lifetime` to some value *R* and -`refreshable_access_token_lifetime` to some value *A* (which is not bigger than *R*), -then: - 1. sessions may become logged out if they are inactive for more than *R - A*. - (Explanation: if a client goes offline just before it was about to refresh its - access token, then it must come online before the refresh token expires.) - 2. sessions will always become logged out if they are inactive for more than *R*. - (Explanation: if a client refreshes its access token just before going offline, - then returns just before the refresh token expires, it will be able to continue - its session.) - -Clients are able to refresh more frequently than strictly necessary in order to -avoid the case described by point (1) above. - -As an example, if refresh tokens are configured to expire after 20 minutes and -access tokens are configured to expire after 5 minutes, then sessions will definitely -end if inactive for 20 minutes, but may end if inactive for as few as 15 minutes. +This works because a client must refresh at least once within a period of +`refresh_token_lifetime` in order to maintain valid credentials to access the +account. +(It's suggested that `refresh_token_lifetime` should be longer than +`refreshable_access_token_lifetime` and this section assumes that to be the case +for simplicity.) Note: this will only affect sessions using refresh tokens. You may wish to set a short `nonrefreshable_access_token_lifetime` to prevent this being bypassed by clients that do not support refresh tokens. -## Diagram +#### Choosing values that guarantee permitting some inactivity +It may be desirable to permit some short periods of inactivity, for example to +accommodate brief outages in client connectivity. +The following model aims to provide guidance for choosing `refresh_token_lifetime` +and `refreshable_access_token_lifetime` to satisfy requirements of the form: + +1. inactivity longer than `L` **MUST** cause the session to be logged out; and +2. inactivity shorter than `S` **MUST NOT** cause the session to be logged out. + +This model makes the weakest assumption that all active clients will refresh as +needed to maintain an active access token, but no sooner. +*In reality, clients may refresh more often than this model assumes, but the +above requirements will still hold.* + +To satisfy the above model, +* `refresh_token_lifetime` should be set to `L`; and +* `refreshable_access_token_lifetime` should be set to `L - S`. From ceb032adf4a08c36aaf9c86bcea5cec91c246e6a Mon Sep 17 00:00:00 2001 From: reivilibre Date: Wed, 8 Dec 2021 14:13:11 +0000 Subject: [PATCH 11/13] Update docs/usage/configuration/user_authentication/refresh_tokens.md Co-authored-by: David Robertson --- docs/usage/configuration/user_authentication/refresh_tokens.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 9a9331caddbd..7c1919aa7042 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -92,8 +92,7 @@ The following configuration options, in the `registration` section, are related: Beware that making it too short will inconvenience clients that do not connect very often, including mobile clients and clients of infrequent users. -**Note:** All these options only apply to newly-created tokens (i.e. tokens -obtained from logging in or from refreshing), so won't apply retroactively. +**Note:** All four options above only apply when tokens are created (by logging in or refreshing). Changes to these settings do not apply retroactively. ### Using refresh token expiry to log out inactive sessions From b4cefa8f3826b0a85b566173d606fed396e0b8ff Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Wed, 8 Dec 2021 14:15:49 +0000 Subject: [PATCH 12/13] Explain consequence of refresh token lifetime --- docs/usage/configuration/user_authentication/refresh_tokens.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index 7c1919aa7042..e815c2f83b25 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -87,6 +87,7 @@ The following configuration options, in the `registration` section, are related: Make this long if you don't want to inconvenience users of clients which don't support refresh tokens. * `refresh_token_lifetime`: lifetime of refresh tokens. + In other words, the client must refresh within this time period to maintain its session. Unless you want to log inactive sessions out, it is often fine to use a long value here or even leave it unset (infinite). Beware that making it too short will inconvenience clients that do not connect From 2b03c7544ce401baf35c71dedae7d9c1cf86600f Mon Sep 17 00:00:00 2001 From: "Olivier Wilkinson (reivilibre)" Date: Wed, 8 Dec 2021 14:28:09 +0000 Subject: [PATCH 13/13] What is inconvenience? --- .../user_authentication/refresh_tokens.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/usage/configuration/user_authentication/refresh_tokens.md b/docs/usage/configuration/user_authentication/refresh_tokens.md index e815c2f83b25..23b3cddae054 100644 --- a/docs/usage/configuration/user_authentication/refresh_tokens.md +++ b/docs/usage/configuration/user_authentication/refresh_tokens.md @@ -85,15 +85,19 @@ The following configuration options, in the `registration` section, are related: by clients which don't support refresh tokens. Make this short if you want to effectively force use of refresh tokens. Make this long if you don't want to inconvenience users of clients which don't - support refresh tokens. + support refresh tokens (by forcing them to frequently re-authenticate using + login credentials). * `refresh_token_lifetime`: lifetime of refresh tokens. In other words, the client must refresh within this time period to maintain its session. Unless you want to log inactive sessions out, it is often fine to use a long value here or even leave it unset (infinite). Beware that making it too short will inconvenience clients that do not connect - very often, including mobile clients and clients of infrequent users. + very often, including mobile clients and clients of infrequent users (by making + it more difficult for them to refresh in time, which may force them to need to + re-authenticate using login credentials). -**Note:** All four options above only apply when tokens are created (by logging in or refreshing). Changes to these settings do not apply retroactively. +**Note:** All four options above only apply when tokens are created (by logging in or refreshing). +Changes to these settings do not apply retroactively. ### Using refresh token expiry to log out inactive sessions