Authentication verifies identity. Session management maintains that identity across requests without re-authenticating every time. Most security breaches target one of these two systems — stolen credentials give initial access, and broken session management lets attackers maintain it.
Authentication Methods Compared
| Method | How It Works | Best For | Stateless? |
|---|
| Session cookies | Server stores session, client gets cookie | Traditional web apps, SSR | No (server state) |
| JWT (access token) | Signed token with claims, client stores | SPAs, mobile apps, APIs | Yes |
| API keys | Long-lived token per client | Service-to-service, developer APIs | Yes |
| OAuth2 + OIDC | Delegated auth via authorization server | SSO, third-party login | Depends on flow |
| mTLS | Client certificate | Service mesh, zero-trust | Yes |
| Passkeys/WebAuthn | Public-key cryptography, biometric | Modern passwordless auth | Yes |
JWT vs. Session Cookies
| Factor | JWT | Session Cookie |
|---|
| Storage | Client (localStorage, memory, cookie) | Server (Redis, database) |
| Scalability | Excellent (no server state) | Requires shared session store |
| Revocation | Hard (must blacklist or use short TTL) | Easy (delete session) |
| Size | Larger (contains claims) | Small (just session ID) |
| Security risk | Token theft, no revocation | Session fixation, CSRF |
| Best for | APIs, microservices, mobile | Traditional web apps |
JWT Token Structure
Header (algorithm + type):
{ "alg": "RS256", "typ": "JWT" }
Payload (claims):
{
"sub": "user_12345",
"email": "user@example.com",
"roles": ["admin"],
"iat": 1709000000,
"exp": 1709003600 // 1 hour
}
Signature:
RSASHA256(base64(header) + "." + base64(payload), private_key)
Token Lifecycle
Login:
Client → POST /auth/login (email, password)
Server → Verify credentials
→ Issue access token (15 min TTL)
→ Issue refresh token (7 day TTL, httpOnly cookie)
→ Return access token
API Request:
Client → GET /api/resource (Authorization: Bearer <access_token>)
Server → Validate signature, check expiry
→ Extract claims, authorize
→ Return resource
Token Refresh:
Client → POST /auth/refresh (refresh token in cookie)
Server → Validate refresh token
→ Issue new access token
→ Rotate refresh token (one-time use)
→ Return new access token
Logout:
Client → POST /auth/logout
Server → Invalidate refresh token
→ Add access token to blacklist (until expiry)
OAuth2 Flows
| Flow | Use Case | Client Type |
|---|
| Authorization Code + PKCE | Web apps, mobile apps, SPAs | Public clients |
| Client Credentials | Service-to-service | Confidential clients |
| Device Code | Smart TVs, CLI tools | Input-limited devices |
| Refresh Token | Maintain session without re-auth | All client types |
Session Storage Options
| Store | Latency | Scalability | Persistence |
|---|
| Redis | Sub-ms | Excellent (cluster) | Optional (AOF) |
| Memcached | Sub-ms | Good | None (volatile) |
| PostgreSQL | Low ms | Good (read replicas) | Full |
| In-memory | Fastest | None (single process) | None |
Security Hardening
| Control | Implementation |
|---|
| Password hashing | bcrypt (cost 12+), argon2id preferred |
| Rate limiting login | 5 attempts per 15 minutes per IP/email |
| Account lockout | Lock after 10 failed attempts, unlock via email |
| MFA | TOTP (authenticator app) or WebAuthn (hardware key) |
| Session fixation prevention | Regenerate session ID on login |
| CSRF protection | SameSite cookies + CSRF token for forms |
| Token storage | Access token in memory, refresh token in httpOnly cookie |
| Secure headers | Strict-Transport-Security, X-Content-Type-Options |
Anti-Patterns
| Anti-Pattern | Risk | Fix |
|---|
| JWT in localStorage | XSS can steal tokens | Store in memory or httpOnly cookie |
| No refresh token rotation | Stolen refresh token gives permanent access | One-time-use refresh tokens |
| Long-lived access tokens | Extended window for stolen token use | 15-30 minute TTL |
| Storing passwords in plaintext | Complete credential exposure on breach | bcrypt or argon2id |
| No rate limiting on login | Brute force attacks | Rate limit per IP and per email |
| Session ID in URL | Session hijacking via logs, referrer headers | Session ID in cookie only |
Checklist
:::note[Source]
This guide is derived from operational intelligence at Garnet Grid Consulting. For security architecture consulting, visit garnetgrid.com.
:::
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting
Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.
View Full Profile →