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=S2563
User authenticates and authorizes; server redirects back with
code param4
Exchange code for tokens at token endpoint, sending
code_verifier5
Use
access_token in API calls; use refresh_token to renewAuthorization 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 Type | Use Case | PKCE | Recommended |
|---|---|---|---|
| Authorization Code + PKCE | SPA, mobile, public clients | Required | Yes |
| Authorization Code | Server-side web apps | Optional | Yes (add PKCE) |
| Client Credentials | Machine-to-machine | N/A | Yes |
| Device Code | Smart TV, CLI tools | N/A | Yes |
| Implicit | Legacy SPAs | N/A | No (deprecated) |
| Password | Legacy direct login | N/A | No (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
| Item | Requirement |
|---|---|
| state parameter | Use a random, unguessable value to prevent CSRF |
| PKCE | Always use for public clients (S256 method) |
| redirect_uri | Register and validate exact URIs, no wildcards |
| Token storage | Never store tokens in localStorage; prefer httpOnly cookies |
| Token lifetime | Short access tokens (1h); rotate refresh tokens |
| Scopes | Request minimal required scopes only |