Expiring a JWT Token Before Its Natural Expiry
JSON Web Tokens (JWTs) are widely used for stateless authentication. By default, a JWT is valid until its expiration time (exp
claim). However, there are scenarios where you might want to invalidate a token before its natural expiry, such as:
- A user logs out.
- A user changes their password.
- A security breach or session compromise.
In this blog post, we’ll explore how to expire a JWT before its natural expiration and best practices to handle token invalidation.
Why JWT Invalidation Is Challenging
JWTs are stateless, meaning they do not rely on a server-side session. Once issued, they remain valid until their exp
time unless you introduce a mechanism to track or revoke them. This statelessness makes JWT efficient but complicates early expiration.
Techniques to Invalidate JWTs Early
1. Use a Blacklist
Store invalidated tokens in a blacklist and check against it during token validation. While effective for early token invalidation, maintaining a blacklist in memory can lead to scalability challenges in large-scale applications. For instance, a high user base may result in significant memory usage and slower lookups. Using a distributed in-memory data store like Redis can help mitigate these issues by enabling efficient and scalable token management.
Implementation:
@Service
public class JwtBlacklistService {
private final Set<String> blacklist = new ConcurrentHashMap.newKeySet();
public void blacklistToken(String token) {
blacklist.add(token);
}
public boolean isBlacklisted(String token) {
return blacklist.contains(token);
}
}
Validation:
Integrate the blacklist check in your authentication process:
public boolean validateToken(String token) {
if (blacklistService.isBlacklisted(token)) {
return false; // Token is invalidated
}
// Perform other validation checks (signature, expiry, etc.)
return true;
}
2. Use a Short Token Lifespan with Refresh Tokens
Limit the lifespan of your access tokens (e.g., 15 minutes) and issue long-lived refresh tokens for re-authentication. If an access token is compromised, it will expire soon.
Implementation:
- Access token lifespan: 15 minutes
- Refresh token lifespan: 7 days
On token refresh, validate the refresh token and issue a new access token.
3. Store a Revocation Flag in a Centralized Store
Maintain a flag in your database to track token validity.
Example:
- Add a
jwtRevokedAt
field to your user table. - During token validation, ensure the token was issued before this timestamp.
Validation Code:
public boolean validateToken(String token, User user) {
Date issuedAt = getIssuedAtFromToken(token); // Extract 'iat' claim
return issuedAt.before(user.getJwtRevokedAt());
}
4. Token Versioning
Include a version
claim in the JWT payload and store the current version in the database.
Example:
- JWT Payload:
{
"sub": "user123",
"version": 1,
"exp": 1700000000
}
- Database:
User ID | Current Version |
---|---|
user123 | 2 |
- Validation Code:
public boolean validateToken(String token, User user) {
int tokenVersion = getVersionFromToken(token); // Extract 'version'
return tokenVersion == user.getCurrentVersion();
}
Best Practices for Early Token Expiry
- Use HTTPS: Always secure token transmission to prevent interception.
- Implement Rotation: Use refresh tokens and rotate them regularly.
- Minimal Scope: Issue tokens with the least required privileges.
- Log Out Detection: Monitor login/logout activities and blacklist tokens accordingly.
- Optimize Blacklists: Use a Redis cache for performance when managing blacklists.
Common Mistakes
- Relying Solely on JWT Expiry: Neglecting early invalidation mechanisms.
- Not Encrypting Sensitive Data: Storing confidential information in the payload without encryption.
- Ignoring Logout Needs: Users expect their tokens to be invalidated upon logout.
- Unlimited Refresh Tokens: Allowing indefinite refresh token usage without rotation.
Interview Explanation
Question: How can you invalidate a JWT before its expiry?
Answer:
"JWT invalidation can be achieved through blacklisting, maintaining a revocation timestamp, or token versioning. For example, when a user logs out, their token can be added to a blacklist checked during token validation. Alternatively, storing a jwtRevokedAt
timestamp ensures tokens issued before the timestamp are invalid. Combining these methods with short-lived access tokens and refresh tokens balances security and user experience."
Further Topics in System Design
- OAuth 2.0 and OpenID Connect
- Token Revocation Standards (RFC 7009)
- Stateless vs Stateful Authentication
- Designing Secure APIs with JWT
Mastering token management and expiration strategies is critical for designing secure and user-friendly systems.