Skip to main content
Refresh Token Metadata is currently in Early Access for Enterprise customers only. By using this feature, you agree to the applicable Free Trial terms in Okta’s Master Subscription Agreement. To learn more about Auth0’s product release cycle, read Product Release Stages.
To configure refresh token metadata, you can use an Auth0 Post-Login Action and the Management API.

Auth0 Post-Login Actions

You can manage refresh token metadata CRUD operations using the api.refreshToken objects with a post-login Action. This allows you to manage refresh token metadata based on user or context-specific logic.

Retrieve existing refresh token metadata

Use the event.refresh_token.metadata object to read the refresh token metadata:
const deviceName = event.refresh_token?.metadata?.deviceName;
The event.refresh_token.metadata object includes metadata set in:
  • Previous Actions within the same flow
  • Prior transactions if the refresh token was reused during a refresh token exchange

Add or update existing metadata

Use the api.refreshToken.setMetadata() method to set or update the refresh token metadata:
api.refreshToken.setMetadata("deviceName", "Auth0's iPhone");
Changes are immediately available in the event.refresh_token object in subsequent Actions.

Delete refresh token metadata

Use the following api.refreshToken methods to delete refresh token metadata:
  • api.refreshToken.deleteMetadata("key") deletes the specified refresh token metadata
  • api.refreshToken.evictMetadata() deletes all refresh token metadata
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.

Auth0 Management API

You can manage refresh token metadata CRUD (create, replace, update, delete) requests using the Management API:
Calls to the /api/v2/refresh-tokens/{id} endpoint require a Management API access token with the update:refresh_tokens scope.

Retrieve existing refresh token metadata

Make a GET request to the /api/v2/refresh-tokens/{id} endpoint:
GET /api/v2/refresh-tokens/{id}

Add or update existing refresh token metadata

Make a PATCH request to the /api/v2/refresh-tokens/{id} endpoint:
PATCH /api/v2/refresh-tokens/{id}
Content-Type: application/json

{
  "refresh_token_metadata": {
    "my_metadata": "my new metadata"
  }
}

Delete refresh token metadata

Make a PATCH request to the /api/v2/refresh-tokens/{id} endpoint with an empty metadata object:
PATCH /api/v2/refresh-tokens/{id}
Content-Type: application/json

{
  "refresh_token_metadata": {}
}

Use case: Store and consume organization context

You can use refresh token metadata to store organization context during the initial authentication and consume it later during refresh token exchanges. This is useful for downstream systems such as audit, analytics, and revocation pipelines.

Set metadata at initial authentication

During the initial login, set the organization context in the refresh token metadata:
/**
 * Post-Login Action
 * Adds organization context to refresh token metadata during initial authentication.
 * This metadata will be available in subsequent refresh token exchanges.
 */
exports.onExecutePostLogin = async (event, api) => {
  // Only proceed if the transaction targets an Organization
  if (!event.organization) return;

  // Keep values short and string-only (refresh token metadata requires strings)
  const orgId = String(event.organization.id || "");
  const orgSlug = String(event.organization.name || "");
  const orgDisplay = String(event.organization.display_name || orgSlug);

  // Set metadata - this will be stored with the refresh token
  api.refreshToken.setMetadata("org_id", orgId);
  api.refreshToken.setMetadata("org_slug", orgSlug);
  api.refreshToken.setMetadata("org_name", orgDisplay);
};

Consume metadata during refresh token exchange

During a refresh token exchange, the event.refresh_token object exists and you can read the previously stored metadata:
/**
 * Post-Login Action
 * Consumes organization context from refresh token metadata during token exchange.
 * Use this to enforce policies or add claims based on the original authentication context.
 */
exports.onExecutePostLogin = async (event, api) => {
  // Check if this is a refresh token exchange (event.refresh_token exists)
  if (!event.refresh_token) return;

  // Read organization context stored during initial authentication
  const orgId = event.refresh_token.metadata?.org_id;
  const orgSlug = event.refresh_token.metadata?.org_slug;

  if (orgId) {
    // Use the organization context for conditional logic
    console.log(`Refresh token exchange for organization: ${orgSlug}`);
    
    // Example: Add custom claims based on the original org context
    api.accessToken.setCustomClaim("org_id", orgId);
  }
};

Retrieve via Management API

You can also query the refresh token metadata via the /api/v2/refresh-tokens/ endpoint:
GET /api/v2/refresh-tokens/{id}
Sample response:
{
  "refresh_token_metadata": {
    "org_id": "org_abc123",
    "org_slug": "acme",
    "org_name": "Acme Corp"
  }
}

Use case: Track and validate device information

You can use refresh token metadata to capture device information at the initial authentication and validate it during subsequent refresh token exchanges for security purposes.

Set device information at initial authentication

exports.onExecutePostLogin = async (event, api) => {
  // Only set device info if this is NOT a refresh token exchange
  // (i.e., this is the initial authentication)
  if (event.refresh_token) return;

  // Store device information in refresh token metadata
  api.refreshToken.setMetadata("initial_ip", event.request?.ip || "unknown");
  api.refreshToken.setMetadata("initial_asn", event.request?.asn?.value || "unknown");
  api.refreshToken.setMetadata("initial_country", event.request?.geoip?.country_code || "unknown");
  api.refreshToken.setMetadata("initial_user_agent", event.request?.user_agent || "unknown");
};

Validate device information during refresh token exchange

exports.onExecutePostLogin = async (event, api) => {
  // Only validate if this is a refresh token exchange
  if (!event.refresh_token) return;

  // Read the original device information
  const initialCountry = event.refresh_token.metadata?.initial_country;
  const currentCountry = event.request?.geoip?.country_code;

  // Example: Detect country change and take action
  if (initialCountry && currentCountry && initialCountry !== currentCountry) {
    console.log(`Country changed from ${initialCountry} to ${currentCountry}`);
    
    // Option 1: Revoke the refresh token for suspicious activity
    // api.refreshToken.revoke("Suspicious country change detected");
    
    // Option 2: Update metadata to track the change
    api.refreshToken.setMetadata("country_changed", "true");
    api.refreshToken.setMetadata("last_country", currentCountry);
  }
};

Error handling

You can review refresh token metadata log events by navigating to Dashboard > Monitoring > Logs or retrieve logs using the Management API logs endpoint.
  • If an error occurs while adding or updating refresh token metadata with Actions, the authentication transaction fails and an error is returned to the callback URL.
A failure f event code is logged with its corresponding error:
{
  "error": "access_denied",
  "error_description": "Failed to set refresh token metadata: Invalid metadata: Metadata keys may only include letters, numbers, underscores, or hyphens",
  "state": "my-custom-state"
}
  • If a failure occurs when managing refresh token metadata using the Auth0 Management API, the API responds with an HTTP status: 400 error and its corresponding message:
{
  "statusCode": 400,
  "message": "Metadata must not exceed 25 entries. Each key and value must be ≤ 255 characters."
}

Learn more