Authentication Patterns — OAuth, JWT, Sessions, and What to Use When
Authentication is not authorization#
Authentication: Who are you? (proving identity) Authorization: What can you do? (checking permissions)
Most systems need both. This post is about authentication — proving you are who you claim to be.
Session-based authentication#
The traditional approach. Server creates a session, stores it, and gives the client a cookie.
Flow:
- User sends username + password
- Server validates, creates a session in database/Redis
- Server sends back a session ID as an HTTP cookie
- Client sends cookie with every request
- Server looks up session to identify the user
Pros: Server controls everything. Can revoke sessions instantly. Simple to understand.
Cons: Server must store all sessions (stateful). Doesn't scale across multiple servers without shared session store.
Best for: Traditional web apps, server-rendered pages.
JWT (JSON Web Tokens)#
Stateless tokens. The server signs a token containing user data, client sends it with every request.
Flow:
- User sends credentials
- Server validates, creates a signed JWT with claims (user ID, role, expiry)
- Client stores JWT (usually in memory or httpOnly cookie)
- Client sends JWT in Authorization header
- Server verifies signature — no database lookup needed
Pros: Stateless — any server can verify the token. Scales horizontally. Works for APIs and microservices.
Cons: Can't revoke individual tokens (they're valid until expiry). Token size grows with claims. Need refresh token rotation for long sessions.
Best for: APIs, microservices, mobile apps, SPAs.
OAuth 2.0#
Not an authentication protocol — it's an authorization framework. But it's commonly used for authentication via OpenID Connect (OIDC).
What it actually does: Lets users grant your app access to their data on another service (Google, GitHub) without sharing their password.
Common flows:
- Authorization Code — for web apps (most secure, server-side)
- PKCE — for SPAs and mobile apps (public clients)
- Client Credentials — for server-to-server (no user involved)
"Login with Google" flow:
- User clicks "Sign in with Google"
- Redirect to Google's consent page
- User approves → Google redirects back with an auth code
- Your server exchanges the code for tokens
- You get the user's profile (email, name) from the ID token
Passkeys / WebAuthn#
The future of authentication. No passwords, no phishing.
How it works: Browser creates a public/private key pair. Private key stays on the device (biometric-protected). Server stores the public key.
Authentication: Device signs a challenge with the private key. Server verifies with the public key. No password ever transmitted.
Pros: Phishing-proof. No passwords to steal. Biometric verification (fingerprint, Face ID).
Cons: Still relatively new. Recovery if device is lost requires backup keys or account recovery flow.
The decision framework#
| Scenario | Best choice |
|---|---|
| Server-rendered web app | Sessions (cookies) |
| REST/GraphQL API | JWT |
| Mobile app | JWT + refresh tokens |
| "Sign in with Google/GitHub" | OAuth 2.0 + OIDC |
| Enterprise SSO | SAML or OIDC |
| Passwordless future | Passkeys / WebAuthn |
| Machine-to-machine | API keys or client credentials |
Security essentials#
Regardless of pattern:
- Hash passwords with bcrypt (never SHA-256)
- Rate limit login attempts (prevent brute force)
- Use HTTPS everywhere (never send credentials over HTTP)
- Implement MFA for sensitive accounts
- Rotate refresh tokens on each use
- Set short JWT expiry (15 min) with refresh tokens (7 days)
See authentication in your architecture#
On Codelit, search "authentication" in ⌘K to load a complete auth system — OAuth providers, MFA service, session store, RBAC engine, and API gateway JWT validation.
Design your auth system: open ⌘K on Codelit.io and search "authentication" for the full architecture.
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
Related articles
Batch API Endpoints — Patterns for Bulk Operations, Partial Success, and Idempotency
8 min read
system designCircuit Breaker Implementation — State Machine, Failure Counting, Fallbacks, and Resilience4j
7 min read
testingAPI Contract Testing with Pact — Consumer-Driven Contracts for Microservices
8 min read
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 componentsBuild this architecture
Generate an interactive architecture for Authentication Patterns in seconds.
Try it in Codelit →
Comments