Your application requires stateless authentication for RESTful services. How would you implement JSON Web Token (JWT) authentication using Spring Security? Describe the flow from user login to accessing protected resources.

Stateless JWT authentication replaces server-side sessions with a self-contained, signed token that the client stores and presents on every request, letting Spring Security authenticate and authorize without storing any session state.

Key Points: • Login validates credentials once and issues a JWT containing the user's identity, roles, and expiration. • The token is returned to the client, typically in the response body, and stored client-side (e.g., in memory or secure storage). • Every subsequent request carries the token in the Authorization: Bearer header instead of a session cookie. • A custom filter intercepts each request, validates the token's signature and expiry, and populates the SecurityContext before the request reaches the controller. • Because there's no server-side session, the API scales horizontally without sticky sessions or shared session stores.

Example: A mobile app logs in once, stores the returned JWT, and attaches it to every API call for the rest of the session; if the token expires, the app calls a refresh endpoint instead of forcing the user to log in again.

Code Example:

// 1. Login and issue token
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest req) {
    Authentication auth = authManager.authenticate(
        new UsernamePasswordAuthenticationToken(req.username(), req.password()));
    String token = jwtService.generateToken(auth);
    return ResponseEntity.ok(token);
}

// 2. Filter validates token on protected requests
public class JwtFilter extends OncePerRequestFilter {
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws ServletException, IOException {
        String token = jwtService.extractToken(req);
        if (token != null && jwtService.isValid(token)) {
            SecurityContextHolder.getContext().setAuthentication(jwtService.getAuthentication(token));
        }
        chain.doFilter(req, res);
    }
}

Interview Tip: A concise interview answer is:

"I'd validate credentials at login and issue a signed JWT holding identity and roles, then return it to the client. Every subsequent request carries that token in the Authorization header, and a custom filter validates it and populates the SecurityContext, so the whole flow stays stateless and scales horizontally."