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.

Ready Click "Next Step" to begin the Authorization Code flow
App
Client
Web / Mobile App
Browser
User Agent
Browser / WebView
Auth
Authorization Server
IdP (Google, Okta, etc.)
API
Resource Server
Protected API
1 Generate PKCE Pair Client generates random code_verifier and computes code_challenge = SHA256(code_verifier)
2 Redirect to Auth Server Client redirects user to /authorize?response_type=code&code_challenge=...&code_challenge_method=S256&scope=openid profile&redirect_uri=...
3 User Authenticates User enters credentials on the authorization server's login page. This is the only time credentials are used — and they never touch the client.
4 User Grants Consent Auth server shows consent screen: "App X wants to access your profile and email." User clicks "Allow."
5 Authorization Code Returned Auth server redirects back to client with ?code=abc123&state=xyz. The code is single-use and short-lived (~10 min).
6 Token Exchange (Back-Channel) Client sends POST /token with grant_type=authorization_code&code=abc123&code_verifier=.... Auth server verifies SHA256(code_verifier) == code_challenge.
7 Tokens Issued Auth server returns access_token, refresh_token, and (if OIDC) id_token. Access token is typically a JWT with short expiry (15-60 min).
8 Access Protected Resource Client calls API with 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

Recommended

Use when: Web apps (server-side or SPA), mobile apps, any interactive user login.

Client --> Browser Redirect to /authorize with code_challenge
Browser --> Auth Server User logs in, grants consent
Auth Server --> Client Redirect with authorization code
Client --> Auth Server POST /token with code + code_verifier
Auth Server --> Client access_token, refresh_token, id_token
Client --> Resource API call with Bearer token
Security: Tokens never exposed in URL. PKCE prevents code interception. Supports refresh tokens. Back-channel token exchange.
Complexity: Requires server-side component for confidential clients. More round-trips than implicit.

Token Anatomy

Examine the structure and purpose of each token type in an OAuth 2.0 / OIDC response.

Encoded (JWT)

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJzYS0xIn0.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMyIsImF1ZCI6ImFwaS5leGFtcGxlLmNvbSIsImV4cCI6MTcxNzEwMDAwMCwiaWF0IjoxNzE3MDk2NDAwLCJzY29wZSI6InJlYWQ6cHJvZmlsZSByZWFkOmVtYWlsIiwiY2xpZW50X2lkIjoiYXBwXzQ1NiJ9.dGhpc19pc19hX3NhbXBsZV9zaWduYXR1cmU

Decoded Payload

iss"https://auth.example.com"Issuer - who created this token
sub"user_123"Subject - the user this token represents
aud"api.example.com"Audience - which API this token is for
exp1717100000Expiration - token is invalid after this time
iat1717096400Issued At - when the token was created
scope"read:profile read:email"Scopes - what permissions are granted
client_id"app_456"Client - which application requested this token
Access tokens are short-lived (15-60 min). The resource server validates the signature, checks expiration, and verifies the scopes match the requested operation.

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.

SHA-256 + Base64url
Enter a code_verifier above to calculate...

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.

seconds
Expires in: 1 hour
seconds
Expires in: 30 days
Token refreshes per day: 24
Max damage window: 1 hour
User re-login frequency: Every 30 days
Security rating: Good

OAuth 2.0 vs OpenID Connect

OAuth 2.0 handles authorization (access). OIDC adds authentication (identity). Understanding the distinction is critical.

Feature
OAuth 2.0
OpenID Connect
Purpose
Authorization — "What can this app access?"
Authentication + Authorization — "Who is this user?" + "What can they access?"
Key Token
Access Token
ID Token (JWT) + Access Token
Scope
Custom (e.g., read:data)
openid (required) + profile, email, address, phone
User Info
Not standardized
Standardized /userinfo endpoint
Discovery
Not standardized
/.well-known/openid-configuration
Session Mgmt
Not defined
Logout endpoints, session iframe checks
Token Format
No requirement (can be opaque)
ID token MUST be JWT (signed, optionally encrypted)
Spec
RFC 6749, RFC 6750
OpenID Connect Core 1.0 (built on OAuth 2.0)

Security Best Practices

OAuth security is not just about picking the right flow — implementation details matter enormously.

PKCE

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.

Token

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.

URI

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.

State

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.

Scope

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.

Rotate

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.

Aud

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).

HTTPS

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.

HIGH

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).

HIGH

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.

MEDIUM

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.

MEDIUM

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.

MEDIUM

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.

LOW

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.

OAuth 2.0 and OpenID Connect are foundational protocols for modern application security. Master the flows, understand the token lifecycle, and always implement PKCE, state validation, and strict redirect URI matching.