Refresh Tokens with Actions
Using Refresh tokens with Actions allows you to configure post-authentication risk detection and response capabilities to protect your applications and users against compromised refresh tokens. You can also dynamically customize the refresh token expirations.
To facilitate this, post-login Actions feature two key objects:
event.refresh_token: Provides relevant information for existing refresh_tokens including
id
,created_at
,expires_at
,idle_expires_at
,clients_id
,device
information, such asASN
,IP
, andUser_agent
, and for browser-based flows,session_id
. This object is populated by refresh token exchange flows.api.refreshToken: Allows you to manage existing refresh tokens by revoking sessions or changing expiry dates.
You can use the event.refresh_token
object to review the last_exchange_at
property and evaluate risks associated with the current transactions. You can also combine the event.refresh_token
object with other event objects, such as the event.authentication
.
You can then use the api.refreshToken
object to either set refresh token expiry dates or revoke the refresh token.
To learn more about these objects, review:
Event object: Learn about the refresh token Event object and properties.
API object: Learn about the refresh token API object and methods.
Revoke refresh tokens with Actions
The post-login api.refreshToken.revoke(reason) method allows you to react to risks associated with a transaction. Revoking the refresh token, invalidates the refresh token, returns a 403 HTTP status code to deny the current transaction, and logs a refresh token revoked event in the tenant logs (srrt
).
Monitor revoke log events
The revoke operation adds the following log event in your tenant logs:
A srrt
event code indicating a refresh token was revoked.
If the refresh token is bound to a previously authenticated session, the log will include a reference to the authenticated session in the session_id
attribute.
Change refresh tokens expiry dates with Actions
You can modify refresh tokens expiry dates with the following post-login methods:
api.refreshToken.setExpiresAt(absolute) allows you to define a new absolute expiration date for a specified refresh token.
api.refreshToken.setIdleExpiresAt(idle) allows you to set a new inactivity timeout expiration date for a specified refresh token.
You can use these methods to dynamically customize the refresh token lifetime and inactivity policies based on:
A user’s organization
A user’s Auth0 connection
A specific user’s group membership or profile
Risk assessment
Any other dynamic criteria available during execution of the Action
Limitations
Refresh tokens issued on or after 21-09-2023 (22-02-2024 for tenants in the US-3 region) contain the session ID (session_id
) property with the appropriate value. Refresh tokens issued before this date contain this property with a null
value.
Refresh tokens issued before the release of the post-login API method api.refreshToken.revoke(reason)
will not contain event.refresh_token.device
information.
Non-expiring refresh tokens or refresh tokens that have not been exchanged will not contain the property event.refresh_token.last_exchanged_at
.
For security reasons, inactivity and absolute timeouts cannot be set above the application refresh token settings defined in the refresh token expirations. If you attempt to set a date above the expiration settings, the API methods will update up to the refresh token expirations and log a warning event (w
) in the tenant logs.
Use cases: Revoke a refresh token
You can use Actions to configure risk detections and revoke refresh tokens with the api.refreshToken.revoke(reason)
method and the event objects.
Revoke refresh tokens due to ImpossibleTravel
You can use the Adaptive MFA assessments object to determine if a user is logging from a location that indicates ImpossibleTravel and revoke the current refresh token associated with the transaction.
exports.onExecutePostLogin = async (event, api) => {
const { riskAssessment } = event.authentication ?? {};
const ImpossibleTravel = riskAssessment?.assessments.ImpossibleTravel;
// If this is an impossible travel and this is a refresh token exchange
if (ImpossibleTravel?.code === "impossible_travel_from_last_login") {
if (event.refresh_token) {
api.refreshToken.revoke("Refresh token revoked due to impossible travel");
}
}
};
Was this helpful?
In this example, a check occurs at the start of the Action to verify that the event.authentication.ImpossibleTravel.code
is equal to the impossible_travel_from_last_login property
. If true
, the Action calls the api.refreshToken.revoke()
to:
Deny the transaction
Revoke the refresh token
Return a 403 response access_denied error
Issue the error “Refresh token revoked due to impossible travel”
Revoke refresh tokens due to IP binding
If you use the post-login object properties event.refresh_token.device.initial_ip
and event.request.ip
to ensure a refresh token transaction stays with the same IP address for its duration. In this scenario, any IP change is considered a risk, and a new refresh token is required.
exports.onExecutePostLogin = async (event, api) => {
const refreshTokenInitialIp = event.refresh_token?.device?.initial_ip;
const requestCurrentIp = event.request.ip;
// if there is a refresh token and the IP changes
if (
refreshTokenInitialIp &&
requestCurrentIp &&
refreshTokenInitialIp != requestCurrentIp
) {
api.refreshToken.revoke("Invalid IP change");
}
};
Was this helpful?
In this example, a check occurs at the start of the Action to keep track of the IP addresses with the event.refresh_token.device.initial_ip
and the event.request.ip
properties. The Action determines if the transaction IP address has changed. If true
, the Action calls the api.refreshToken.revoke()
to:
Deny the transaction
Revoke the refresh token
Return a
403
responseaccess_denied
errorIssue the error “
Invalid IP change
”
Alternatively, for a less restrictive Action, you can keep track of the event.request.asn
and event.refresh_token.device.initial_asn
properties to monitor for ASN changes instead of IP changes.
Use cases: Customize refresh token expiry dates
You can use Actions to customize the refresh token lifetime and inactivity dates. Specifically, you can configure the refresh token idle and absolute expiration dates for a particular transaction using the post-login api.refreshToken.setExpiresAt(absolute)
and api.refreshToken.setIdleExpiresAt(idle)
methods.
Customize absolute refresh token expiration date based on Organization
You can use post login action to define a refresh token lifetime per Organization. The example below uses the refresh_token_timeout
metadata from the Organization to set the expiration time of the refresh token.
exports.onExecutePostLogin = async (event, api) => {
// Refresh token timeout (in miliseconds) metadata configured in the Organizations
const organization_refresh_token_lifetime =
event.organization?.metadata?.refresh_token_timeout;
if (organization_refresh_token_lifetime) {
// Refresh token already exists
if (event.refresh_token) {
const created = Date.parse(event.refresh_token.created_at);
const new_expiration_time =
created + Number(organization_refresh_token_lifetime);
api.refreshToken.setExpiresAt(new_expiration_time);
} else {
// Refresh token doesn't exist yet (e.g., token is being issued)
const current_time = new Date().getTime();
const new_expiration_time =
current_time + Number(organization_refresh_token_lifetime);
api.refreshToken.setExpiresAt(new_expiration_time);
}
}
};
Was this helpful?
In this example, If there is a specific absolute timeout defined for an Organization, the Action sets the refresh token absolute timeout to be equal to:
Newly issued tokens:
current_time
plusorganization_refresh_token_lifetime
Existing Tokens:
event.refresh_token.created_at
plusorganization_refresh_token_lifetime
Customize refresh token inactivity timeout based on membership role
You can use post login action to define a refresh token idle timeout using application and user metadata. The example below uses the user metadata roles to define the user membership role and Application metadata to define the expected refresh token idle timeout.
exports.onExecutePostLogin = async (event, api) => {
// admins are configured with a shorter idle timeout for refresh tokens, in an application metadata
const max_idle_lifetime =
event.client.metadata?.admin_refresh_token_idle_timeout;
// Check the user app metadata roles attribute to check if it is an admin user.
const isAdmin = event.user?.app_metadata?.roles?.find(
(role) => role === "admin",
);
// If the application has an specific idle timeout defined, set the timeout
if (max_idle_lifetime && isAdmin) {
const current_time = new Date().getTime();
api.refreshToken.setIdleExpiresAt(current_time + Number(max_idle_lifetime));
}
};
Was this helpful?
In this example, if there is a specific idle timeout defined for the Application and the user is an Admin, the Action sets the refresh token inactivity timeout to be equal to the current_time
plus the refresh_token_idle_timeout
. Note that we are changing the timeout for both newly issued tokens and existing ones during refresh token exchange.