# How Does Spring Security Authentication Work?

## Introduction

Spring Security adds security to an application during servlet request processing through the FilterChain. It introduces a Proxy Filter called `DelegationFilterProxy`, which delegates the request from the servlet filter chain to a Spring Bean named `FilterChainProxy`. The `FilterChainProxy` manages a list of `SecurityFilterChain`s, each responsible for authenticating and authorizing requests using the necessary methods based on project requirements.

We discussed these components in detail in the previous article of this series, you can take a look at it before continuing with this article if necessary. Here’s the link to it 👉 [**Key Elements of Spring Security Architecture Explained**](https://blog.rajugowda.in/spring-security-behind-the-curtain)

In this article, we will focus on how Spring Security authenticates the client requests, what components are involved in the process, and how these components can be used in the future to tweak the implementation as per our requirements.

## When is the authentication happening?

Each `SecurityFilterChain` has two main filters: the `SecurityContextPersistenceFilter` and the `UsernamePasswordAuthenticationFilter`. These filters play a key role in request authentication and authorization.

* The `SecurityContextPersistenceFilter` ensures that the `SecurityContext` is updated, while the `UsernamePasswordAuthenticationFilter` handles the authentication of login requests.
    
* How do they work exactly? Let's explore them in detail.
    

## The SecurityContextPersistanceFilter

The `SecurityContextPersistenceFilter` is responsible for persisting the `SecurityContext` between requests using the `SecurityContextRepository`. Here is how it works step-by-step.

1. The request enters the `SecurityContextPersistenceFilter`.
    
2. The `SecurityContextPersistenceFilter` uses `SecurityContextRepository` to check if the `SecurityContext` already exists in the `HttpSession`.
    
    * If the `SecurityContext` already exists, the same will be updated into the `SecurityContextHolder`,
        
    * Or else a new `SecurityContext` is created and updated both into the `SecurityContextHolder` and the `HttpSession`.
        
3. <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text"><strong>Note: </strong>If the <code>SecurityContext</code> is already present in the <code>HttpSession</code>, it indicates that the user is logged in. This can be verified by checking the <code>isAuthenticated</code> property of the <code>Authentication</code> object within the <code>SecurityContext</code>.</div>
    </div>
    
4. Once the `SecurityContext` is updated into the `SecurityContextHolder`, the request is then delegated to other filters in the filter chain.
    
5. The `SecurityContextPersistenceFilter` wraps around the rest of the filters in the `SecurityFilterChain`, and at the end of the `SecurityFilterChain` it ensures that if any changes are made to the `SecurityContext` in the `SecurityContextHolder`, the same will be updated into the `HttpSession` as well.
    
6. In summary,
    
    The `SecurityContextPersistenceFilter` loads the `SecurityContext` at the start of a `SecurityFilterChain` and saves any updates back to the `HttpSession` after processing, to maintain the user's authentication state seamlessly.  
    Take a look at the diagrammatic flow of the working model of `SecurityContextPersistenceFilter`.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1742951649984/7416dfeb-2090-4767-9414-7b0d5fdd481a.png align="center")

While the `SecurityContextPersistenceFilter` ensures the persistence of `SecurityContext` across requests, it doesn’t significantly contribute to the actual authentication of the request. Rather, the request authentication is majorly carried out by the `UsernamePasswordAuthenticationFilter`.

## The UsernamePasswordAuthenticationFilter

The `UsernamePasswordAuthenticationFilter` is the main filter responsible for authenticating client requests. This process occurs in several stages and involves many components. Let's break down each stage and the components involved in detail.

### The Behaviour

The `UsernamePasswordAuthenticationFilter` is specially designed to authenticate the requests that are made for the `/login` endpoint and expects the request body with the contentType as `x-www-form-urlencoded`. It is specifically designed for login operations. Here is how it operates:

* The `UsernamePasswordAuthenticationFilter` accepts the request,
    
