Custom Token Exchange Beta

Overview

The Custom Token Exchange feature allows clients to exchange their existing tokens for Auth0 tokens by calling the /oauth/token endpoint with specific parameters. You can use Actions to write custom code to decode subject_tokens passed to the /oauth/token endpoint, set the user in the transaction, and issue tokens for that user.

Custom Token Exchange allows customers to address advanced integration use cases. In particular, it is useful for integrating legacy systems or third-party services by converting their tokens into Auth0 tokens, thus enabling seamless authentication and authorization within the Auth0 ecosystem. It is also useful for exchanging Auth0 tokens for other Auth0 tokens, making it possible to get Auth0 tokens for a different audience or for a different client_id.

Setup

Application

To use Custom Token Exchange, you must create a new application. To learn how to set up the new application with the proper settings, read Application Settings. Make sure to enable the Database Connection you intend to use with Custom Token Exchange for this application.

Once you've created the application, note the client_id and client_secret for later use when calling the /oauth/token endpoint.

Actions

To configure Custom Token Exchange in your Auth0 tenant using Actions, follow these steps in the Auth0 Dashboard:

  1. Navigate to Actions > Library.

  2. Click Create Action > Build from Scratch.

3. In the Create Action dialog, enter a name and select the Custom Token Exchange Beta trigger from the drop-down.

4. Click Create.

Next, add the newly created Action to the Custom Token Exchange flow.

  1. Navigate to Actions > Flows.

  2. Click Custom Token Exchange Beta.

  3. Under Add Action, click Custom. Then drag and drop your newly-created Action into the flow under Start. You will see Drop Here appear as you drag it.

4. Click Apply.

Now that you have an Action assigned to the Custom Token Exchange Beta flow, you can use the new Actions API methods available in the Custom Token Exchange Beta to set the user in the transaction.

Actions API

Custom Token Exchange vs Post Login Actions

The new Token Exchange Action available as a part of the Custom Token Exchange Beta is designed for use with the new API methods we have listed below.

For other use cases, such as adding custom claims to Access Tokens, your Post Login Actions will execute after the Token Exchange Action for the user that you set, thus giving you all the same functionality you have today for other login flows. You can identify the Token Exchange flow in your Post Login Action by searching for an “event.transaction.protocol” value equal to “oauth2-token-exchange”.

Use the Actions API

We have provided a number of APIs to use with your Token Exchange Action. You should implement an Action which decodes and validates the subject_token based on the subject_token_type. You can then indicate in your Action which user the subject token corresponds to. Auth0 will then issue access, ID, and refresh tokens for this user.

api.authentication.setUserByProfile

The setUserByProfile command sets user profile attributes in a specified database connection. If the user does not exist, it is created on the fly with the specified attributes. If the user already exists, this command ensures that user profiles are updated with the provided attributes in a structured and controlled manner.

The setUserByProfile command accepts the following parameters:

Parameter Description
connection_name The name of the database connection where the user profile will be set. Limited to 512 characters.
user_profile An object containing the user profile attributes to be set. Limited to 24 properties.

Supported user_profile Properties

You can set the following profile properties for new users. These are the same properties supported by the Management API Update a user endpoint.

  • user_id (required): note this is the external user's id provided by the external identity provider 

  • email (required)

  • app_metadata

  • user_metadata

  • blocked

  • email_verified

  • given_name

  • family_name

  • name

  • nickname

  • picture

  • username

Example Usage

