JWT and Session Questions
What is a JWT and what are its three parts?
A JSON Web Token is a compact, signed token: header.payload.signature, each part Base64URL-encoded.
- Header: algorithm and type, e.g.
{"alg":"HS256","typ":"JWT"}. - Payload: claims such as
sub(user),roles,iat,exp,iss. - Signature: HMAC or RSA/EC signature over
header.payload, proving the token was issued by the server and not changed.
Is the JWT payload encrypted? Can you put a password in it?
Example
No. A signed JWT is only encoded, not encrypted. Anyone can decode the payload:
import java.util.Base64;
public class Main {
public static void main(String[] args) {
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
+ ".eyJzdWIiOiJhc2hhQHNob3BlYXNlLmluIiwicm9sZSI6IkFETUlOIn0"
+ ".signature-not-needed-to-read";
String payload = token.split("\\.")[1];
System.out.println(new String(Base64.getUrlDecoder().decode(payload)));
}
}Output
{"sub":"[email protected]","role":"ADMIN"}So never put passwords, card numbers or other secrets in a JWT. Use JWE (encrypted JWT) only if the claims really must be hidden.
Session-based vs token-based (JWT) authentication: compare them.
| Server session (JSESSIONID) | JWT | |
|---|---|---|
| State | stored on the server (memory/Redis) | stateless, carried by the client |
| Scaling | needs sticky sessions or a shared session store | any instance can verify the token |
| Logout / revoke | easy: invalidate the session | hard: token is valid until exp |
| Transport | cookie (needs CSRF protection) | usually Authorization: Bearer header |
| Best for | server-rendered web apps | SPAs, mobile apps, microservices |
How do you implement JWT authentication in Spring Boot 3?
POST /api/auth/loginauthenticates with theAuthenticationManagerand returns a signed token with a shortexp(e.g. 15 minutes).- A
OncePerRequestFilteradded beforeUsernamePasswordAuthenticationFilterreadsAuthorization: Bearer ..., verifies signature and expiry, and puts anAuthenticationinto theSecurityContextHolder. - Session policy is
STATELESS, CSRF is disabled (no cookies), protected endpoints useauthenticated()/hasRole. - Simpler alternative:
.oauth2ResourceServer(o -> o.jwt(...))with aJwtDecoderbean, which does the filter work for you.
How do refresh tokens work?
The access token is short-lived (5–15 min) and sent on every request. The refresh token is long-lived (days), stored securely (HttpOnly cookie or the server database), and sent only to /api/auth/refresh to get a new access token. Use rotation: each refresh issues a new refresh token and invalidates the old one; if an old one is used again, assume theft and revoke the whole token family.
How do you log out a user or revoke a JWT?
- Keep access tokens short-lived so a leaked token expires quickly.
- Delete the refresh token on the server on logout; the client discards the access token.
- For instant revocation: a denylist of token ids (
jti) in Redis untilexp, or atokenVersionper user stored in the DB and in the token (increment it to kill all tokens).
What is session fixation and how does Spring Security prevent it?
An attacker makes the victim log in with a session id the attacker already knows, then uses that session. Spring Security changes the session id on login (sessionFixation().changeSessionId(), the default), so the old id becomes useless. You can also limit concurrent sessions with sessionManagement(s -> s.maximumSessions(1)).