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 as ASN, IP, and User_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.

The api.refreshToken.setExpiresAt(absolute) and api.refreshToken.setIdleExpiresAt(idle) methods are not available for Resource Owner Password Flow, Sign In with Apple to Native iOS Apps, and Facebook Login to Native Apps.

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 response access_denied error

  • Issue 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 plus organization_refresh_token_lifetime

  • Existing Tokens: event.refresh_token.created_at plus organization_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.