Setting up authentication in React Native usually leads you straight to expo-auth-session. It’s the standard for a reason—it handles the heavy lifting of browser redirects and session management so you don't have to.
But as anyone who has integrated Okta with PKCE knows, the "standard" flow usually has a few undocumented sharp edges.
While building out a recent auth flow, I hit a wall with the exchangeCodeAsync method. If you’re using PKCE (Proof Key for Code Exchange), the /authorization endpoint generates a code challenge that expects a matching code_verifier when you finally exchange your temporary code for an access token.
Here’s the catch: if you look at the Expo exchangeCodeAsync documentation (https://docs.expo.dev/versions/latest/sdk/auth-session/#authsessionexchangecodeasyncconfig-discovery),
you'll notice that the TokenRequestConfig and AccessTokenRequestConfig types don't actually include a codeVerifier key. If you try to pass it as a top-level property, the method ignores it; if you omit it, Okta (rightfully) rejects the exchange because it can't verify the original challenge.
After some digging, I found a GitHub issue from 2020 (https://github.com/expo/expo/issues/8300#issuecomment-718369087) that confirmed this has been a quiet pain point for years.
The official guides don't explicitly call it out, but the fix is actually quite simple. You have to "sneak" the verifier in using the extraParams object.
To get your tokens successfully, your request should look something like this:
1 const tokenResult = await exchangeCodeAsync(
2 {
3 code: response.params.code,
4 clientId:'my-client-id'
5 redirectUri:'my-app-scheme://redirect'
6 extraParams: {
7 code_verifier: request?.codeVerifier, // The missing link
8 },
9 },
10 discovery
11 );
By mapping the codeVerifier to extraParams (don't forget the snake case), it gets included in the POST body where Okta’s token endpoint expects it. It’s a small, one-line fix, but one of those "lost an afternoon" bugs if you’re relying solely on the official types.
Sources & Further Reading:
- Expo Docs: exchangeCodeAsync API Reference (https://docs.expo.dev/versions/latest/sdk/auth-session/#authsessionexchang ecodeasyncconfig-discovery)
- Expo Guides: Authentication in Expo (https://docs.expo.dev/guides/authentication/)
- GitHub Issue: Expo Auth Session PKCE Discussion (#8300) (https://github.com/expo/expo/issues/8300#issuecomment-718369087)
- Okta API: Token Endpoint - code_verifier (https://developer.okta.com/docs/api/openapi/okta-oauth/oauth/customas/toke ncustomas#customas/tokencustomas/t=request&path=&d=0/code_verifier)









