Authentication & Authorization (OAuth2, JWT)
Authentication answers "who are you?" while authorization answers "what can you do?" These are distinct concerns but tightly coupled in practice. Getting them wrong means either locking out legitimate users or letting attackers in.
Auth Flow: Login → Token → Validated Request
OAuth2 Flows
Authorization Code Flow (Web Apps)
- User clicks "Sign in with Google"
- App redirects to Google's authorization server
- User authenticates and consents
- Google redirects back with an authorization code
- App exchanges code for tokens (server-to-server, secret stays safe)
- App receives access token + refresh token
Why the extra step? The code exchange happens server-side, so the access token never touches the browser.
Client Credentials Flow (Service-to-Service)
No human involved — a service authenticates itself:
- Service sends its
client_id+client_secretto the auth server - Auth server validates and returns an access token
- Service uses token to call other APIs
Used for: background jobs, microservice-to-microservice calls, scheduled tasks.
JWT Structure
A JWT (JSON Web Token) has three base64-encoded parts separated by dots:
eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzA5MjUxMjAwfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p...
| Header | Algorithm + token type: {"alg":"RS256","typ":"JWT"} |
| Payload | Claims: {"sub":"user123","role":"admin","exp":1709251200} |
| Signature | HMAC or RSA signature over header + payload — tamper-proof |
Stateless verification: Any service with the public key can verify the token without calling the auth server.
RBAC vs ABAC
| Aspect | RBAC (Role-Based) | ABAC (Attribute-Based) |
|---|---|---|
| Decision based on | User's assigned role | Multiple attributes (role, time, location, resource) |
| Example | "admins can delete users" | "managers can approve expenses < $10k during business hours" |
| Complexity | Simple, well-understood | Flexible but harder to audit |
| Best for | Most applications | Complex enterprises, fine-grained needs |
Token Refresh & Revocation
Refresh Strategy
- Access tokens: Short-lived (5–15 min) — limits damage if leaked
- Refresh tokens: Longer-lived (days/weeks), stored securely, exchanged for new access tokens
- Rotation: Issue a new refresh token with each use; old one is invalidated
Revocation Strategies
- Token blocklist: Check each request against a revoked-token list (adds state)
- Short expiry: Don't revoke — just wait for it to expire (simplest)
- Token versioning: Bump user's token version; all older tokens become invalid
Real-World Examples
Google's OAuth2: "Sign in with Google"
Google's OAuth2 implementation enables millions of apps to authenticate users without handling passwords. The Authorization Code flow keeps secrets server-side. Scopes like email, profile, calendar.readonly let users grant minimal permissions. Google issues short-lived access tokens (1 hour) with refresh tokens for long sessions — a single identity provider serving the entire ecosystem.
Stripe: API Keys + Scoped Permissions
Stripe uses restricted API keys — each key can be scoped to specific resources (charges: read-only, customers: write). They separate publishable keys (safe for browser) from secret keys (server-only). Keys can be rolled without downtime. This is Client Credentials pattern with fine-grained RBAC on each key.
Interactive: Decode a JWT
JWT Decoder
Paste a JWT or use the example to see its decoded parts: