Skip to content

React authentication with PKCE

In short

A React single-page app should use the Authorization Code flow with PKCE, because it cannot keep a client secret — anything in the bundle is public.
  • No client secret. Ever. It ships to every visitor.
  • PKCE replaces the secret with a per-request verifier and challenge.
  • Verify the state parameter on the callback route before doing anything else.

The flow: Authorization Code with PKCE

  1. 1

    Generate the verifier and challenge

    Create a random verifier, hash it with SHA-256, base64url-encode it as the challenge, and keep the verifier in session storage until the callback.

    Full detail in the docs
  2. 2

    Redirect to authorize

    Send response_type=code with your client ID, redirect URI, scopes, state, the challenge and code_challenge_method=S256.

  3. 3

    Handle the callback route

    Compare the returned state against the one you stored, then exchange the code and verifier for tokens.

    Full detail in the docs
  4. 4

    Store tokens deliberately

    Decide where tokens live and why. Anything in localStorage is readable by any script that gets onto the page.

Common mistakes

  • Using the implicit flow. It is deprecated and returns tokens in the URL fragment.
  • Leaving the verifier in storage after a failed exchange.
  • Registering a wildcard redirect URI in development and shipping it to production.

SPA with PKCE

Open the guide