Skip to content

Conversation

@gyaneshgouraw-okta
Copy link
Contributor

@gyaneshgouraw-okta gyaneshgouraw-okta commented Nov 7, 2025

📝 Summary

This PR adds support for the exchangeToken method from auth0-spa-js to auth0-react, enabling token exchange flows based on RFC 8693 This allows apps to exchange external or legacy tokens for Auth0 tokens directly in React.

🔧 Changes

  • Added exchangeToken to the Auth0ContextInterface with full TypeScript and JSDoc support.
  • Implemented exchangeToken using a useCallback with proper error handling.
  • Updated the auth state after successful exchanges.
  • Updated useAuth0 docs to include the new method.
  • Added examples and best practices to EXAMPLES.md.

🧪 Testing

  • Added 4 new tests for method behavior, error handling, auth state updates, and memoization.
  • Updated Jest mocks for exchangeToken, with all tests passing and full TypeScript coverage.

💥 Impact

  • Enables secure token exchange following RFC 8693.
  • Helps migration from legacy auth systems.
  • Fully documented, type-safe, and consistent with existing SDK patterns.

@yogeshchoudhary147 yogeshchoudhary147 force-pushed the feat/custom-token-exchange branch 2 times, most recently from 56fc5c6 to c34a6bf Compare November 21, 2025 05:03
@yogeshchoudhary147 yogeshchoudhary147 marked this pull request as ready for review November 21, 2025 10:51
@yogeshchoudhary147 yogeshchoudhary147 requested a review from a team as a code owner November 21, 2025 10:51
@gyaneshgouraw-okta gyaneshgouraw-okta force-pushed the feat/custom-token-exchange branch from 7f32394 to 3d98928 Compare November 24, 2025 17:56
throw tokenError(error);
} finally {
dispatch({
type: 'GET_ACCESS_TOKEN_COMPLETE',
Copy link
Contributor

@tusharpandey13 tusharpandey13 Nov 25, 2025

Choose a reason for hiding this comment

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

  1. This block will execute even if the tokenExchange fails. Do we want to send a GET_ACCESS_TOKEN_COMPLETE dispatch in the case of error ?
  2. Do we want to dispatch a TOKEN_EXCHANGE_COMPLETE or a similar event here? Just a suggestion, open to all perspectives on this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Acknowledged. @gyaneshgouraw-okta, looping you in to address this comment regarding the implementation design.

Copy link
Contributor

Choose a reason for hiding this comment

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

@tusharpandey13 , @gyaneshgouraw-okta and I discussed this. We are inclined to stick with GET_ACCESS_TOKEN_COMPLETE for now.

The reducer is currently designed around the outcome (obtaining a token) rather than the source (Silent Auth vs. CTE). Since the impact on the state is identical, adding a new action type would force us to duplicate the reconciliation logic (or alias the case) without changing the actual behavior. We feel it follows DRY principles better to keep a single source of truth for "token received" events.

Copy link
Contributor

Choose a reason for hiding this comment

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

This block will execute even if the tokenExchange fails. Do we want to send a GET_ACCESS_TOKEN_COMPLETE dispatch in the case of error ?

Is this expected behaviour?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, it is. We are following the exact same pattern as getAccessTokenSilently here to ensure the CTE flow behaves consistently with the rest of the SDK, regardless of success or failure.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is to enable backwards compat, this behaviour should be documented (CTE + normal token flows)

Copy link
Contributor

Choose a reason for hiding this comment

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

Just to clarify, do you mean adding an inline code comment explaining why we reuse GET_ACCESS_TOKEN_COMPLETE, or are you asking for an update in the public docs?

Copy link
Contributor

Choose a reason for hiding this comment

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

Addressed in the latest commit. I documented the backward compatibility behavior both in the source code (inline) and in the EXAMPLES.md guide.

EXAMPLES.md Outdated
const tokenResponse = await exchangeToken({
subject_token: externalToken,
subject_token_type: 'urn:your-company:legacy-system-token',
authorizationParams: {
Copy link
Contributor

@nandan-bhat nandan-bhat Nov 25, 2025

Choose a reason for hiding this comment

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

I don't think exchangeToken accepts authorizationParams. options is of type CustomTokenExchangeOptions and it's coming from auth0-spa-js here: https://auth0.github.io/auth0-spa-js/types/CustomTokenExchangeOptions.html

Can you confirm this ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch. You're right, exchangeToken expects those at the root level, not nested. I'll push a fix now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated. Thanks again for spotting that!

nandan-bhat
nandan-bhat previously approved these changes Nov 26, 2025
@yogeshchoudhary147 yogeshchoudhary147 merged commit f6a7780 into main Nov 26, 2025
14 checks passed
@yogeshchoudhary147 yogeshchoudhary147 deleted the feat/custom-token-exchange branch November 26, 2025 07:38
This was referenced Dec 4, 2025
gyaneshgouraw-okta added a commit that referenced this pull request Dec 4, 2025
**Added**
- feat: add custom token exchange support
[\#928](#928)
([gyaneshgouraw-okta](https://github.com/gyaneshgouraw-okta))

---------

Co-authored-by: Frederik Prijck <frederik.prijck@auth0.com>
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.

5 participants