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

# Get Token

> The On-Behalf-Of (OBO) Token Exchange enables a middle-tier service to exchange an incoming user token for a new token scoped to the downstream service.

`POST /oauth/token`

The On-Behalf-Of (OBO) Token Exchange ([RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693)) enables middle-tier services to exchange a user-scoped token for a new token to call downstream services.

The new token maintains the original user's identity and permissions while being scoped specifically for the downstream service, enabling that service to make authorization decisions based on the end user. The delegation chain is tracked in the `act` (actor) claim, with each level representing a service in the call chain. To learn more, read the [On-Behalf-Of Token Exchange documentation](https://auth0.com/docs/secure/call-apis-on-users-behalf/on-behalf-of-token-exchange).

## Remarks

* Only Custom API clients associated with a resource server can use the OBO token exchange. A Custom API client has the following requirements:
  * Set `app_type` to `resource_server`.
  * Set `resource_server_identifier` to the valid resource server, i.e. `https://my-api.example.com`. Auth0 uses the resource server identifier as the audience parameter in authorization calls.

* The scopes issued to the application may differ from the scopes requested. In this case, a `scope` parameter will be included in the response JSON. Scopes are based on the user's [Role-Based Access Control (RBAC) policies](/docs/manage-users/access-control/rbac).

* OBO token exchanges trigger the [`post-login` Action trigger](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger), where `event.transaction.protocol` is set to `oauth2-token-exchange` and `event.transaction.actor` tracks the complete delegation chain.

* The delegation chain is limited to five nested levels. The OBO token exchange fails if the subject token already has five nested `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.

## Parameters

<ParamField header="DPoP" type="string">
  A DPoP proof for the request. This is optional and only required if your application uses [Demonstrating Proof-of-Possession](/docs/secure/sender-constraining/demonstrating-proof-of-possession-dpop).
</ParamField>

<ParamField header="auth0-forwarded-for" type="string">
  End-user IP as a string value. Set this if you want [Suspicious IP Throttling](/docs/secure/attack-protection/suspicious-ip-throttling) protection to work in server-side scenarios.
</ParamField>

## Request Body

<ParamField body="grant_type" type="string" required>
  Denotes the flow you are using. For On-Behalf-Of Token Exchange, use `urn:ietf:params:oauth:grant-type:token-exchange`.
</ParamField>

<ParamField body="subject_token_type" type="string" required>
  The type of the subject token. For On-Behalf-Of Token Exchange, use `urn:ietf:params:oauth:token-type:access_token`.
</ParamField>

<ParamField body="subject_token" type="string" required>
  The incoming Auth0 access token from the user or upstream service that the middle-tier service is currently holding.
</ParamField>

<ParamField body="requested_token_type" type="string" required>
  Indicates what kind of token you want back. For On-Behalf-Of Token Exchange, use `urn:ietf:params:oauth:token-type:access_token`.
</ParamField>

<ParamField body="client_id" type="string" required>
  Your Custom API client's Client ID. The Custom API client must be associated with a resource server (same identifier). As for other grant types, you can also pass the Client ID in the Authorization header using HTTP Basic Auth.
</ParamField>

<ParamField body="client_secret" type="string" required>
  Your Custom API client's Client Secret. As for other grant types, you can also pass the Client Secret in the Authorization header using `HTTP` Basic Auth. Review alternatives in [Auth0 Authentication API reference docs](https://auth0.com/docs/api/authentication#authentication-methods). Note that you cannot set `token_endpoint_auth_method` to `none` for OBO token exchange.
</ParamField>

<ParamField body="audience" type="string" required>
  The unique identifier of the downstream API you want to access. This is the identifier for the downstream service that receives and validates the new token.
</ParamField>

<ParamField body="scope" type="string">
  (Optional) A space-delimited list of specific permissions requested for the downstream call. If not specified, all scopes granted to the user for the target audience will be included based on RBAC policies.
</ParamField>

## Response

| Status | Description                                                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| 200    | Successful response. Returns an access token for the downstream API with the same user identity preserved.                                            |
| 400    | Bad request. May occur if the delegation chain depth exceeds the maximum allowed limit of 4 nested levels, or if required parameters are missing.     |
| 401    | Unauthorized. The subject token is invalid, expired, or the client credentials are incorrect.                                                         |
| 403    | Forbidden. The client does not have permission to perform the token exchange, or the user does not have the requested scopes for the target audience. |

<ResponseExample>
  ```json 200 Response theme={null}
  {
    "access_token": "eyJ...",
    "expires_in": 86400,
    "token_type": "Bearer",
    "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
  }
  ```

  ```json 400 Response (Delegation chain limit exceeded) theme={null}
  {
    "error": "invalid_request",
    "error_description": "Delegation chain (`act` claim) depth exceeds the maximum allowed limit of 5"
  }
  ```
</ResponseExample>

## Response Fields

<ResponseField name="access_token" type="string">
  The new Auth0 access token scoped for the downstream API. This [JSON Web Token (JWT)](/docs/secure/tokens/json-web-tokens#json-web-tokens) contains the same `sub` (user identity) as the subject token, with the `aud` set to the requested downstream API audience. The `act` claim tracks the delegation chain.
</ResponseField>

<ResponseField name="issued_token_type" type="string">
  Confirms the format of the token returned. This matches the `requested_token_type` from your request.

  Value: `urn:ietf:params:oauth:token-type:access_token`
</ResponseField>

<ResponseField name="token_type" type="string">
  Specifies the authentication scheme to use in the Authorization header. For OBO, this is `Bearer` unless using DPoP, in which case `DPoP` will be used.
</ResponseField>

<ResponseField name="expires_in" type="number">
  The lifetime of the token in seconds.
</ResponseField>

<ResponseField name="scope" type="string">
  (Optional) Only included if the granted scopes differ from the requested scopes. Space-delimited list of scopes that were actually granted.
</ResponseField>
