Excellent questions! Here's a comprehensive approach to JWT security in Spring Boot:
1. Secret Key Management
Never store secrets in application.properties. Use environment variables or a secrets management service like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault:
@Value("${JWT_SECRET}")
private String jwtSecret;
// Better yet, use a proper key:
private Key getSigningKey() {
byte[] keyBytes = Decoders.BASE64.decode(jwtSecret);
return Keys.hmacShaKeyFor(keyBytes);
}
2. Token Expiration
Use short-lived access tokens (15-30 minutes) with refresh tokens:
public String generateAccessToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 900000)) // 15 min
.signWith(getSigningKey(), SignatureAlgorithm.HS512)
.compact();
}
public String generateRefreshToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 604800000)) // 7 days
.signWith(getSigningKey(), SignatureAlgorithm.HS512)
.compact();
}
3. Refresh Token Implementation
Absolutely! Store refresh tokens in a secure database with user association:
@Entity
public class RefreshToken {
@Id
private String token;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private Instant expiryDate;
// Add token family for rotation detection
private String tokenFamily;
}
4. Token Revocation Strategy
Implement a token blacklist with Redis for fast lookups:
@Service
public class TokenBlacklistService {
@Autowired
private RedisTemplate redisTemplate;
public void blacklistToken(String token, long expirationTime) {
String jti = extractJti(token);
long ttl = expirationTime - System.currentTimeMillis();
redisTemplate.opsForValue().set(
"blacklist:" + jti,
"revoked",
ttl,
TimeUnit.MILLISECONDS
);
}
public boolean isTokenBlacklisted(String token) {
String jti = extractJti(token);
return redisTemplate.hasKey("blacklist:" + jti);
}
}
Additional Security Recommendations:
- Always use HTTPS in production
- Implement rate limiting on auth endpoints
- Add a JTI (JWT ID) claim for unique token identification
- Consider implementing token binding to prevent token theft
- Use refresh token rotation for enhanced security
- Implement proper CORS configuration
This approach balances security with usability. The short-lived access tokens minimize exposure if compromised, while refresh tokens allow seamless user experience.