- Client Credentials Flow: The application acts on its own behalf and authenticates as itself. The request may have been initiated by a user, but that context will be lost. The downstream service only knows the identity of the calling application.
- On-Behalf-Of (OBO) Token Exchange: The application receives a user-scoped token and can exchange it for a new token to call downstream services. This preserves the identity and context of the original end user throughout the call chain.
- Maintains the original user’s identity and permissions
- Is scoped specifically for Service B
- Enables Service B to make authorization decisions based on the end user
post-login Action trigger, where:
- The
event.transaction.protocolis set tooauth2-token-exchange. - The
event.transaction.actortracks the complete delegation chain.
When you purchase the Auth0 for AI Agents add-on, you can use your subscription tier’s maximum Authentication API rate limit for OBO token exchanges. For example, if you are on Private Cloud 100 RPS, you can exceed the OBO token exchange rate limit of 30 RPS and leverage the full 100 RPS capacity for your OBO token exchange requests. The Authentication API limit is shared and acts as the global ceiling for all Authentication API requests, including logins, token refreshes, and token exchanges combined. Reach out to your Technical Account Manager for more information.
Use cases
Common use cases for the OBO Token Exchange include:- MCP servers that need to call first-party APIs on the user’s behalf
- Microservices that need to call downstream services on the user’s behalf
How it works
OBO token exchange enables middle-tier services to exchange an incoming user token for a new token scoped to a downstream service. The new token preserves the original user’s identity while tracking the chain of services involved in the JSON Web Token (JWT) payload.Example: MCP server calls first-party API
A user authenticates with Auth0 to a client application, which then calls an MCP server, which in turn needs to call a first-party API.Step 1: User authentication
When the user logs in, Auth0 issues an access token scoped for the MCP server with the following claims in the JWT payload:| Claim | Value | Description |
|---|---|---|
sub | auth0|user123 | The end-user’s identity |
aud | https://mcp-server.example.com | Token scoped for the MCP server |
azp (or client_id depending on the Access token profile) | spa_client_id | The client application that requested the token |
Step 2: OBO exchange
Using the OBO token exchange, the MCP server presents the user’s token to Auth0 and requests an access token scoped to the first-party API. Auth0 issues a new access token scoped for the API with the following claims:| Claim | Value | Description |
|---|---|---|
sub | auth0|user123 | Same user identity preserved |
aud | https://first-party-api.example.com | Token scoped for the first-party API |
azp (or client_id depending on the Access token profile) | mcp_server_client_id | Client that requested the token (the MCP server that performed the exchange) |
act | {"sub": "mcp_server_client_id", "act": {"sub": "spa_client_id"}} | Delegation chain showing all actors involved |
The act claim
The act (actor) claim tracks the complete delegation chain. Each act level represents a service in the call chain, with the outermost act.sub identifying the current actor that performed the token exchange.
In our example:
- Outermost
act.sub:mcp_server_client_id(the MCP server that just exchanged the token) - Nested
act.sub:spa_client_id(the original client application)
azp claim should match the outermost act.sub value, identifying the service that most recently performed the token exchange.
If the first-party API calls another downstream service (https://calendar-api.acme.com), the delegation chain would extend:
act levels.
Cache access tokens for the lifetime of the token instead of requesting a new token for each API call. Access tokens are reusable until they expire; repeated token exchanges waste resources, increase latency, and may trigger rate limits.
User > MCP server > API flow
The following diagram shows an end-to-end OBO token exchange flow where an MCP server calls a first-party API on the user’s behalf:- User authentication: The user authenticates with the client application. The Auth0 Authorization Server issues Token A, scoped for the MCP server.
- Initial request: The client application calls the MCP Server, passing Token A in the
Authorization: Bearerheader. - Validation and token exchange: The MCP server receives Token A, validates it, and passes it to the Auth0 Authorization Server’s
/oauth/tokenendpoint. Using the OBO token exchange, the MCP server presents Token A as thesubject_tokenand requests a new token for the first-party API. - Token issuance: The Auth0 Authorization Server issues Token B. Token B has the same
sub(user ID) as Token A, but theaud(audience) is now the first-party API. - Downstream call: The MCP Server calls the first-party API using Token B. The API validates Token B and sees that the request is legitimately being made “on behalf of” the original user.
User > API1 > API2 > API3
The following diagram shows an end-to-end flow of a chain of microservices making downstream calls on the user’s behalf:- User authentication: The user successfully authenticates with a client application. The Auth0 Authorization Server issues Token A, scoped for API1.
- Initial request: The client application calls API1, passing Token A in the
Authorization: Bearerheader. - API1 delegates to API2: API1 receives Token A, validates it, then passes it to the Auth0 Authorization Server’s
/oauth/tokenendpoint. Using the OBO token exchange, API1 presents Token A as thesubject_tokenand requests a new token for API2. - Token issuance: The Auth0 Authorization Server grants a new access token, Token B, to API1. Token B has the same
sub(user ID) as Token A, but theaud(audience) is now API2. - Downstream call: API1 makes a request to API2 using Token B.
- API2 delegates to API3: API2 receives Token B, validates it, then passes it to the Auth0 Authorization Server’s
/oauth/tokenendpoint. Using the OBO token exchange, API2 presents Token B as thesubject_tokenand requests a new token for API3. - Token issuance: The Auth0 Authorization Server grants a new access token, Token C, to API2. Token C has the same
sub(user ID) as Token A and B, but theaud(audience) is now API3. - Downstream call: API2 makes a request to API3 using Token C. API3 validates Token C and sees that the request is legitimately being made “on behalf of” the original user.
Prerequisites
Only Custom API clients associated with a resource server can use the OBO token exchange. A Custom API client is linked to a resource server when they share the same identifier. Custom API clients have the following requirements:- Set
app_typetoresource_server. - Set
resource_server_identifierto the valid resource server, i.e.,https://my-api.example.com. Auth0 uses the resource server identifier as the audience parameter in authorization calls.
Create Custom API client
You can create a Custom API client using the Auth0 Dashboard or Management API.- Auth0 Dashboard
- Management API
To create a Custom API client in the Auth0 Dashboard:

- Navigate to Applications > APIs and select your backend API.

- Select Add Application and enter an application name.
- Select Add.

Create client grant
You need to create a user-delegated client grant between the Custom API client and the downstream API to authorize access.- Auth0 Dashboard
- Management API
- Navigate to Applications > Applications and select your Custom API client.
- Under API Access, find your resource server (i.e.,
https://my-api.example.com) and select Edit. - Under User-Delegated Access, select Grant Access, then select the permissions you want to grant or Always grant all permissions.
- Select Save.
Configure the OBO token exchange
Learn how to configure your Custom API client with the OBO token exchange grant.- Auth0 Dashboard
- Management API
- Navigate to Applications > Applications and select your Custom API client.
- Under Token Exchange, toggle on On-Behalf-Of Token Exchange.
- Select Save.
Perform OBO token exchange
To perform the OBO token exchange, you can useauth0-api-js, auth0_api_python, or the Authentication API.
Cache access tokens for the lifetime of the token instead of requesting a new token for each API call. Access tokens are reusable until they expire; repeated token exchanges waste resources, increase latency, and may trigger rate limits.
- JavaScript
- Python
- cURL
Before you begin, make sure you’ve installed the Then, use the
auth0-api-js library and its dependencies.First, initialize the ApiClient with your MCP server’s credentials:getTokenOnBehalfOf() method to exchange tokens:getTokenOnBehalfOf() returns an object containing:accessToken: The new token for your downstream APIscope: The granted scopesexpiresIn: Token expiration time in seconds
Organizations support
When a user authenticates through an organization, the access token includes anorg_id claim. OBO token exchange preserves this organization context throughout the delegation chain.
When Auth0 receives an OBO token exchange request with an org-bound access token, it validates:
- The
org_idexists in your tenant - The user (identified by
sub) is a member of that organization
- Contains the same
org_idclaim as the original token - Applies the same organization-specific RBAC policies
- Makes the organization context available in the
post-loginActions trigger via theevent.organizationproperty