25:00
Focus
Lesson 6
~15 min125 XP

Introduction

Welcome to your deep dive into securing modern web applications. In this lesson, we will master the architecture of Spring Security and implement stateless authentication using JSON Web Tokens (JWT).

The Spring Security Filter Chain

At its heart, Spring Security is a massive pipeline of Servlet Filters known as the DelegatingFilterProxy. Every incoming HTTP request must pass through this funnel before it ever reaches your business logic (the Controller). Imagine a high-security building where every visitor must pass through multiple checkpoints—ID verification, bag checks, and metal detectors—before entering the lobby.

The core of this process is the FilterChainProxy. When you configure HttpSecurity in your code, you are essentially defining the sequence and the logic of these checkpoints. Common filters include the UsernamePasswordAuthenticationFilter (for standard forms) and the BearerTokenAuthenticationFilter (for JWT).

One common pitfall is misunderstanding the order of these filters. Because Spring Security is built on a chain, if you add a custom filter, you must decide where it sits. If you place your custom JWT filter after the authentication filter, your application won't know the user is authenticated when it hits the standard security checks. Always use .addFilterBefore() or .addFilterAfter() to ensure your security logic executes precisely when needed.

Exercise 1Multiple Choice
What is the primary role of the DelegatingFilterProxy in Spring Security?

AuthenticationManager and AuthenticationProvider

Once a request reaches the security layer, the system needs to verify the identity of the user. This is handled by the AuthenticationManager. Think of this as the "Chief of Security" who delegates verification to specific experts known as AuthenticationProviders.

A provider could be a database lookup, an LDAP server, or an OAuth2 server. When you submit credentials, they are wrapped in an Authentication object. The provider checks these credentials. If valid, it returns an Authenticated object containing the user's GrantedAuthorities (roles or permissions).

In a stateless JWT flow, we bypass the traditional HttpSession by manually populating the SecurityContext after validating the JWT. This tells Spring that the user is who they claim to be for the duration of this single request only.

Implementing the Stateless JWT Filter

In a stateless architecture, the server does not remember the user. Instead, the client sends a Authorization: Bearer <token> header with every call. To implement this, we create a custom filter that extends OncePerRequestFilter.

This filter performs four critical steps:

  1. Extract the Authorization header.
  2. Verify that the header starts with "Bearer ".
  3. Validate the JWT signature using a secret key.
  4. If valid, set the SecurityContext so that your Controllers can access the Principal.

Note: Never store your secret JWT signing key in plain text within your source code. Use Environment Variables or a Secret Management service like HashiCorp Vault to inject the key at runtime.

A major pitfall here is failing to handle expired tokens. Always include logic to catch ExpiredJwtException and return a 401 Unauthorized status. Failure to do so may lead to the application throwing a 500 error, leaking stack traces to the user.

Exercise 2True or False
In a stateless REST API, we must populate the SecurityContextHolder for every request to maintain identity.

Securing API Endpoints

Now that we have a filter, we must configure which endpoints require authentication. We do this via the SecurityFilterChain bean. This is where you map URL patterns to security constraints.

You should follow the principle of Least Privilege. Deny everything by default and explicitly allow only what is necessary, such as /api/auth/login or /api/public/**.

Common mistake: Forgetting to disable CSRF (Cross-Site Request Forgery) protection. Since your app is stateless and uses JWTs provided in the header rather than cookies, CSRF is generally not applicable, but leaving it enabled can block your API requests if you aren't providing the correct tokens.

Exercise 3Fill in the Blank
To ensure no session is created on the server, the sessionCreationPolicy must be set to ___ .

Key Takeaways

  • Spring Security uses a FilterChain of various filters to intercept and secure HTTP requests before they reach your controllers.
  • The AuthenticationManager acts as the central coordinator for verifying identity, delegating tasks to specific AuthenticationProviders.
  • In stateless JWT authentication, the SecurityContextHolder must be manually updated by a custom filter for every individual request.
  • Always implement the principle of Least Privilege by explicitly permitting public paths and enforcing authentication on sensitive ones, remembering to disable CSRF when you aren't using session-based cookies.
Check Your Understanding

The Spring Security architecture relies on a structured sequence of filters to validate incoming web requests before they reach your controller logic. Explain why the specific positioning of a custom JWT authentication filter within the FilterChainProxy is critical to the security of your application, and describe what might go wrong if this filter is placed incorrectly in the processing sequence.

🔒Upgrade to submit written responses and get AI feedback
Go deeper
  • How do I determine the correct filter ordering?🔒
  • Where should I inject my custom JWT validation logic?🔒
  • Are session-based cookies less secure than stateless JWTs?🔒
  • What happens if a filter is placed in the wrong position?🔒
  • How can I debug the Spring Security filter chain effectively?🔒