Unlocking Spring Security: Authentication Pipeline & Bean Connections
Introduction
For years, I configured Spring Security by copying snippets from tutorials — a SecurityFilterChain bean here, an AuthenticationManager there — without truly understanding how the pieces connected. So I decided to dig deeper.
This article captures what I learned about the Spring Security authentication pipeline and how each component fits together. If you have been configuring Spring Security blindly like I did, this visual breakdown will be a game changer.
The Authentication Pipeline
Every request that hits a Spring Boot application passes through a chain of filters before reaching your controller. Spring Security plugs into this chain and intercepts requests that require authentication.
Here is the complete flow:
Key Concepts
SecurityFilterChain
The backbone of Spring Security. Every HTTP request passes through a configured chain of filters — authentication, authorization, CSRF protection, CORS, exception handling, and more. Each filter has a single responsibility and can decide to pass the request to the next filter or short-circuit with a response.
1@Bean
2public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
3 http
4 .authorizeHttpRequests(auth -> auth
5 .requestMatchers("/api/public/**").permitAll()
6 .requestMatchers("/api/admin/**").hasRole("ADMIN")
7 .anyRequest().authenticated()
8 )
9 .formLogin(Customizer.withDefaults())
10 .httpBasic(Customizer.withDefaults());
11 return http.build();
12}AuthenticationManager
Acts as the central coordinator. It receives an authentication request (typically a username/password token) and delegates validation to one or more configured AuthenticationProvider instances. If no provider can authenticate the request, an AuthenticationException is thrown.
AuthenticationProvider (DaoAuthenticationProvider)
The most commonly used provider. It:
- Delegates user lookup to
UserDetailsService - Delegates password verification to
PasswordEncoder - Returns a fully populated
Authenticationobject on success
PasswordEncoder (BCrypt)
Passwords should never be stored in plain text. BCrypt is the default and recommended encoder — it applies a salt and multiple hash rounds, making brute-force attacks computationally expensive.
1@Bean
2public PasswordEncoder passwordEncoder() {
3 return new BCryptPasswordEncoder();
4}Session Management
Controls how HTTP sessions are created and maintained after authentication. For stateful applications (traditional server-rendered apps), sessions track the authenticated user across requests. For stateless APIs (REST backends), JWT tokens replace session-based tracking.
1http.sessionManagement(session -> session
2 .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // For REST APIs
3);CSRF Protection
Cross-Site Request Forgery protection is enabled by default in Spring Security. It ensures that requests modifying state (POST, PUT, DELETE) include a token that an attacker cannot forge. For stateless APIs using JWT, CSRF protection is typically disabled since tokens serve as the anti-forgery mechanism.
The Biggest Realization
Before this deep dive, I assembled security configurations like a puzzle without the picture on the box. Now I see the full picture:
- The SecurityFilterChain is the entry point — every request flows through it
- Filters extract credentials and pass them to the AuthenticationManager
- The AuthenticationManager delegates to a provider that knows how to validate
- UserDetailsService + PasswordEncoder form the final authority on "is this user real?"
- On success, the SecurityContextHolder is populated — this is what
@AuthenticationPrincipalandSecurityContextHolder.getContext().getAuthentication()read from
Understanding this flow means you can debug authentication issues confidently, customize any part of the pipeline, and move from "copy-paste security" to "designed security."
[!TIP] This article was originally posted on LinkedIn. If you found it helpful, feel free to connect and share your thoughts.
Enjoyed this article?
Check out my projects or get in touch if you'd like to discuss backend engineering, system design, or collaboration.