Skip to content

feat(auth0-api-js): Add support for Token Vault to exchange access tokens - #50

Closed
guabu wants to merge 2 commits into
auth0:mainfrom
guabu:tv-with-at
Closed

feat(auth0-api-js): Add support for Token Vault to exchange access tokens#50
guabu wants to merge 2 commits into
auth0:mainfrom
guabu:tv-with-at

Conversation

@guabu

@guabu guabu commented Sep 3, 2025

Copy link
Copy Markdown
Contributor

Description

Adds a getAccessTokenForConnection method to exchange an access token (urn:ietf:params:oauth:token-type:access_token) for a connection's access token using the urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token grant.

The API client can now optionally be instantiated by providing a client ID and secret to facilitate the exchange.

Testing

  • This change adds test coverage for new/changed/fixed functionality
  1. Authenticate in a web app and obtain the access token for an audience
  2. Pass the access token getAccessTokenForConnection method
  3. The token set returned should contain the access token for the connection

Checklist

  • I have added documentation for new/changed functionality in this PR or in auth0.com/docs
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not the default branch

constructor(options: ApiClientOptions) {
this.#options = options;

if (options.clientId && options.clientSecret) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about Private Key JWT?

@pmalouin pmalouin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple minor comments

clientSecret: '<AUTH0_CLIENT_SECRET>',
});

const tokenSet = await apiClient.getAccessTokenForConnection({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this code snippet somehow describe the shape of the returned object?


## Get an access token for a connection

To get an access token for a connection using the `getAccessTokenForConnection` method, you need to instantiate the `AuthClient` with a `clientId` and `clientSecret`:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend that we give more details about where the clientId and clientSecret come from... They are in fact the client credentials of the application of type resource_server associated with this API.

);
});

test('getAccessTokenForConnection - should return a token set when the exchange is successful', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be helpful to include a test case where the HTTP request returns an error?

The most common error case would be that the Token Vault does not have any AT for the user for the specified connection. The developer would have to handle this error case by triggering an authz flow (eventually to use connected accounts). Because there is specific error handling logic that will come from this error case, this is why I think it could be valuable to include in the covered test cases.

Comment on lines +115 to +116
connection: options.connection,
loginHint: options.loginHint,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a practical reason that we return the input fields in the returned value? When would the caller actually use those over the inputs that it passed to the method?

Also, minor but it would be preferable that loginHint does not even get added if options.loginHint is undefined (returning a field with value undefined seems messy).

Comment on lines +41 to +53
export interface AccessTokenForConnectionOptions {
connection: string;
accessToken: string;
loginHint?: string;
}

export interface ConnectionTokenSet {
accessToken: string;
scope: string | undefined;
expiresAt: number;
connection: string;
loginHint?: string;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to include some jsdoc for all these fields.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that there is no test case for missing ctor option: options.domain. non-blocking but would be good to include coverage for that (probably already broken today if domain is missing and the developer tries to verify a JWT).

@guabu guabu closed this Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants