Token exchange

Learn what OAuth 2.0 token exchange is, how it works, and how you can use it to exchange access tokens from different sources to access tokens provided by Authorization Control Plane.

Token exchange in a nutshell

OAuth 2.0 Token Exchange is an extension to the standard OAuth 2.0 protocol. It enables client applications to request and obtain security tokens (such as access tokens) from an authorization server (in this case, ACP) acting as a Security Token Service (STS).

STS is a service responsible for validating tokens provided to it and issuing new tokens in the response, which enables client applications to obtain appropriate security tokens for resources that are within distributed environments. In other words, a client application may request access to resources with an access token from a third-party authorization server, exchange its token to an access token provided by ACP, and then use this token to authenticate the request.

Token exchange in ACP

At the moment, client applications can only exchange access tokens. Exchanging refresh or ID tokens is not supported.

The verification for third-party tokens is done using an OpenID-Connect-based Identity Provider that is configured for a given workspace (authorization server). Currently, the token exchange grant flow is available for Okta, Auth0, and Generic OIDC Connector. ACP does not support token exchange grant flow for SAML-based IDPs.

ACP’s authorizers are also capable of exchanging third party access tokens to ACP tokens when enforcing access control. To learn more, see the Using third-party access tokens for access control article.

Traditional OAuth flow vs. Token exchange

In the traditional OAuth 2.0 setup of ACP, a client application requests access to protected resources using an access token provided by ACP. This client application is registered within ACP and requests tokens only from ACP.

When token exchange is used, the access token source can be different as long as it comes from a trusted third-party OAuth authorization server. There are, in fact, two client applications and two OAuth authorization servers - ACP and a third-party authorization server. Client application A is registered within the third-party authorization server. Client application B is registered within ACP. Once Client A gets a token from the third-party authorization server, it can send a request to the ACP’s OAuth token endpoint using client credentials from the Client B and passing the original token it got from the third-party authorization server. ACP validates the request and mints a token that is used to authenticate the client to access protected resources. In this setup, Client B impersonates Client A.

Learn more

To learn more about the impersonation concept in OAuth Token Exchange grant type, see the Delegation vs. Impersonation Semantics section of the OAuth 2.0 Token Exchange specification.

When to use

Token exchange grant can be used for a variety of reasons, but there are two main and most common use cases it solves:

  • Migration enablement - it is much easier for you to migrate from a third-party OAuth or OpenID Connect provider to ACP. You can make sure that your migration is going to be successful and the services protected by ACP’s authorizers can consume access tokens provided by your legacy OAuth/OIDC provider.

  • Partnership enablement - if you are a Cloudentity partner that provides OAuth/OIDC authorization server capabilities, you are able to consume tokens coming from your authorization server and enforce authorization at the API request layer. Additionally, you can take a hybrid approach, where simple client applications that do not need highest level of security are registered within your authorization server, but the client applications that do need the highest level of security or need to be, for example, FAPI or Open Banking compliant, are registered within ACP.

Exchanging tokens in depth

sequenceDiagram autonumber participant app as Client Application participant ACP participant IDP as 3rd Party OAuth Server app->>IDP: OAuth authorization IDP->>app: 3rd Party Access Token app->>ACP: request to /token endpoint Note right of app: The request includes the 3rd party access token in the payload ACP->>ACP: Validate the token Note Right of ACP: ACP checks if the token comes from a trusted IDP alt Request valid opt 3rd party token is opaque ACP-->IDP: /userinfo end opt 3rd party token is JWT but with /userinfo marked in IDP's settings ACP-->IDP: /userinfo end ACP->>ACP: Map token claims ACP-->>app: ACP's access token else request invalid ACP-->>app: Invalid token request end
  1. A client application performs OAuth authorization to a third-party OAuth authorization server, also referred to as an Identity Provider.

  2. The server returns a third party access token.

  3. The client application makes a request to ACP’s OAuth token endpoint.

    For the diagram simplification, you can see that this is one client application requesting tokens both to the 3rd party authorization server and to the ACP. In fact, one client application cannot be registered within two different authorization servers to get access tokens. When the application requests a token from the 3rd party provider, it uses client credentials coming from the application registered within the 3rd party authorization server. When it requests token exchange to ACP, it uses client credentials from an application that is registered within ACP.

    For more details about the request and, for example, it’s parameters, see the token request details section.

  4. ACP validates the token.

    Trust validation

    ACP checks if the 3rd party access token comes from an Identity Provider that is configured as trusted in ACP.

    For JWT tokens, the token contains the iss claim so it is easier to validate the token. ACP uses the JSON Web Key Set (JWKS) of the 3rd party authorization server to validate the token signature.

    For opaque tokens, it is not possible to verify the token without calling the /userinfo endpoint of the 3rd party authorization server.

  5. If the 3rd party token is an opaque token, ACP calls the 3rd party provider’s /userinfo endpoint.

    ACP calls every IDP that has the token exchange grant enabled in ACP’s Identities configuration to check if the 3rd party token is still valid.

  6. If your IDP has the /userinfo endpoint marked in the ACP Identities configuration and the 3rd party token is a JSON Web Token, ACP calls the configured /userinfo endpoint.

  7. ACP maps the claims from the incoming 3rd party token to claims that are configured in ACP.

  8. If the validation is successful, ACP returns an access token minted by ACP.

  9. If the validation is not successful, ACP returns Invalid token request in the response body.

Token request details

Below, you can see an example of the request to the OAuth token endpoint using the token exchange grant type.

curl -v -d

When token exchange grant is used, the request to the OAuth token endpoint must contain the grant_type request body parameter with the urn:ietf:params:oauth:grant-type:token-exchange set. Additionally, the request body must contain the following parameters:

  • client_id - client identifier of the client application registered within ACP for the purpose of the token exchange.

  • client_secret - client secret of the client application registered within ACP for the purpose of the token exchange.

  • subject_token - third party authorization server’s access token to be exchanged for the ACP’s access token.


    The subject_token cannot be an ACP’s access token. The token must come from a third party provider.

Additional parameters

For a detailed list of all parameters that are used when requesting tokens, see the OAuth token endpoint reference and OAuth 2.0 Token Exchange specification.

Contrary to the OAuth 2.0 Token Exchange specification, ACP’s implementation for the token exchange grant does not support the resource request body parameter. It’s logic is covered by the scope parameter.

The scope parameter holds a list of space-delimited and case-sensitive strings that allow the client application to specify the desired scope of the requested token. Scopes are unique within different authorization servers.

If there is a client application that requests a custom-scope from the ACME service, you do not need to explicitly provide the aud (audience) parameter in your request. The ACME service is automatically added to your token audience parameter as the custom-scope is unique to the ACME service.

Token exchange and extensions limitations

When the token exchange grant type is used, some of the features that you would get with a standard OAuth authorization for client apps that request tokens from ACP are not available:

  • When using the token exchange grant type, it is not possible to use ACP’s Extensions (post authentication scripts).

  • The amr (authentication method reference) can be set only through a static field in your IDP configuration. It is not possible to modify or map the amr claim using Extensions.