SSOGEN / Learn / What Is PKCE? The OAuth PKCE Flow, Step by Step

Learn

What Is PKCE? The OAuth PKCE Flow, Step by Step

PKCE (said "pixy") ties an OAuth authorization code to the app that asked for it, so a code stolen on the way back is useless to the thief.

Updated

OpenID Connect sign-in with PKCEAn application redirects the person to the provider with a code challenge. After sign-in the provider returns a one-time code, and the application exchanges the code and its code verifier for tokens over a direct connection. Application OpenID client Browser OpenID provider 1 redirect with code_challenge 2 authorize request 3 signs the person in 4 redirect with a one-time code 5 code reaches the app 6 code + code_verifier 7 ID token + access token
OpenID Connect sign-in with PKCE

Make a PKCE verifier and challenge here

This tool generates a code verifier and shows its S256 challenge. It also fills a sample authorization request and token request with those values. To check an existing verifier, paste it to see its challenge.

The tool is free, runs in your browser with Web Crypto and uploads nothing.

43 to 128 characters from A-Z, a-z, 0-9, hyphen, period, underscore and tilde. Press Generate for a random one, or paste your own to get its challenge.

Private by design. The verifier and challenge are made and checked in this page with your browser's Web Crypto. Nothing is sent to SSOGEN or anyone else (check your browser's network tab). Use values from a tool like this to learn and test; a real client should generate a fresh verifier for every authorization request.

What PKCE is

What is PKCE?

PKCE is a one-time secret that an OAuth client creates before it starts an authorization request. The client sends a hash of the secret with the request and the secret itself when it redeems the authorization code.

The authorization server issues tokens only if the two match, so an attacker who intercepts the code cannot redeem it. PKCE stands for Proof Key for Code Exchange and is defined in RFC 7636 (read 2026-10-08).

What attack does PKCE stop?

PKCE stops the authorization code interception attack. In the authorization code flow, the server redirects the browser back to the client with a short-lived code in the URL.

RFC 7636 describes the attack in three moves (introduction, read 2026-10-08):

  1. A malicious app on the same device registers for that redirect URI.
  2. It captures the code when the server redirects back.
  3. It redeems the code at the token endpoint before the legitimate client does.

A public client, such as a mobile or single-page app, has no client secret with which to prove its identity, so nothing else stops the exchange.

PKCE adds a secret that never appears in the redirect URL. The code is valid only for a caller that can also present that secret.

What are the code verifier and the code challenge?

The code verifier is a random string the client generates for each authorization request. Under RFC 7636, section 4.1, it is 43 to 128 characters long and may contain only letters, digits, hyphen, period, underscore and tilde.

Section 7.1 recommends at least 256 bits of entropy. The verifier must therefore come from a cryptographically secure random generator, never from a timestamp or a counter (read 2026-10-08).

The code challenge is derived from the verifier (section 4.2). With S256 the derivation is one-way, so the challenge can travel in the clear without revealing the verifier.

S256 or plain: which method should you use?

RFC 7636 defines two methods in section 4.2 (read 2026-10-08):

Method Challenge What an observer of the request learns
S256 Base64url of the SHA-256 hash of the verifier A hash, from which the verifier cannot be recovered
plain The verifier itself The verifier, which defeats the purpose

The RFC requires any client that can use S256 to use it; plain exists only for clients that technically cannot.

If the request omits code_challenge_method, the default is plain (section 4.3), so a client that wants S256 must send it explicitly.

Three sources agree on S256:

  • RFC 7636. Any client that can use S256 must use it.
  • RFC 9700. Clients use challenge methods that do not expose the verifier, and today only S256 qualifies (section 2.1.1, read 2026-10-08).
  • OAuth 2.1 draft. It lists S256 as the method value and explicitly prohibits plain (section 4.1.1 of draft-ietf-oauth-v2-1-16, read 2026-10-09).

How does the PKCE flow work, step by step?

  1. The app makes a verifier and a challenge

    For each sign-in, the app generates a new random verifier. It hashes the verifier with SHA-256 and base64url-encodes the hash to produce the challenge. It keeps the verifier until the token request.
  2. The app sends the authorization request

    The browser goes to the authorization endpoint with the usual parameters (response_type=code, client_id, redirect_uri, scope, state) plus code_challenge and code_challenge_method=S256 (RFC 7636, section 4.3). The server stores the challenge with the code it will issue.
  3. The person signs in and the code comes back

    The server redirects the browser to the redirect URI with the authorization code. This is the step an attacker observes. The challenge was in the request, but the verifier has not left the app.
  4. The app redeems the code with the verifier

    The app calls the token endpoint with grant_type=authorization_code, the code, the redirect_uri, the client_id and code_verifier (section 4.5).
  5. The server checks the match

    The server transforms the verifier with the stored method and compares the result with the stored challenge. If they match, it issues tokens; if not, it returns invalid_grant (section 4.6).