exports.onExecuteCustomTokenExchange = async (event, api) => {
  // validate and decode your token, and extract user details
  const user = validateToken(event.transaction.subject_token);

  api.authentication.setUserByProfile('Username-Password-Authentication', {
   user_id: user.id,
   name: user.name,
   email: user.email,
   phone: user.phone_number,
   user_metdata: {
      department: user.department
   }
 });

Was this helpful?

/

api.authentication.setUserById

The setUserById command sets user attributes based on a specified user ID. This allows you to specify an existing user without updating the profile. This will fail if the user does not yet exist.

The setUserById accepts the following parameter:

Parameter Description
user_id The user ID, such as auth0|55562040asf0aef.

Example Usage

exports.onExecuteCustomTokenExchange = async (event, api) => {
  // validate and decode your token, and extract user details
  const user = validateToken(event.transaction.subject_token);

  api.authentication.setUserById(user.id);

  return;
};

Was this helpful?

/

api.access.deny

The deny command denies the login transaction and returns an error to the caller.

The deny command accepts the following parameters:

Parameter Description
code A string which is returned in the error property in the response. Two “standard” error codes can be used:
  • invalid_request (which returns a 400 status code).
  • server_error (which returns 500 status code).

If you use your own error code, it will return a 400 status code.

reason A string which is returned in the error_description property in the response.

Example Usage

exports.onExecuteCustomTokenExchange = async (event, api) => {
 if (event.client.client_id !== 'HOVc2PDFTH7eahimN4yNCo8mOtjfNjLV') {
   api.access.deny('invalid_request', 'Unable to process token exchange.');
 }

 // ...
};

Was this helpful?

/

Actions Event

In addition to new Actions API methods, you can use data in the Actions Event to learn about the context of the Token Exchange request, such as the subject token, IP address, client, and more.

Client parameters

Property Type Example
client_id string HOVc2PDFTH7eahimN4yNCo8mOtjfNjLV
name string My Web App
metadata object { “foo”: “bar” }

Tenant parameters

Property Type Example
id string dev_1234

Request parameters

Parameter Type Example
geoip object { … geoip object }
hostname string dev_1234.us.auth0.com
ip string 123.42.42.34
userAgent string Mozilla/5.0
language string en
body object { // raw req.body }
method string POST

Transaction parameters

Property Type Example
subject_token_type string urn://cic-migration-token
subject_token string 41598922a1745f7af70
requested_scopes string[] [“openid”, “email”]
requested_token_type string|null urn:ietf:params:oauth:token-type:access_token

Resource server parameters

Parameter Type Example
id string http://acme-api/v1/profile

Deploy the Action

After you create your Token Exchange Action using the API and Event object, you must deploy the changes by clicking the Deploy button at the top of the page in the Auth0 Dashboard.

Call Token Exchange

To use Custom Token Exchange, you need to call the POST /oauth/token endpoint using the client_id and client_secret from the application you configured earlier. Note the new parameters used with Custom Token Exchange:

Parameter Description
grant_type For Custom Token Exchange, use urn:ietf:params:oauth:grant-type:token-exchange.
subject_token_type The type of the subject token. For Custom Token Exchange, this can be any url which is scoped under your own ownership, such as http://acme.com/legacy-token. ⚠️ Token types using Auth0 or IETF spec namespaces are not permitted.
subject_token The subject token.
client_id The client ID of the application you are using for the Token Exchange. As for other grant types, this can be conveyed in the Authorization header using HTTP Basic Auth.
client_secret The client secret of the application you are using for the Token Exchange. As for other grant types, this can be conveyed in the Authorization header using HTTP Basic Auth.
audience The API identifier defined in Auth0.
scope The OAuth2 scope parameter.
Other extension parameters are ignored, although they are included in the event.request.body in the corresponding Action.

Sample Request

curl --location –-request POST 'https://{domain}/oauth/token' \ --data '{ "grant_type":"urn:ietf:params:oauth:grant-type:token-exchange", "subject_token_type":"http://acme.com/migration", "subject_token":"fha9f3fadf0asffdfjsd", "client_id":"{clientId}", "client_secret":"clientSecret}", "audience":"urn:acme.com/v1/profile", "scope":"openid email profile" }'

Was this helpful?

/

Limitations

This is a beta feature, and thus comes with some limitations and incompatibility with other Auth0 features.

The following features are not supported (or will not work properly) with Custom Token Exchange Beta:

  • Organizations

  • MFA

  • Attack Detection

  • Non-DB Connections

  • Flexible Identifiers other than email

  • Impersonation Use Cases

  • Third-Party and Non-OIDC Conformant Clients

Rate Limits

The Custom Token Exchange Beta feature is configured with a fixed one request per second (RPS) rate limit. If you exceed 1 RPS, you will see a too_many_requests error with the following message: Custom Token Exchange Beta rate limit exceeded.

Troubleshooting

In certain cases, you may see a consent_required response when calling the token endpoint (error invalid_request with error description Consent required. In this case, you need to enable the Allow Skipping User Consent option for your API in the Auth0 Dashboard.