Link to reproduction
N/A
To Reproduce
Setup a new Payload CMS and sign in using API.
Describe the Bug
TL;DR
Main concern is that an access token is forever functional and can forever be renewed - and can't be revoked.
Current refresh token flow
When an issued access_token is about to expire, one can call the [user-collection]/refresh-token endpoint to retrieve a new token.
Quoted from current documentation:
If your user has a token that is about to expire, but the user is still active and using the app, you might want to use the refresh operation to receive a new token by sending the operation the token that is about to expire.
This operation requires a non-expired token to send back a new one. If the user's token has already expired, you will need to allow them to log in again to retrieve a new token.
If successful, this operation will automatically renew the user's HTTP-only cookie and will send back the updated token in JSON.
This implies that if anyone were to gain access to an access token as a string, they would in theory forever be able to renew the token and there would be no way as admin or user to invalidate or detect this. This could prove critical especially if said access token should belong to an admin.
The OAuth approach
Access Tokens
Access tokens are issued as short-living "tickets" allowing the carrier of said token to access and act on behalf of the subject to which said token has been issued.
Refresh Tokens
Refresh tokens can be either JWTs, opaque strings, or strings of encrypted data which represents an active session. When an access token has expired, the refresh token is used to request a new access token. The refresh token acts as the receipt of a transaction and proves that for a set amount of time, the subject can request access to a resource or service.
Refresh tokens are either stored in a Database on the authentication service which issues tokens, or preferably are self-contained and contain certain data that associates the subject with an active session id and expiration time. The refresh token can also contain data of the audience, which can be a specific application or resource, which helps to set privileges specific for the issued access tokens.
Whenever a refresh token is used to request a new access token, the refresh token is first unwrapped/verified on the auth service. Then the session_id contained in the refresh token is verified by ensuring it hasn't been previously revoked. Hereafter, the subject_id contained in the refresh token is used to issue a new access token.
To revoke a refresh token, oftentimes the session_id is added to a database (RedisDB is usually a good choice) and automatically set to expire from the db table when the refresh token itself is set to expire. This reduces the number of entries in a db necessary, and handles garbage collection automatically.
Client ID and Key
An added level of security would be to issue client credentials which are generated per resource and application, and often tied to the audience identifier in the refresh token.
This way, whenever a refresh token is used to request a new access token, the application/resource is also required to send along their secure client credentials to ensure the action is indeed done by the correct audience and not using a potentially leaked refresh token.
Revoke token
Access tokens can't per definition not be revoked. Hence why they should be short-lived. When a user sends a logout request, the session_id (which could be present in both access token and refresh token) is added to the db table for revoked tokens. Next time a refresh token is used to request and access token, this request is then denied as the session_id is revoked.
From within admin, it could likewise be possible to create a session table for users, which simply lists the session_ids, the create date and expiration of each issued refresh token, and allow the user to revoke manually from within admin. This table is only used to store records or currently active sessions and is only to facilitate the process of revoking a token for the user.
Payload Version
1.15.2
Link to reproduction
N/A
To Reproduce
Setup a new Payload CMS and sign in using API.
Describe the Bug
TL;DR
Main concern is that an access token is forever functional and can forever be renewed - and can't be revoked.
Current refresh token flow
When an issued
access_tokenis about to expire, one can call the[user-collection]/refresh-tokenendpoint to retrieve a new token.Quoted from current documentation:
This implies that if anyone were to gain access to an access token as a string, they would in theory forever be able to renew the token and there would be no way as admin or user to invalidate or detect this. This could prove critical especially if said access token should belong to an admin.
The OAuth approach
Access Tokens
Access tokens are issued as short-living "tickets" allowing the carrier of said token to access and act on behalf of the subject to which said token has been issued.
Refresh Tokens
Refresh tokens can be either JWTs, opaque strings, or strings of encrypted data which represents an active session. When an access token has expired, the refresh token is used to request a new access token. The refresh token acts as the receipt of a transaction and proves that for a set amount of time, the subject can request access to a resource or service.
Refresh tokens are either stored in a Database on the authentication service which issues tokens, or preferably are self-contained and contain certain data that associates the subject with an active session id and expiration time. The refresh token can also contain data of the
audience, which can be a specific application or resource, which helps to set privileges specific for the issued access tokens.Whenever a refresh token is used to request a new access token, the refresh token is first unwrapped/verified on the auth service. Then the
session_idcontained in the refresh token is verified by ensuring it hasn't been previously revoked. Hereafter, thesubject_idcontained in the refresh token is used to issue a new access token.To revoke a refresh token, oftentimes the
session_idis added to a database (RedisDB is usually a good choice) and automatically set to expire from the db table when the refresh token itself is set to expire. This reduces the number of entries in a db necessary, and handles garbage collection automatically.Client ID and Key
An added level of security would be to issue client credentials which are generated per resource and application, and often tied to the
audienceidentifier in the refresh token.This way, whenever a refresh token is used to request a new access token, the application/resource is also required to send along their secure client credentials to ensure the action is indeed done by the correct audience and not using a potentially leaked refresh token.
Revoke token
Access tokens can't per definition not be revoked. Hence why they should be short-lived. When a user sends a logout request, the session_id (which could be present in both access token and refresh token) is added to the db table for revoked tokens. Next time a refresh token is used to request and access token, this request is then denied as the session_id is revoked.
From within admin, it could likewise be possible to create a session table for users, which simply lists the session_ids, the create date and expiration of each issued refresh token, and allow the user to revoke manually from within admin. This table is only used to store records or currently active sessions and is only to facilitate the process of revoking a token for the user.
Payload Version
1.15.2