OAuth 2.0 Explained Simply — Flows, Tokens, and When to Use Each
OAuth is not authentication#
This is the #1 misconception. OAuth 2.0 is an authorization protocol — it lets apps access resources on behalf of a user. It doesn't verify who the user is.
OpenID Connect (OIDC) is the authentication layer built on top of OAuth 2.0. When someone says "login with Google," they mean OIDC + OAuth together.
The core concept#
Instead of giving an app your password, OAuth lets you grant limited, revocable access through tokens.
Without OAuth:
App asks for your Gmail password → stores it → reads your emails
With OAuth:
App redirects to Google → you approve "read emails" scope
→ Google gives the app a token → app reads emails with that token
→ You can revoke the token anytime
The four roles#
- Resource Owner — You (the user)
- Client — The app requesting access (e.g., a calendar app)
- Authorization Server — Issues tokens (e.g., Google's auth server)
- Resource Server — Hosts the data (e.g., Google Calendar API)
Authorization Code Flow (the most common)#
This is what "Login with Google" uses:
Step 1: Client redirects user to the authorization server
GET https://accounts.google.com/oauth/authorize
?client_id=abc123
&redirect_uri=https://myapp.com/callback
&response_type=code
&scope=email profile
&state=random_csrf_token
Step 2: User logs in and approves the requested scopes
Step 3: Auth server redirects back with an authorization code
https://myapp.com/callback?code=AUTH_CODE_HERE&state=random_csrf_token
Step 4: Client exchanges the code for tokens (server-to-server)
POST https://oauth2.googleapis.com/token
grant_type=authorization_code
&code=AUTH_CODE_HERE
&client_id=abc123
&client_secret=secret456
&redirect_uri=https://myapp.com/callback
Step 5: Auth server returns access token + refresh token
The code-for-token exchange happens server-side, so the access token is never exposed in the browser URL.
PKCE: For mobile and SPAs#
Single-page apps and mobile apps can't keep a client_secret secret. PKCE (Proof Key for Code Exchange) fixes this:
- Client generates a random
code_verifierand a SHA-256 hash (code_challenge) - Sends
code_challengewith the auth request - Sends
code_verifierwhen exchanging the code for tokens - Auth server verifies the hash matches — proves the same client that started the flow is finishing it
Always use PKCE for public clients. It's now recommended for all OAuth flows.
Token types#
Access Token — Short-lived (15 min to 1 hour). Included in API requests as a Bearer token. If stolen, limited damage due to short expiry.
Refresh Token — Long-lived (days to months). Used to get new access tokens without re-authenticating. Store securely — if stolen, attacker gets persistent access.
ID Token (OIDC) — JWT containing user identity claims (name, email, picture). Only used for authentication, not API access.
Other flows#
| Flow | Use case |
|---|---|
| Authorization Code + PKCE | Web apps, mobile apps, SPAs |
| Client Credentials | Server-to-server (no user involved) |
| Device Code | Smart TVs, CLI tools (no browser) |
| Implicit | Deprecated — use Auth Code + PKCE instead |
| Password Grant | Deprecated — never send passwords to third-party apps |
Common security mistakes#
Not validating the state parameter. This prevents CSRF attacks. Always generate a random state, store it in the session, and verify it on callback.
Storing tokens in localStorage. Vulnerable to XSS. Use httpOnly cookies for refresh tokens, and keep access tokens in memory.
Not rotating refresh tokens. Use refresh token rotation — each time a refresh token is used, issue a new one and invalidate the old one.
Overly broad scopes. Request the minimum scopes needed. read:email not admin:everything.
Not checking token audience. Verify the access token was issued for your API, not someone else's.
Visualize your auth architecture#
See how OAuth flows connect your app, auth server, and resource servers — try Codelit to generate an interactive diagram of your authentication system.
Key takeaways#
- OAuth = authorization, OIDC = authentication
- Authorization Code + PKCE is the standard flow for all clients
- Access tokens are short-lived, refresh tokens are long-lived
- Never store tokens in localStorage — use httpOnly cookies
- Always validate
stateto prevent CSRF - Implicit and Password grants are deprecated — don't use them
Explore the GitHub architecture interactively
Try it →Try these templates
OpenAI API Request Pipeline
7-stage pipeline from API call to token generation, handling millions of requests per minute.
8 componentsDistributed Rate Limiter
API rate limiting with sliding window, token bucket, and per-user quotas.
7 componentsAuthentication & Authorization System
OAuth2/OIDC-based auth with SSO, MFA, session management, and role-based access control.
8 componentsContinue learning
Go deeper on security
As an Amazon Associate I earn from qualifying purchases. Codelit may receive a commission at no extra cost to you.
Real-World Cryptography
David Wong · 2021
Which primitive to pick for TLS, JWTs or end-to-end messaging, and what breaks when you pick wrong.
4.7 (100)#14 in Client-Server Networking SystemsSecurity Engineering
Ross Anderson · 2020
Failure case studies across banking, hardware and protocols, plus the economics of why attacks pay.
4.8 (274)Kindle editionDatabase Internals
Alex Petrov · 2019
Explains B-trees, LSM trees and consensus protocols so you can predict how a datastore will behave.
4.6 (560)#2 in Management Information SystemsRelease It!
Michael T. Nygard · 2018
Post-mortems of real outages, then the stability patterns (circuit breaker, bulkhead) that stop them.
4.6 (501)#4 in Client-Server Networking Systems