> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.com/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn how to configure Auth0 refresh token metadata

# Configure Refresh Token Metadata

To configure refresh token metadata, you can use an Auth0 [Post-Login Action](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger) and the [Management API](https://auth0.com/docs/api/management/v2).

## Auth0 Post-Login Actions

You can manage refresh token metadata CRUD operations using the `api.refreshToken` objects with a [post-login Action](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger). 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:

```javascript lines theme={null}
const deviceName = event.refresh_token?.metadata?.deviceName;
```

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  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
</Callout>

### Add or update existing metadata

Use the `api.refreshToken.setMetadata()` method to set or update the refresh token metadata:

```javascript lines theme={null}
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](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-event-object): Learn about the refresh token Event object and properties.
* [API object](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-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:

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Calls to the `/api/v2/refresh-tokens/{id}` endpoint require a [Management API access token](/docs/secure/tokens/access-tokens) with the `update:refresh_tokens` scope.
</Callout>

### Retrieve existing refresh token metadata

Make a `GET` request to the [`/api/v2/refresh-tokens/{id}`](https://auth0.com/docs/api/management/v2/refresh-tokens/get-refresh-token) endpoint:

```bash lines theme={null}
GET /api/v2/refresh-tokens/{id}
```

### Add or update existing refresh token metadata

Make a `PATCH` request to the [`/api/v2/refresh-tokens/{id}`](https://auth0.com/docs/api/management/v2/refresh-tokens/patch-refresh-token) endpoint:

```bash lines theme={null}
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}`](https://auth0.com/docs/api/management/v2/refresh-tokens/patch-refresh-token) endpoint with an empty metadata object:

```bash lines theme={null}
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:

```javascript lines theme={null}
/**
 * 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:

```javascript lines theme={null}
/**
 * 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/{id}](https://auth0.com/docs/api/management/v2/refresh-tokens/get-refresh-token) endpoint:

```bash lines theme={null}
GET /api/v2/refresh-tokens/{id}
```

Sample response:

```json lines theme={null}
{
  "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

```javascript lines theme={null}
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

```javascript lines theme={null}
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](https://manage.auth0.com/#/logs) or retrieve logs using the [Management API logs](/docs/api/management/v2/logs/get-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:

```json lines theme={null}
{
  "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:

```json lines theme={null}
{
  "statusCode": 400,
  "message": "Metadata must not exceed 25 entries. Each key and value must be ≤ 255 characters."
}
```

## Learn more

* [Refresh Token Metadata](/docs/secure/tokens/refresh-tokens/refresh-token-metadata)
* [Refresh Tokens with Actions](/docs/secure/tokens/refresh-tokens/manage-refresh-tokens-actions)
* [Refresh Tokens](/docs/secure/tokens/refresh-tokens)
* [Post-Login Event Object](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-event-object)
* [Post-Login API Object](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-api-object)
