Skip to main content

Token Exchange

The OAuth 2.0 Token Exchange (RFC 8693) is a standardized flow that allows a client to exchange one token for another. This is distinct from the standard OAuth authorization code or client credentials flows and is particularly useful in microservices architectures, token delegation scenarios, and when you need to transform tokens for different contexts.

Token-exchange.svg

Token Exchange enables various token transformation scenarios:

  • Access Token β†’ Access Token: Exchange an access token for another access token with different scopes (downscoping or upscoping)
  • ID Token β†’ Access Token: Exchange an ID token for an access token to access protected resources
  • User Token β†’ Service Token: Transform a user's access token into a service token for backend-to-backend communication
  • Cross-Domain Token Exchange: Exchange tokens between different authorization servers or domains

Understanding Token Exchange vs. Other Flows​

It's important to understand that Token Exchange is not a standard OAuth authorization flow like Authorization Code or Client Credentials. Instead, it's a mechanism for transforming existing tokens. Here's how it compares:

FlowPurpose
Authorization CodeEnd-user sign-in + token creation
Client CredentialsService authentication without user
Refresh TokenGet a new access token (same type/scope)
πŸ”„ Token ExchangeConvert existing tokens into new ones

Key Difference: While other flows create tokens from credentials or authorization codes, Token Exchange transforms tokens you already have into different tokens with potentially different scopes, audiences, or types.

When to Use Token Exchange​

Token Exchange is ideal for:

  • Microservices Architecture: Services need to exchange tokens to communicate with each other while maintaining user context
  • Token Delegation: Delegating access from one service to another with appropriate scopes
  • Scope Transformation: Downscoping (reducing permissions) or upscoping (requesting additional permissions) tokens
  • Backend-for-Frontend (BFF) Pattern: Exchanging user tokens for service tokens in backend services
  • Cross-Domain Scenarios: Exchanging tokens between different authorization servers or domains
  • Token Refresh Alternatives: When you need a different token type rather than just refreshing the same token

Key Advantages​

  • Token Transformation: Convert tokens between different types (access token, ID token, etc.)
  • Scope Management: Adjust token scopes to match specific service requirements
  • Audience Support: Request an audience so the exchanged token’s aud claim is set to the target service/API, ensuring the token can only be used by that recipient
  • Delegation Support: Enable secure token delegation in distributed systems
  • User Context Preservation: Maintain user context when exchanging tokens
  • Flexible Architecture: Support complex microservices and multi-tenant scenarios

How it Works​

Before we step into how it works, let's understand some useful parameters.

Parameter NameDescription
grant_typeMust be urn:ietf:params:oauth:grant-type:token-exchange
subject_tokenThe token you want to exchange (e.g., an access token, ID token)
subject_token_typeSpecifies the type of the token being exchanged. Common values: urn:ietf:params:oauth:token-type:access_token, urn:ietf:params:oauth:token-type:id_token
scopeOptional. Defines the desired scopes for the new token. Used for downscoping or upscoping
audienceOptional. Supported. Specifies the intended recipient(s) of the exchanged token. Can be a string (single audience) or an array of strings (multiple audiences). The issued token’s aud claim is set accordingly. See Audience (aud) in Token Exchange below.
client_idClient identifier (required in Authorization header or request body)
client_secretClient secret (required in Authorization header or request body)

Audience (aud) in Token Exchange​

The audience (aud) in a token exchange identifies the intended recipient(s) of the exchanged token. When you include the audience parameter in the token exchange request, the authorization server issues a new token whose aud claim is set to that value. This ensures the token can only be used by the target service(s) or API(s) it was issued forβ€”protecting against token misuse and enabling strict audience validation in microservices and API gateways.

Format: audience can be either:

  • String β€” single audience. The issued token’s aud claim is a single value. Example: audience=api-backend-service
  • Array β€” multiple audiences. The issued token’s aud claim is an array of those values. In application/x-www-form-urlencoded requests, send multiple values with the same parameter name: audience=api-a&audience=api-b

Step 1: The client application makes a POST request to the token endpoint with the subject_token (the token to be exchanged), subject_token_type, grant_type=urn:ietf:params:oauth:grant-type:token-exchange, and optionally scope and audience. The audience parameter is supported and sets the aud claim on the issued token so it can only be used by the target service/API.

Step 2: The authorization server validates:

  • The subject_token is valid and active
  • The client credentials (from Authorization header) are valid
  • The requested scopes are allowed for the subject token
  • The client has permission to perform token exchange

Step 3: If validation succeeds, the authorization server issues a new token (typically an access token) with the requested scopes and audience.

