Intermediate · Secure
Choose Sessions, JWTs, and Refresh Tokens by Threat Model
Compare server-side sessions with self-contained bearer access tokens and design refresh rotation.
Primary source: Spring Security 6.5 Reference Architecture
Lesson 2 of 5
1d streakThe Architectural Question
Token lifetime, storage, and revocation decisions set the blast radius of a breach; defaults chosen casually become the postmortem.
What this guide proves
- Hash passwords with an adaptive one-way function
- Keep access tokens short lived and validate all required claims
- Treat refresh tokens as high-value credentials with replay detection
Stateful Sessions vs Stateless JWTs: Architectural Threat Modeling
Choosing between server-side HTTP sessions and client-side JSON Web Tokens (JWT) is not a matter of style; it is an architectural decision based on threat models, state storage, and revocation requirements.
Architectural Boundary · Do Not Confuse
Stateful HTTP Sessions: Server stores session ID in memory or Redis; client holds cookie (JSESSIONID). A server-side session can be revoked immediately on logout. HttpOnly reduces token theft through JavaScript, but XSS can still act through the browser; cookie flows also need CSRF protection. Requires server-side session clustering.
Stateless JWT Bearer Tokens: Cryptographically signed token held by client. Microservices validate signature offline using public keys without hitting a database. Signature validation alone does not provide revocation before expiration; use short expirations, key rotation, introspection, or an explicit revocation check when the threat model requires it.
Use sessions for monolithic web apps or server-rendered frontends. Use stateless JWTs for distributed microservice resource servers where hitting a shared session database on every request introduces latency bottlenecks.
The Storage Rule for JWTs in Single Page Applications
localStorage or sessionStorage. Any Cross-Site Scripting (XSS) vulnerability in any third-party npm package can steal the token immediately. Store tokens in memory or use HttpOnly; SameSite=Strict cookies.Active Recall Checkpoint
Why is revoking an individual JWT token immediately upon user logout challenging in a pure stateless architecture?
Hint: Does the resource server query a central database when verifying the JWT signature?
Show answer & explanation
Because resource servers validate the cryptographic signature locally without calling an identity provider. Until the token reaches its exp (expiration) timestamp, the signature remains valid regardless of user actions.
JWT Cryptography: HMAC (HS256) vs Asymmetric (RS256/ES256)
A JSON Web Token consists of three base64url-encoded parts separated by periods: Header.Payload.Signature. The signature guarantees that the payload has not been tampered with in transit.
| Algorithm Type | Signing Key | Verification Key | Security Fit |
|---|---|---|---|
| Symmetric (HS256) | Shared Secret (256-bit string) | Same Shared Secret | Internal single-app services. If a resource server is compromised, the attacker can forge valid tokens for any user. |
| Asymmetric (RS256 / ES256) | Private Key (held strictly by Auth Server) | Public Key (published via JWKS endpoint) | Enterprise fit for independently operated resource servers. Resource servers verify tokens with public keys, so compromising a verifier does not reveal the signing private key; stolen valid tokens can still be misused until they expire or are revoked. |
{
"sub": "usr_948194",
"iss": "https://auth.example.com",
"aud": "https://api.example.com",
"roles": ["ROLE_USER", "ROLE_ADMIN"],
"exp": 1725710400,
"nbf": 1725706800,
"iat": 1725706800
}Active Recall Checkpoint
What critical claims must a resource server validate before trusting a JWT?
Hint: Think about issuer, audience, and expiration.
Show answer & explanation
iss (issuer must match trusted authorization server), aud (audience must match this specific API), and exp (current time must be strictly before expiration timestamp).
Refresh Token Rotation & Mitigating Token Theft
To balance security with user convenience, production systems pair short-lived Access Tokens (5 to 15 minutes) with Refresh Token Rotation (RTR).
- 011. Client logs in: Auth server returns Access Token (15 min) and single-use Refresh Token (7 days)
- 022. Access Token expires: Client sends Refresh Token to
/oauth/token - 033. Auth Server validates Refresh Token, invalidates it immediately, and issues a NEW Access Token and NEW Refresh Token
- 044. Token Reuse Detection: If an attacker and legitimate user attempt to use the same Refresh Token twice, the Auth Server detects breach and invalidates all active tokens in that family immediately.
The Reuse Detection Guarantee
Active Recall Checkpoint
What happens when an identity provider detects that a previously exchanged refresh token is presented a second time?
Hint: What does this indicate about possible token interception?
Show answer & explanation
It indicates token theft. The identity provider revokes the entire token family (the refresh token and all associated access tokens), forcing the legitimate user to re-authenticate.
Deliberate Failure Lab: The Stateless Revocation Gap
Consider an employee fired at 2:00 PM. The administrator disables their account in the database. If the employee possesses an access token issued with a 12-hour expiration, they can continue querying protected APIs until 2:00 AM if this resource server only validates the signature and does not perform introspection or a revocation check.
Architectural Defenses Against the Revocation Gap
jti (JWT ID) claims.Active Recall Checkpoint
How does a five-minute access-token lifetime change the revocation window, and what risk remains?
Hint: What is the maximum window of vulnerability after an account is suspended?
Show answer & explanation
The token may remain usable until its expiry in this configured design. A shorter lifetime reduces that window, but it does not revoke an already-issued token immediately; introspection or a revocation check is needed when immediate suspension matters.
Runtime Architecture & Flow
Decision canvas
Evaluate the choice across three constraints
These are comparison criteria, not sequential steps. A strong answer states which constraint dominates in the current system.
Hash passwords with an adaptive one-way function
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Keep access tokens short lived and validate all required claims
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Treat refresh tokens as high-value credentials with replay detection
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Decision prompt: Implement login and rotate a refresh token after every successful use.
Working Implementation
Code Walkthrough
Implement login and rotate a refresh token after every successful use.
package com.example.security;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class JwtTokenRotationLab {
public record TokenPair(String accessToken, String refreshToken, Instant expiresAt) {}
// In-memory token family storage for rotation tracking
private final Map<String, String> activeRefreshTokens = new ConcurrentHashMap<>();
public TokenPair issueInitialTokens(String userId) {
String accessToken = "jwt_access_" + UUID.randomUUID() + "_" + userId;
String refreshToken = "rfr_" + UUID.randomUUID();
activeRefreshTokens.put(refreshToken, userId);
return new TokenPair(accessToken, refreshToken, Instant.now().plus(Duration.ofMinutes(15)));
}
public TokenPair rotateRefreshToken(String presentedRefreshToken) {
String userId = activeRefreshTokens.remove(presentedRefreshToken);
if (userId == null) {
// Replay detected! Invalidate entire user session family
throw new SecurityException("Refresh token reuse detected! Revoking token family.");
}
String newAccessToken = "jwt_access_" + UUID.randomUUID() + "_" + userId;
String newRefreshToken = "rfr_" + UUID.randomUUID();
activeRefreshTokens.put(newRefreshToken, userId);
return new TokenPair(newAccessToken, newRefreshToken, Instant.now().plus(Duration.ofMinutes(15)));
}
}Synthesis & Production Verification
Production Acceptance Criteria
- Store passwords hashed with BCrypt or Argon2 and verify encoder strength
- Expire access tokens in minutes and validate iss, aud, and exp claims
- Rotate refresh tokens per use and reject replayed ones
Key Takeaway
Stateful sessions provide immediate revocation for browser apps; stateless JWTs enable decoupled microservice authorization but require short lifespans and refresh token rotation to mitigate revocation gaps.
Architectural & Technical Review
Core Interview Questions
Q01When should an architecture choose stateful sessions over stateless JWTs?Show answer
Stateful sessions are ideal for monolithic web applications with server-side rendering or high-security banking where immediate server-side revocation on logout is mandatory.
Q02What is the cryptographic advantage of asymmetric (RS256) JWTs over symmetric (HS256)?Show answer
Asymmetric signing allows the authorization server to hold the private signing key while distributing the public key via JWKS. Resource servers verify signatures without the ability to forge new tokens.
Q03How does Refresh Token Rotation (RTR) mitigate stolen refresh token vulnerabilities?Show answer
Each refresh token can only be exchanged once; exchanging it issues a new access/refresh token pair and invalidates the previous token. If an invalidated token is reused, the entire token family is revoked.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Storing JWT access tokens in browser localStorage vulnerable to XSS — Any XSS vulnerability in client scripts can extract localStorage tokens; store tokens in memory or HttpOnly cookies.
- Pitfall: Using long-lived JWT access tokens without refresh rotation or revocation mechanisms — Stateless access tokens cannot be revoked before expiration; keep lifetimes strictly under 10–15 minutes.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources