PKCE (Proof Key for Code Exchange) closes a class of attacks on public OAuth2 clients — mobile apps, SPAs, CLI tools. In 2026, OAuth2 best practice is: always use authorization code + PKCE, never implicit, and use refresh tokens with rotation.
The problem PKCE solves
Public clients can't keep a client_secret secret. An attacker who intercepts the authorization code (via custom URL scheme on mobile, browser redirect) can exchange it for tokens. PKCE binds the code to a verifier only the legitimate client knows.
The flow
Client generates a random code_verifier, computes code_challenge = SHA256(verifier). Sends challenge with the auth request. Authorization server stores it. On token exchange, client sends verifier; server checks SHA256(verifier) == challenge.
Why not implicit
Implicit flow returned access tokens in URL fragments — exposed to logs, browser history, referer headers. Deprecated by OAuth2.1. If you're still using it, migrate to code+PKCE.
Refresh token rotation
Single-use refresh tokens: every refresh returns a new one, old one invalidated. Detects token theft (server sees an old token presented = breach). The 2026 default for public clients.
Common mistakes
Storing tokens in localStorage (XSS-readable) instead of httpOnly cookies. Skipping state param (CSRF). Long-lived access tokens (use 5-15 min + refresh). Failing to validate the audience claim.