The diagram shows the same five steps between the app and the authorization server.

Authorization code flow with PKCE

  • The appKeeps the verifier
  • Authorization serverStores the challenge
  1. The app to Authorization server1Authorization request with code_challengeIncludes code_challenge_method=S256. The server stores the challenge with the code it will issue.
  2. Authorization server to The app2Redirect back with the authorization codeThe step an attacker would watch. The verifier has not left the app.
  3. The app to Authorization server3Token request with the code and code_verifierSent directly to the token endpoint.
  4. Authorization server4Transform the verifier and compare with the challenge
  5. Authorization server to The app5Tokens if they match, invalid_grant if not
Take-away: the challenge travels in the open, but the verifier only goes to the token endpoint, so a stolen code cannot be redeemed.

Where does each value go?

Value Made by Sent in Sent to
code_verifier The app, once per sign-in The token request only Token endpoint
code_challenge The app, from the verifier The authorization request Authorization endpoint
code_challenge_method The app The authorization request Authorization endpoint
Authorization code The server The redirect back to the app The app, then the token endpoint

Who has to use PKCE?

RFC 9700 (BCP 240, Best Current Practice for OAuth 2.0 Security) requires PKCE for public clients and recommends it for confidential clients. Authorization servers must support it (section 2.1.1, read 2026-10-08).

The RFC also sets two rules for the server:

  • If an authorization request carries a code_challenge, the server must enforce the matching code_verifier at the token endpoint.
  • If a token request carries a code_verifier but the authorization request had no code_challenge, the server must refuse it. This blocks a downgrade attack in which the attacker strips the challenge from the request.

The OAuth 2.1 draft goes further: it requires the code challenge for the authorization code flow, with narrow exceptions in its section 7.5.1.

Revision 16 is dated 3 September 2026, and the working group’s milestone for sending it to the IESG is December 2026. It is still an Internet-Draft, so treat it as direction rather than a finished standard (draft-ietf-oauth-v2-1-16, read 2026-10-09).

For background on the framework, see what is OAuth 2.0.

What are the common PKCE mistakes?

  • Using plain when S256 is available. The verifier is then visible in the authorization request.
  • Omitting code_challenge_method. The default is plain (RFC 7636, section 4.3).
  • Reusing one verifier. Generate a new one for every sign-in.
  • Weak randomness. A guessable verifier protects nothing. Use your language’s cryptographically secure random function.
  • Losing the verifier between the two requests. If a single-page app loses it on a page reload, for example, the code cannot be redeemed. Keep it in memory or session storage for that sign-in only.
  • A server that does not enforce it. If the token endpoint redeems a code without checking the verifier, PKCE has no effect. Send a wrong verifier and confirm that the response is invalid_grant.
  • Treating PKCE as the only protection. RFC 9700 also requires exact string matching on redirect URIs (section 2.1, read 2026-10-08).

How SSOGEN uses PKCE

SSOGEN’s OpenID Connect provider runs the authorization code flow with PKCE on every sign-in.

  • S256 only. The provider accepts only the S256 method.
  • Authorization code flow only. There is no implicit or hybrid flow.
  • Public client by default. A new OpenID Connect application is registered as a public client that proves itself with PKCE alone.
  • Optional secret or key. A web application with a server can add a client secret or a private key.

Setup is in OIDC SSO: register an OpenID Connect application, and the wider picture is in what is OpenID Connect.

Questions people ask

What does PKCE stand for?
Proof Key for Code Exchange. It is pronounced “pixy” and defined in RFC 7636.
Is PKCE a replacement for the client secret?
No. A public client has no secret, so PKCE gives it a proof for each sign-in. RFC 9700 recommends PKCE for confidential clients as well, as an additional layer.
Is the code verifier sent in the browser address?
No. Only the challenge goes in the authorization request. The verifier goes in the token request, which the app sends directly to the token endpoint.
Can I use plain instead of S256?
Only if your client cannot compute SHA-256, which is rare. RFC 7636 requires S256 whenever the client can use it, and RFC 9700 names only S256 as safe.
What is the OAuth authorization code flow?
The app sends the user to the authorization server, which authenticates them and redirects the browser back with a short-lived authorization code. The app then exchanges that code for tokens at the token endpoint. PKCE adds the verifier check to that exchange (RFC 6749, section 4.1; RFC 7636).
Does Microsoft Entra ID support PKCE?
Yes. Microsoft’s documentation recommends PKCE for all application types and requires it for single-page apps that use the authorization code flow. Entra accepts both S256 and plain; SSOGEN accepts only S256 (Microsoft Learn, authorization code flow, read 2026-10-09).
How long should the verifier be?
Between 43 and 128 characters from the allowed set, built from at least 256 bits of random data (RFC 7636, sections 4.1 and 7.1).

Where to go next

Sources, all read 2026-10-09: RFC 7636, RFC 9700, OAuth 2.1 draft.