Error

OAuth PKCE Error — Fix

OAuth Error Response
{"error": "invalid_grant", "error_description": "PKCE verification failed: code_verifier does not match code_challenge"}

The code_verifier you sent in the token exchange does not match the code_challenge you sent in the authorization request. They must be cryptographically linked — the challenge is the SHA-256 hash of the verifier.

Common causes

Correct PKCE implementation

// Generate verifier and store BEFORE redirecting
const verifier = generateVerifier();
sessionStorage.setItem('pkce_verifier', verifier); // store here

const challenge = await sha256Base64url(verifier);
// redirect to auth with code_challenge=challenge

// On callback — retrieve the STORED verifier
const verifier = sessionStorage.getItem('pkce_verifier'); // NOT regenerated
await exchangeCode(code, verifier);
function generateVerifier() {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return btoa(String.fromCharCode(...array))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

async function sha256Base64url(str) {
  const data = new TextEncoder().encode(str);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
Debug your OAuth PKCE error → OAuthFixer