The Problem with localStorage
Many tutorials store JWT tokens in localStorage or sessionStorage. This is a critical security mistake — any JavaScript on your page can read these values, making you vulnerable to XSS attacks.
The httpOnly Cookie Solution
By storing the JWT in an httpOnly cookie, the browser automatically includes it in every request, but JavaScript can never read it. This is the gold standard for web authentication.
Implementing the JWT Provider
@Component
public class JwtTokenProvider {
@Value("${jwt.secret}")
private String jwtSecret;
public String generateToken(Authentication authentication) {
return Jwts.builder()
.subject(authentication.getName())
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000L))
.signWith(getSigningKey())
.compact();
}
private SecretKey getSigningKey() {
byte[] keyBytes = Decoders.BASE64.decode(jwtSecret);
return Keys.hmacShaKeyFor(keyBytes);
}
}
Conclusion
Using httpOnly cookies with JWT is more secure than localStorage and doesn't sacrifice developer experience. Combined with HTTPS in production, this pattern is battle-tested and production-ready.