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
Statestored on the server (memory/Redis)stateless, carried by the client
Scalingneeds sticky sessions or a shared session storeany instance can verify the token
Logout / revokeeasy: invalidate the sessionhard: token is valid until exp
Transportcookie (needs CSRF protection)usually Authorization: Bearer header
Best forserver-rendered web appsSPAs, mobile apps, microservices

How do you implement JWT authentication in Spring Boot 3?

  1. POST /api/auth/login authenticates with the AuthenticationManager and returns a signed token with a short exp (e.g. 15 minutes).
  2. A OncePerRequestFilter added before UsernamePasswordAuthenticationFilter reads Authorization: Bearer ..., verifies signature and expiry, and puts an Authentication into the SecurityContextHolder.
  3. Session policy is STATELESS, CSRF is disabled (no cookies), protected endpoints use authenticated() / hasRole.
  4. Simpler alternative: .oauth2ResourceServer(o -> o.jwt(...)) with a JwtDecoder bean, 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 until exp, or a tokenVersion per 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)).