* Checks if the `SecurityContext` already has an `Authentication`. If it does, it verifies whether the authentication status is true or false.
    
    * If `true` ✅, the request bypasses the `UsernamePasswordAuthenticationFilter` —authentication process.
        
    * If `false` ❌, then the `UsernamePasswordAuthenticationFilter` will proceed with the Authentication using the given `username` and `password`.
        
* In other words, if the client is considered authenticated, the `UsernamePasswordAuthenticationFilter` bypasses further authentication processing.
    

### Let’s Elaborate

Now that we have understood when exactly the Authentication happens, let us understand how the authentication happens.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1742953882889/1e82a8ad-727c-48d4-9897-0337451be83a.png align="center")

After the `UsernamePasswordAuthenticationFilter` intercepts a login request and retrieves the `username` and `password` from the request parameters, it generates a `UsernamePasswordAuthenticationToken` using these credentials.

1. ### Creates UsernamePasswordAuthenticationToken
    

* The filter creates a **UsernamePasswordAuthenticationToken** with the username and password.
    
* This token is unauthenticated at this stage, meaning its `isAuthenticated` property is set to `false`.
    

2. ### Delegate to AuthenticationManager
    

* The UsernamePasswordAuthenticationFilter passes the **UsernamePasswordAuthenticationToken** to the **AuthenticationManager** for authentication.
    
* The AuthenticationManager iterates through available **AuthenticationProviders** to find a suitable provider for processing the token.
    

3. ### Authentication by AuthenticationProvider
    

* If the AuthenticationProvider can process the UsernamePasswordAuthenticationToken, it attempts to authenticate the user.
    
* Usually, the **DaoAuthenticationProvider** or **InMemoryAuthenticationProvider** handles this task.
    
    * **DaoAuthenticationProvider:** Loads user details from a UserDetailsService, often querying a database via the UserRepository.
        
    * **InMemoryAuthenticationProvider:** Matches the provided credentials against a predefined in-memory user list.
        

4. ### Password Verification
    

* The AuthenticationProvider verifies the password using a **PasswordEncoder**.
    
* If the password matches, the provider creates a new authenticated **UsernamePasswordAuthenticationToken** with the authenticated user's details and sets its `isAuthenticated` property to `true`.
    

5. ### Return Authenticated Token
    

* The authenticated **UsernamePasswordAuthenticationToken** is returned to the AuthenticationManager.
    
* The AuthenticationManager then sends the authenticated token back to the **UsernamePasswordAuthenticationFilter**.
    

6. ### Store Authentication in SecurityContext
    

* The **UsernamePasswordAuthenticationFilter** receives the authenticated token and updates the **SecurityContextHolder** with this new **Authentication** object.
    
* This ensures that subsequent requests within the same session have access to the authenticated user.
    

7. ### Save the SecurityContext to HttpSession
    

* If necessary, any changes to the SecurityContext are persisted back to the HttpSession by the **SecurityContextPersistenceFilter** at the end of the request.
    

This process ensures that user authentication is seamlessly integrated into the SecurityContext, allowing further requests to be authenticated without requiring re-authentication.

### The Overall Flow

**Note:** The flow diagram skips the representation of `SecurityContextPersistenceFilter` for simplicity.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1742955914136/f581d9ef-902d-4bdb-a4c7-0f30f92e11ae.png align="center")

### Conclusion

In this article, we explored the detailed authentication process in Spring Security, focusing on the role of `SecurityContextPersistenceFilter` and `UsernamePasswordAuthenticationFilter` in handling client requests.

The `SecurityContextPersistenceFilter` ensures that the `SecurityContext` is correctly loaded and persisted between requests, maintaining the user's authentication state. On the other hand, the `UsernamePasswordAuthenticationFilter` is responsible for authenticating login requests by generating a `UsernamePasswordAuthenticationToken`, delegating it to the `AuthenticationManager`, and updating the `SecurityContextHolder` with the authenticated token.

Understanding how these filters work together not only helps in grasping the core concepts of Spring Security but also provides the foundation for customizing security behavior in your applications. This knowledge enables developers to effectively tweak and enhance the authentication mechanism based on their project’s requirements. 🚀  
Your thoughts and questions are always welcome! **Please do like and share! ☺**