Step 4: The client uses the new token to access protected resources with the transformed permissions.

Technical Integration​

APIDescriptionLink to API
Token ExchangeExchange one token for another with potentially different scopes or audience. Supports the audience parameter so the issued token’s aud claim is set to the intended recipient (target service/API).View API

Example Implementation​

Here are examples of common Token Exchange scenarios:

Example 1: Access Token β†’ Access Token (Downscoping)​

Exchange a user's access token for a new access token with reduced scopes:

POST https://{{base_url}}/token-srv/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {{base64_encoded_client_credentials}}

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token={{user_access_token}}
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&scope=read:data
&audience=api-backend-service

Response: The issued access token will include aud: "api-backend-service" when audience=api-backend-service was requested.

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read:data",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
}

Example 2: ID Token β†’ Access Token​

Exchange an ID token for an access token. Include audience so the new token can only be used by the target API:

POST https://{{base_url}}/token-srv/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {{base64_encoded_client_credentials}}

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token={{id_token}}
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&scope=api:read api:write
&audience=target-api-service

Example 3: User Token β†’ Service Token​

Transform a user's access token into a service token for backend communication:

POST https://{{base_url}}/token-srv/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {{base64_encoded_service_client_credentials}}

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token={{user_access_token}}
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&scope=service:internal
&audience=internal-api-service

Base64 Encoding Example​

To create the Authorization header, Base64-encode client_id:client_secret:

# Example: client_id="my-client-id", client_secret="my-client-secret"
# Encoded: bXktY2xpZW50LWlkOm15LWNsaWVudC1zZWNyZXQ=

Authorization: Basic bXktY2xpZW50LWlkOm15LWNsaWVudC1zZWNyZXQ=

JavaScript Example:

const credentials = btoa(`${client_id}:${client_secret}`);
const authHeader = `Basic ${credentials}`;

Security Considerations​

Security Note​

Important: Token Exchange should only be performed by confidential clients (server-side applications) that can securely store the client_secret. Never perform token exchange from client-side code.

1. Confidential Client Requirement​

  • Only confidential clients (server-side applications) should perform token exchanges
  • Ensure the client_secret is securely stored and never exposed
  • Use environment variables or secret management systems

2. Authorization Header Security​

  • The Authorization header must include valid credentials (Base64-encoded client ID and secret)
  • If credentials are compromised, attackers can perform malicious token exchanges, leading to privilege escalation
  • Always use HTTPS/TLS for all token exchange requests

3. Scope Restriction (Principle of Least Privilege)​

  • Minimize the scope of the newly issued token to the least privilege required
  • Use downscoping to reduce permissions when possible
  • Avoid upscoping unless absolutely necessary and authorized

4. Subject Token Validation​

  • The Authorization Server validates the subject_token to ensure it is still active
  • The server verifies the token was issued to the correct client
  • Expired or revoked tokens cannot be exchanged

5. Token Lifetime Management​

  • Use short lifetimes for exchanged tokens to limit exposure
  • Ensure exchanged tokens are only active for the required backend service "session"
  • Implement proper token caching and expiration handling

6. Audit and Monitoring​

  • Log all token exchange requests for security auditing
  • Monitor for unusual patterns (e.g., frequent exchanges, unexpected scope requests)
  • Alert on failed exchange attempts or privilege escalation attempts

Common Use Cases​

Use Case 1: Microservices Token Delegation​

A frontend service receives a user's access token and needs to call a backend microservice. The frontend exchanges the user token for a service token with appropriate scopes for the microservice.

Use Case 2: Scope Downscoping​

A user grants broad permissions to an application, but the application needs to call a third-party API with limited permissions. The application exchanges the broad-scope token for a narrow-scope token.

Use Case 3: Backend-for-Frontend (BFF) Pattern​

A BFF service receives user tokens from the frontend and exchanges them for service tokens to communicate with backend APIs, keeping the user context while using service credentials.

Use Case 4: Cross-Domain Token Exchange​

An application needs to access resources in a different domain. It exchanges its current token for a token valid in the target domain.

Comparison with Other Flows​

AspectToken ExchangeClient CredentialsAuthorization Code
User Interaction❌ No❌ Noβœ… Yes
Client Secretβœ… Requiredβœ… Requiredβœ… Required
Use CaseToken transformation, delegationM2M, BackendUser authentication
InputExisting tokenClient credentialsUser credentials
OutputNew token (different type/scope)Access tokenAccess token
Best ForMicroservices, token delegationServer-to-serverUser-facing apps

References​

Need Support?​

Please contact us directly on our support page.