Skip to content
Toolcroft

Developer Tools

OAuth 2.0 PKCE Generator - Code Verifier & Challenge for S256

Generate OAuth 2.0 PKCE code_verifier and code_challenge (S256) pairs for public clients. Build the complete authorization URL with client ID, redirect URI, scope, and state.

Authorization URL Builder

1Generate

Create a random code_verifier (43–128 chars).

2Hash

Compute code_challenge = BASE64URL(SHA-256(verifier)).

3Authorize

Send code_challenge in the authorization request.

4Exchange

Send code_verifier when exchanging the auth code for tokens.

What is OAuth 2.0 PKCE?

PKCE (Proof Key for Code Exchange, pronounced "pixy") is a security extension to the OAuth 2.0 authorization code flow. It prevents authorization code interception attacks that could occur in public clients (single-page apps, mobile apps) that cannot securely store a client secret.

How PKCE works

  1. The client generates a random code verifier (a high-entropy random string, 43–128 characters).
  2. The client computes the code challenge: BASE64URL(SHA256(code_verifier)).
  3. The authorization request includes code_challenge and code_challenge_method=S256.
  4. The auth server stores the challenge. When the client exchanges the code for a token, it sends the original code_verifier.
  5. The auth server re-hashes the verifier and compares it to the stored challenge. They must match.

Why it matters

Even if an attacker intercepts the authorization code, they cannot exchange it for a token because they don't have the code verifier. PKCE is now recommended for all OAuth 2.0 clients, including confidential server-side apps (RFC 9700).

Code verifier requirements

The code verifier must meet specific requirements per RFC 7636:

  • Character set: URL-safe base64 characters only - A–Z, a–z, 0–9, hyphen (-), period (.), underscore (_), tilde (~).
  • Length: minimum 43 characters, maximum 128 characters.
  • Entropy: minimum 256 bits of cryptographic randomness (use crypto.getRandomValues or equivalent - never Math.random()).

These constraints exist to ensure the verifier cannot be guessed or brute-forced, even if the code challenge is exposed.

Integration code example

// Generate PKCE code verifier and challenge (Web Crypto API)
async function generatePKCE() { 
  // Generate 32 random bytes -> 43 base64url chars
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  const codeVerifier = btoa(String.fromCharCode(...array))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');

  // SHA-256 hash of the verifier
  const encoder = new TextEncoder();
  const data = encoder.encode(codeVerifier);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = new Uint8Array(hashBuffer);
  const codeChallenge = btoa(String.fromCharCode(...hashArray))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');

  return { codeVerifier, codeChallenge };
}

Comparison to implicit flow

The OAuth 2.0 implicit flow (now deprecated in RFC 9700) was designed for browser-based apps that could not safely store client secrets. Instead of an authorization code, it returned access tokens directly in the URL fragment (e.g., #access_token=abc123). This exposed tokens in browser history, server logs, and referrer headers.

PKCE eliminates this attack surface by keeping the token exchange server-side (or at minimum, preventing its reuse without the verifier). All new OAuth implementations should use the authorization code flow with PKCE rather than the implicit flow.