CodePark/ questions / Tokens & auth in SPAs
START PRACTICINGPRACTICE
Frontend question · Frontend security › Tokens & auth in SPAs

Walk through the OAuth Authorization Code flow with PKCE from the SPA's side. What does the browser create, store and send?

PKCE (Proof Key for Code Exchange) proves that the app that started the login is the same app that finishes it.

The steps in the browser:

  • 1. Create secrets. Make a random code_verifier (43 to 128 characters) and a random state. Compute code_challenge = BASE64URL(SHA-256(code_verifier)). Save the verifier and the state in sessionStorage, so they survive the redirect.
  • 2. Redirect to login. Send the user to the authorization server's /authorize URL with response_type=code, client_id, redirect_uri, scope, state, code_challenge and code_challenge_method=S256.
  • 3. Come back. After login, the server redirects to redirect_uri?code=...&state=....
  • 4. Check state. If it doesn't match the saved value, stop. A mismatch means someone else started this login.
  • 5. Swap the code. POST to the /token endpoint with grant_type=authorization_code, the code, redirect_uri, client_id and the code_verifier. There is no client secret, because an SPA can't hide one.
  • 6. Clean up. Delete the verifier and state. Remove code from the address bar with history.replaceState.

What PKCE protects: a stolen authorization code is useless without the verifier, and the verifier never left the browser.

The older implicit flow put the token straight into the URL. It is no longer recommended. Use a well-tested library instead of writing this by hand.

  • The SPA creates a random code_verifier and sends only its SHA-256 hash as the code_challenge.
  • It saves the verifier and state in sessionStorage so they survive the redirect.
  • It checks state when the user comes back, and stops if it doesn't match.
  • It swaps the code plus the verifier for tokens, with no client secret.
  • A stolen code is useless without the verifier.