Unlocking Spring Security: Authentication Pipeline & Bean Connections
May 10, 2026/4 min read/729 words
The Authentication Architecture
Spring Security is arguably the most powerful yet misunderstood framework in the Java enterprise ecosystem. Many developers configure it using boilerplate code without understanding the underlying servlet architecture.
At its core, Spring Security is built on a chain of servlet filters. It intercepts incoming HTTP requests, performs authentication and authorization checks, and either permits the request to pass to your Controller or rejects it with an appropriate HTTP error code.
The Pipeline at a Glance
When an API request arrives, it is intercepted by a special servlet filter called the DelegatingFilterProxy. This proxy delegates the work to the FilterChainProxy, which loads the active SecurityFilterChain matching the request URL.
♦ ♦ ♦
Enjoyed this article?
Check out my projects or get in touch if you'd like to discuss backend engineering, system design, or collaboration.
Let's break down the execution steps when securing a REST endpoint with a stateless JSON Web Token (JWT):
Step 1: Request Interception
The request passes through a custom filter (typically extending OncePerRequestFilter).
The filter extracts the Authorization header.
It parses the token and checks if it starts with Bearer .
If a token is found, the filter constructs an unauthenticated UsernamePasswordAuthenticationToken (containing the principal/subject and the raw credentials).
Step 2: Authentication Delegation
The filter passes the unauthenticated token to the AuthenticationManager (usually implemented by ProviderManager).
The AuthenticationManager iterates through a list of configured AuthenticationProviders.
An AuthenticationProvider (like DaoAuthenticationProvider or a custom JwtAuthenticationProvider) loads user details from a database using UserDetailsService.
It verifies the password hashes or token signatures.
Step 3: Storing Context
If authentication is successful, the provider returns a fully populated, authenticated Authentication object (which includes authorities/roles).
The filter takes this authenticated token and stores it in the SecurityContextHolder's SecurityContext.
[!NOTE]
Always use SecurityContextHolder.createEmptyContext() instead of SecurityContextHolder.getContext().setAuthentication() to avoid multi-threaded race conditions in high-concurrency environments.
♦ ♦ ♦
2. Complete Code Implementation
Here is a modern, production-ready Spring Security configuration utilizing a stateless JWT filter.
Custom JWT Authentication Filter
Security Configuration Class
♦ ♦ ♦
3. Advanced Context Propagation in Async Threads
By default, the SecurityContextHolder uses a ThreadLocal strategy. This means the authentication details are only bound to the specific thread handling the request.
If you spawn asynchronous background jobs using Spring's @Async, the security context is lost.
[!TIP]
To propagate security context to child threads, configure the Strategy Name during application startup:
Common Pitfalls to Avoid:
Not disabling CSRF for stateless APIs: If your backend is a stateless REST API (no cookies, only JWT/Headers), CSRF tokens are unnecessary. Disable them to improve latency.
Missing CorsFilter Order: Standard CORS configuration must run before Spring Security filter chain checks, or browser pre-flight OPTIONS requests will be rejected with HTTP 403.
Leaving default Exception Handling: Customize AuthenticationEntryPoint and AccessDeniedHandler to return standardized JSON error bodies instead of raw HTML error pages.