Skip to main content
To use Custom Token Exchange, make a POST request to the /oauth/token endpoint with the following parameters:
Remember that subject_tokens used with Custom Token Exchange can be any token format or type, as long as your Action code can interpret them. Each subject_token_type maps to a Custom Token Exchange Profile and is associated with an Action that will be executed to control that transaction.
ParameterDescription
grant_typeFor Custom Token Exchange, use urn:ietf:params:oauth:grant-type:token-exchange.
subject_token_typeThe type of the subject token. For Custom Token Exchange, this can be any URI scoped under your own ownership, such as http://acme.com/legacy-token or urn:acme:legacy-token.

The following namespaces are reserved and cannot be used:
  • http://auth0.com
  • https://auth0.com
  • http://okta.com
  • https://okta.com
  • urn:ietf
  • urn:auth0
  • urn:okta
subject_tokenThe subject token, which your action should validate and use to identify the user.
client_idThe client ID of the application you are using for the Token Exchange. As for other grant types, you can also pass the client ID in the Authorization header using HTTP Basic Auth.
client_secretThe client secret of the application you are using for the Token Exchange. As for other grant types, you can also pass the client secret in the Authorization header using HTTP Basic Auth.

Other alternatives are also available as explained in Auth0 Authentication API reference docs.

Note Custom Token Exchange can be used by public Applications. Make sure to read Attack Protection in that case.
audienceThe API identifier defined in Auth0. The default tenant audience will be used when not present, as configured in Tenant Settings.
scope(Optional) The OAuth2 scope parameter.
organization(Optional) The organization identifier you want the request to be associated with. Alternatively, you can specify an organization name if Use Organization Names in Authentication API is allowed for your tenant. To learn more about how the request is processed, read about the api.authentication.setOrganization() API method.
Other extension parameters are ignored, although they are included in the event.request.body in the corresponding Action.

Sample request

curl --location 'https://{yourDomain}/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'audience=https://api.acme.com' \
--data-urlencode 'scopes=openid offline_access acme-scope1 acme-scope2' \
--data-urlencode 'subject_token_type=urn:acme:external-idp-migration' \
--data-urlencode 'subject_token=t8e7S2D9trQm73e .... iqBR3GjxDtbDVjpfQU' \
--data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
--data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>'
--data-urlencode 'organization=periscope-acme'