OAuth 2.0 & OpenID Connect
Authorization Flows, Token Anatomy, PKCE, and Security Best Practices
OAuth 2.0 is the industry-standard authorization framework that enables third-party applications to obtain limited access to a user's resources without exposing their credentials. Instead of sharing passwords, OAuth introduces access tokens — short-lived, scoped credentials that grant specific permissions. OpenID Connect (OIDC) is an identity layer built on top of OAuth 2.0 that adds authentication — it introduces the ID token (a signed JWT) that tells the client who the user is, while OAuth alone only tells the client what the user has authorized. Together, they power login flows for virtually every modern application: "Sign in with Google," GitHub OAuth apps, enterprise SSO via Okta/Auth0, and API authorization for mobile and single-page applications. The critical security improvement in modern implementations is PKCE (Proof Key for Code Exchange), which prevents authorization code interception attacks — now recommended for all clients, not just public ones.
Authorization Code Flow with PKCE
The most secure and recommended flow for web and mobile apps. Click "Next Step" to walk through each stage of the protocol exchange between the four participants.
code_verifier and computes code_challenge = SHA256(code_verifier) /authorize?response_type=code&code_challenge=...&code_challenge_method=S256&scope=openid profile&redirect_uri=... ?code=abc123&state=xyz. The code is single-use and short-lived (~10 min). POST /token with grant_type=authorization_code&code=abc123&code_verifier=.... Auth server verifies SHA256(code_verifier) == code_challenge. access_token, refresh_token, and (if OIDC) id_token. Access token is typically a JWT with short expiry (15-60 min). Authorization: Bearer <access_token>. Resource server validates the token (signature, expiry, scopes) and returns data. OAuth 2.0 Grant Types
OAuth defines multiple flows for different client types. Select a flow to see its sequence diagram and when to use it.
Authorization Code + PKCE
RecommendedUse when: Web apps (server-side or SPA), mobile apps, any interactive user login.
Token Anatomy
Examine the structure and purpose of each token type in an OAuth 2.0 / OIDC response.
Encoded (JWT)
Decoded Payload
PKCE Calculator
PKCE (Proof Key for Code Exchange, pronounced "pixy") prevents authorization code interception attacks. Enter a code_verifier to see how the code_challenge is derived using SHA-256 and base64url encoding.
Step 1: Generate Verifier
Create a cryptographically random string, 43-128 characters, using unreserved characters: [A-Za-z0-9-._~]
Step 2: Compute Challenge
code_challenge = BASE64URL(SHA256(code_verifier))
Step 3: Send Challenge
Include code_challenge and code_challenge_method=S256 in the /authorize request. Keep the verifier secret.
Step 4: Prove Possession
Send code_verifier in the /token request. Auth server verifies SHA256(verifier) == challenge. An interceptor who only has the code cannot forge this.
Token Lifetime Calculator
Configure token lifetimes to understand the security vs. usability tradeoff.
OAuth 2.0 vs OpenID Connect
OAuth 2.0 handles authorization (access). OIDC adds authentication (identity). Understanding the distinction is critical.
read:data)openid (required) + profile, email, address, phone/userinfo endpoint/.well-known/openid-configurationSecurity Best Practices
OAuth security is not just about picking the right flow — implementation details matter enormously.
Always Use PKCE
PKCE is mandatory for public clients (SPAs, mobile) and strongly recommended for confidential clients too. It prevents authorization code interception even if an attacker can observe the redirect. The OAuth 2.1 draft makes PKCE required for all clients.
Secure Token Storage
Server-side apps: Store tokens in encrypted server-side sessions. SPAs: Use in-memory storage (not localStorage). Mobile: Use OS keychain (iOS Keychain, Android Keystore). Never store tokens in localStorage or sessionStorage where XSS can steal them.
Strict Redirect URI Validation
Register exact redirect URIs — no wildcards. The auth server must perform exact string matching. Open redirectors are the #1 OAuth vulnerability, allowing attackers to steal authorization codes by redirecting to their server.
Use the State Parameter
Always include a cryptographically random state parameter in the /authorize request and validate it on return. This prevents CSRF attacks where an attacker initiates an OAuth flow and tricks a victim into completing it, linking the attacker's account.
Minimize Scopes
Request only the scopes your application actually needs. Over-requesting scopes increases the blast radius of token compromise. Use incremental authorization: request additional scopes only when the user triggers a feature that needs them.
Refresh Token Rotation
Issue a new refresh token with each use and invalidate the old one. If a stolen refresh token is used, the legitimate user's next refresh will fail (token reuse detection), alerting the system to revoke all tokens for that grant.
Validate Token Audience
Resource servers must verify that the aud claim in the access token matches their own identifier. Without this check, a token meant for API-A could be replayed against API-B (the "confused deputy" problem).
TLS Everywhere
All OAuth endpoints MUST use HTTPS. Authorization codes, tokens, and client secrets are transmitted in HTTP requests — without TLS, they are exposed to network eavesdroppers. This is not optional — it is a spec requirement.
Common OAuth Vulnerabilities
Understanding attack vectors helps you build more secure implementations.
Authorization Code Interception
Attack: Malicious app on the same device registers for the redirect URI scheme and intercepts the authorization code before the legitimate app.
Mitigation: PKCE. Even with the code, the attacker cannot exchange it without the code_verifier. Also use claimed HTTPS redirect URIs (Universal Links / App Links).
Open Redirect / Redirect URI Manipulation
Attack: If the auth server allows wildcard or substring matching on redirect URIs, an attacker crafts a URL like redirect_uri=https://legit.com.evil.com/callback to steal the authorization code.
Mitigation: Exact string matching for redirect URIs. No wildcards, no subdomain patterns, no path prefixes.
CSRF via Missing State
Attack: Attacker starts an OAuth flow with their own account, gets the authorization code, and tricks the victim into completing the flow — linking the attacker's third-party account to the victim's session.
Mitigation: Cryptographically random state parameter bound to the user's session. Validate before processing the callback.
Token Leakage via Referrer Headers
Attack: In the implicit flow, the access token is in the URL fragment. If the page includes third-party resources (analytics, ads), the referrer header may leak the token.
Mitigation: Do not use the implicit flow. Use Authorization Code + PKCE. Set Referrer-Policy: no-referrer headers.
Insufficient Scope Validation
Attack: API accepts any valid access token without checking scopes. A token with read:profile scope is used to call DELETE /account.
Mitigation: Every API endpoint must validate that the token's scopes authorize the specific operation. Use fine-grained scopes.
Token Replay Across Services
Attack: An access token intended for Service A is sent to Service B. If B doesn't check the aud claim, it accepts a token not intended for it.
Mitigation: Audience restriction — every resource server validates the aud claim matches its own identifier.