OAuth2 Flow Guide

Authorization Code Flow (with PKCE)

1
Generate code_verifier (random 43-128 char string) and code_challenge = BASE64URL(SHA256(code_verifier))
2
Redirect user to authorization endpoint with response_type=code, code_challenge, code_challenge_method=S256
3
User authenticates and authorizes; server redirects back with code param
4
Exchange code for tokens at token endpoint, sending code_verifier
5
Use access_token in API calls; use refresh_token to renew

Authorization Request

GET https://auth.example.com/authorize? response_type=code &client_id=YOUR_CLIENT_ID &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback &scope=openid%20profile%20email &state=xyzABC123 &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM &code_challenge_method=S256

Token Exchange Request

POST https://auth.example.com/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &code=AUTHORIZATION_CODE &redirect_uri=https://app.example.com/callback &client_id=YOUR_CLIENT_ID &code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk # Response { "access_token": "eyJhbGci...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "id_token": "eyJhbGci..." }

Grant Types Comparison

Grant TypeUse CasePKCERecommended
Authorization Code + PKCESPA, mobile, public clientsRequiredYes
Authorization CodeServer-side web appsOptionalYes (add PKCE)
Client CredentialsMachine-to-machineN/AYes
Device CodeSmart TV, CLI toolsN/AYes
ImplicitLegacy SPAsN/ANo (deprecated)
PasswordLegacy direct loginN/ANo (deprecated)

Token Refresh

POST https://auth.example.com/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA &client_id=YOUR_CLIENT_ID

Security Checklist

ItemRequirement
state parameterUse a random, unguessable value to prevent CSRF
PKCEAlways use for public clients (S256 method)
redirect_uriRegister and validate exact URIs, no wildcards
Token storageNever store tokens in localStorage; prefer httpOnly cookies
Token lifetimeShort access tokens (1h); rotate refresh tokens
ScopesRequest minimal required scopes only