Spring security
Table of contents
- SecurityFilterChain
- Authentication Filter
- UsernamePasswordAuthenticationFilter
- UsernamePasswordAuthenticationToken
- AuthenticationManager Interface
- AuthenticationProvider Interface
- SecurityContext
- Summarization of Flow:
- 1. Incoming Request (Authentication Filter Triggered):
- 2. AuthenticationFilter (e.g., UsernamePasswordAuthenticationFilter):
- 3. AuthenticationManager:
- 4. AuthenticationProvider (e.g., DaoAuthenticationProvider):
- 5. Return Authenticated Authentication Object:
- 6. AuthenticationFilter Sets SecurityContext:
- 7. Request Continues:
- Summary of Components Involved:
- What is SecurityFilterChain
- In memory authentication
- Roles and PreAuthrorize in Spring security
Note: Whenever the request comes it goes through SecurityFilterChain in spring security
SecurityFilterChain
The
SecurityFilterChain
is a sequence of filters that are applied to incoming HTTP requests in a Spring Security configuration.These filters are arranged in a chain to ensure that different security tasks are handled in the right order for each request.
The filters perform various actions such as checking for authentication, verifying permissions, and modifying the request or response. We will see more about this below.
Authentication Filter
In Spring Security, the Authentication Filter is a filter responsible for handling the authentication process. It is part of the security filter chain, and its primary role is to authenticate users based on the information provided in the request (e.g., username and password, token, or OAuth credentials).
Authentication Filter in Spring Security is responsible for creating an
Authentication
object. Here's a breakdown of how that works:
Authentication Object Creation Process:
1). Extracting Credentials:
When a request is made (for example, a login request), the
AuthenticationFilter
(e.g.,UsernamePasswordAuthenticationFilter
) extracts the necessary credentials from the request, such as:Username
Password
In the case of token-based authentication (like JWT), the filter would extract the token from the request (typically from the
Authorization
header).
2). Creating the Authentication Object:
After extracting the credentials, the filter creates an
Authentication
object that holds the credentials and any additional data. For example:For username/password authentication, the filter would create a
UsernamePasswordAuthenticationToken
object:Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
For token-based authentication, it could create a
BearerTokenAuthenticationToken
object (or a custom authentication token) that holds the token extracted from the request.
3). Delegating to the AuthenticationManager:
- Once the
Authentication
object is created (but not yet authenticated), the filter passes it to theAuthenticationManager
for authentication.
UsernamePasswordAuthenticationFilter
The
AuthenticationFilter
is a generic, abstract class in Spring Security responsible for handling the authentication process for various types of authentication schemes. It is part of the security filter chain, and its purpose is to intercept requests and initiate the authentication process based on the credentials provided in those requests.While
AuthenticationFilter
is abstract and doesn't perform authentication itself, it is the base class for more specific authentication filters, such asUsernamePasswordAuthenticationFilter
(for username/password authentication),BearerTokenAuthenticationFilter
(for JWT or token-based authentication), and others.The
UsernamePasswordAuthenticationFilter
is a concrete subclass ofAuthenticationFilter
that handles form-based authentication with a username and password. This is the most commonly used filter for handling login forms in a web application.Authentication Process:
It extracts the username and password from the request (usually
HttpServletRequest
).Creates an
UsernamePasswordAuthenticationToken
object with these credentials.Passes this token to the
AuthenticationManager
for authentication.
UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken
is a specific implementation of theAuthentication
interface in Spring Security.It is used primarily in username and password authentication scenarios (such as login forms). It represents the credentials (username and password) provided by the user in a login request, as well as the authenticated user's authorities (roles/permissions) once authentication is successful.
Key Characteristics of UsernamePasswordAuthenticationToken
:
Implements
Authentication
Interface:The
UsernamePasswordAuthenticationToken
implements theAuthentication
interface, which is a core interface in Spring Security for representing an authentication request and response.The
Authentication
interface has methods to check if the user is authenticated, get the user's principal (identity), get the user's granted authorities (roles), and more.
Holds Principal and Credentials:
Principal: The principal is typically the username of the user (or any other identity).
Credentials: The credentials usually hold the password or other authentication token used to verify the user's identity.
Used During Authentication:
Before authentication: It is created by the authentication filter (e.g.,
UsernamePasswordAuthenticationFilter
) when the user submits their username and password. At this stage, the credentials (username and password) are not yet verified.After authentication: If the
AuthenticationManager
successfully authenticates the user, theUsernamePasswordAuthenticationToken
is populated with the authenticated user’s details (principal, authorities, etc.) and stored in theSecurityContextHolder
.
Example Usage:
When a user submits a login form, the UsernamePasswordAuthenticationFilter
creates an instance of UsernamePasswordAuthenticationToken
:
Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
Important Note :
- That means
AuthenticationFilter
creates authentication object but in behind there isUsernamePasswordAuthenticationFilter
who extracts username and password from request and it creates instance ofUsernamePasswordAuthenticationToken
which is implementation of Authentication interface eventually we will get Authentication object and it is further passed to AuthenticationManger.
AuthenticationManager Interface
The
AuthenticationManager
is a core interface in Spring Security that is responsible for handling the authentication process. It takes anAuthentication
object from AuthenticationFilter (containing credentials provided by the user) and validates it. It Actually send’s authentication object toAuthenticationProvider
and it validate’s it.Without an
AuthenticationManager
, Spring Security wouldn't have a clear mechanism to coordinate multipleAuthenticationProvider
s and manage the authentication process for different types of authentication tokens.
Key Points about AuthenticationManager
:
Purpose:
The
AuthenticationManager
acts as a central point for managing authentication.It delegates the actual authentication to one or more
AuthenticationProvider
implementations.
How it Works:
It takes an
Authentication
object (e.g.,UsernamePasswordAuthenticationToken
) as input.Validates the credentials using configured
AuthenticationProvider
instances.If authentication is successful:
- Returns a new, authenticated
Authentication
object with principal, authorities, andauthenticated = true
.
- Returns a new, authenticated
If authentication fails:
- Throws an
AuthenticationException
(e.g.,BadCredentialsException
).
- Throws an
Implementation:
The most common implementation of
AuthenticationManager
isProviderManager
.ProviderManager
delegates authentication to a list ofAuthenticationProvider
instances.
ProviderManager Class
- The most commonly used implementation of AuthenticationManager is
ProviderManager
. This class is responsible for managing a chain ofAuthenticationProvider
instances and coordinating the authentication process by delegating the authentication request to the appropriateAuthenticationProvider
.
Key Features of ProviderManager
It delegates authentication to each
AuthenticationProvider
until one successfully authenticates the request or all providers fail.If the authentication is successful, it returns an authenticated
Authentication
object.If no provider can authenticate the request or if there’s an error in the process, it throws an
AuthenticationException
.
Default Configuration in Spring Security
- When you configure Spring Security (e.g., in a
WebSecurityConfigurerAdapter
), Spring Boot automatically provides aProviderManager
as the defaultAuthenticationManager
. You typically don’t need to explicitly define theAuthenticationManager
unless you want to customize its behavior.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authenticationManager(authenticationManager()) // Uses the default ProviderManager
.formLogin()
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager(); // This is where ProviderManager is configured by default
}
}
AuthenticationProvider Interface
- The
AuthenticationProvider
interface in Spring Security is responsible for performing the actual authentication logic. It validates anAuthentication
object, such as aUsernamePasswordAuthenticationToken
, against a specific source, like a database or an external system. It works as a plugin to theAuthenticationManager
, allowing different types of authentication mechanisms to coexist.
Key Points about AuthenticationProvider
Purpose:
- The
AuthenticationProvider
performs the validation of credentials (e.g., username and password) and provides an authenticatedAuthentication
object if successful.
- The
How it Works:
The
AuthenticationManager
delegates authentication requests to one or moreAuthenticationProvider
s in its list.Each
AuthenticationProvider
checks whether it can handle the type ofAuthentication
object passed to it.If it supports the type, it attempts to authenticate the request.
Primary Methods: The
AuthenticationProvider
interface defines two methods:Authentication authenticate(Authentication authentication)
:Validates the
Authentication
object.Returns an authenticated
Authentication
object if validation is successful.Throws an
AuthenticationException
if authentication fails.
boolean supports(Class<?> authentication)
:- Indicates whether the
AuthenticationProvider
can handle the given type ofAuthentication
object.
- Indicates whether the
Common Implementations of AuthenticationProvider
DaoAuthenticationProvider
:Used for validating username-password credentials.
Relies on a
UserDetailsService
to fetch user details and aPasswordEncoder
to validate the password.Example:
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(passwordEncoder);
JwtAuthenticationProvider
:Used for validating JWT tokens in stateless authentication.
Custom implementation is often used for token-based authentication.
RememberMeAuthenticationProvider
:- Used for "Remember Me" functionality.
UserDetailService Interface
The
UserDetailsService
is a core interface in Spring Security responsible for retrieving user-related data. It is used to load user-specific details (such as username, password, and authorities) during the authentication process.When a user tries to authenticate (e.g., logging in), Spring Security needs to fetch the user's information from a persistent store (like a database). This is where
UserDetailsService
comes into play.
Key Method:
loadUserByUsername(String username)
: This is the most important method in theUserDetailsService
interface. It is used to retrieve user details based on the username (or another unique identifier).
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
The loadUserByUsername
method should return a UserDetails
object, which represents the user’s information (such as their username, password, authorities, etc.).
PasswordEncoder
The
PasswordEncoder
is an interface in Spring Security used to handle password encoding and matching. It provides methods to hash passwords before saving them to the database and to verify the hashed password during the authentication process.By using a
PasswordEncoder
, passwords are stored in a secure, irreversible format, preventing plain-text passwords from being stored or leaked.
Summary
AuthenticationProvider
usesUserDetailsService
to load user details (such as the username, password, and roles) from a data source during the authentication process.The
AuthenticationProvider
checks the credentials and performs authentication, while theUserDetailsService
is responsible for fetching the user data, typically from a database.
SecurityContext
In Spring Security, the
SecurityContext
is a container for holding security-related information about the current user (such as their authentication details) throughout the lifespan of a request. It is a central concept for managing security contexts in a web application.Once the fully authenticated object is created by AuthenticationProvider it is passed to AuthenticationManager and then AuthenticationFilter and then AuthenticationFilter stores it in SecurityContext.
Key Points about SecurityContext
:
Holds the Current User's Authentication:
The
SecurityContext
holds anAuthentication
object, which represents the current authenticated user's details, such as:Username: The identifier of the authenticated user.
Authorities: The roles or permissions granted to the user.
Credentials: Information like passwords (although typically not stored directly).
Principal: The user details (can be a
UserDetails
object, or any other object representing the authenticated user).
SecurityContextHolder:
Spring Security uses the
SecurityContextHolder
class to store and retrieve theSecurityContext
.SecurityContextHolder
has a static method to access theSecurityContext
, allowing you to get or set theAuthentication
object in a thread-local storage.
Thread-Local Storage:
- The
SecurityContext
is typically stored in a thread-local variable, meaning it is specific to the current thread of execution. This allows each request to maintain its own security context, even in a multi-threaded environment (such as web requests handled by different threads).
- The
Key Methods:
SecurityContextHolder.getContext()
: Retrieves theSecurityContext
for the current thread.SecurityContextHolder.getContext().setAuthentication(Authentication authentication)
: Sets theAuthentication
object in the currentSecurityContext
.SecurityContextHolder.clearContext()
: Clears theSecurityContext
, effectively logging the user out.
Summarization of Flow:
1. Incoming Request (Authentication Filter Triggered):
- A user sends a request to the application (e.g., login with username and password).
2. AuthenticationFilter (e.g., UsernamePasswordAuthenticationFilter
):
The
AuthenticationFilter
(typicallyUsernamePasswordAuthenticationFilter
for login) intercepts the request.It extracts the username and password from the request (e.g., form data, headers, etc.).
It then creates an
Authentication
object (e.g.,UsernamePasswordAuthenticationToken
) using these credentials:Authentication authRequest = new UsernamePasswordAuthenticationToken(username, password);
The
AuthenticationFilter
passes theAuthentication
object to theAuthenticationManager
.
3. AuthenticationManager:
The
AuthenticationManager
is responsible for deciding how to authenticate the user.It forwards the
Authentication
object to one or moreAuthenticationProvider
instances to validate the credentials.
4. AuthenticationProvider (e.g., DaoAuthenticationProvider
):
The
AuthenticationProvider
(such asDaoAuthenticationProvider
) validates the credentials.It compares the username and password from the
Authentication
object with the values stored in the database.If the credentials are valid, the
AuthenticationProvider
creates an authenticatedAuthentication
object (e.g.,UsernamePasswordAuthenticationToken
), which contains the principal (user) and authorities (roles or permissions).
5. Return Authenticated Authentication Object:
- The
AuthenticationProvider
returns the authenticatedAuthentication
object to theAuthenticationManager
.
6. AuthenticationFilter Sets SecurityContext:
The
AuthenticationFilter
receives the authenticatedAuthentication
object.It sets the
Authentication
object in theSecurityContext
usingSecurityContextHolder
:SecurityContextHolder.getContext().setAuthentication(authentication);
This step ensures that the user's authentication information is available throughout the application for authorization and access control decisions.
7. Request Continues:
- After authentication, the request is passed to the next filter in the chain, or if it’s a successful login, the response can proceed (e.g., redirecting the user to a dashboard or returning a success response).
Summary of Components Involved:
AuthenticationFilter
: Intercepts the request, extracts credentials, and initiates the authentication process.AuthenticationManager
: Forwards theAuthentication
object to the appropriateAuthenticationProvider
for validation.AuthenticationProvider
: Validates the credentials and creates an authenticatedAuthentication
object.SecurityContext
: TheAuthenticationFilter
sets the authenticatedAuthentication
object in theSecurityContext
for access control and further processing.
What is SecurityFilterChain
In Spring Security, the
SecurityFilterChain
defines a series of filters that are applied to HTTP requests as they pass through the security pipeline. Each filter serves a specific purpose and is applied in a sequence, depending on the configuration.The filters in the
SecurityFilterChain
typically handle different aspects of security, such as authentication, authorization, session management, and protection against common vulnerabilities (e.g., CSRF, CORS).
What is difference between AuthenticationFilter and SecurityFilterChain
AuthenticationFilter
is one of the filters used by theSecurityFilterChain
to process requests, and theSecurityFilterChain
is the overall configuration that manages the sequence and application of various security filters.
Common Filters in SecurityFilterChain
ChannelProcessingFilter:
This filter is used to ensure that requests are served over a secure channel (e.g., HTTPS). If a request comes over HTTP but should be served over HTTPS, this filter can redirect the request to the secure channel.
It’s usually the first filter applied in the chain.
SecurityContextPersistenceFilter
:This filter loads the
SecurityContext
(which contains the authentication information) from the session or other persistent storage (e.g., cookies).It is responsible for managing the
SecurityContext
between requests.
AuthenticationFilter
(e.g.,UsernamePasswordAuthenticationFilter
):This filter handles authentication logic. For example, the
UsernamePasswordAuthenticationFilter
checks for the presence of a username and password, and if found, tries to authenticate the user by delegating the authentication task to anAuthenticationManager
.If using other authentication mechanisms like JWT, a custom
AuthenticationFilter
(e.g.,JwtAuthenticationFilter
) could be used.
CsrfFilter
:- This filter provides protection against Cross-Site Request Forgery (CSRF) attacks. It ensures that requests made to the server include a valid CSRF token, making it harder for attackers to trick users into submitting malicious requests on their behalf.
CorsFilter
:- This filter handles Cross-Origin Resource Sharing (CORS) requests. It adds the necessary HTTP headers to support cross-origin requests, often required for APIs that are accessed by web applications hosted on different domains.
- There are many more filters in the SecurityChainFilter
Does a Request Pass Through All Filters in the SecurityFilterChain
?
Yes, a request typically passes through each filter in the
SecurityFilterChain
, but not all filters will necessarily take action on every request.Filters are applied in the order they are defined, and each one serves a distinct purpose in securing the application.
Example of how SecurityFilterChain
is defined in security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// this line specifies that, each request comming to server is authenticated
http.authorizeHttpRequests().anyRequest().authenticated();
http.formLogin(Customizer.withDefaults());
http.httpBasic(Customizer.withDefaults());
return (SecurityFilterChain)http.build();
}
}
Important Note:
By default Spring security framework protects all the paths present inside the web application.This behaviour is due to code present inside the method
defaultSecurityFilterChain(HttpSecurity http)
of classSpringBootWebSecurityConfiguration
The class WebSecurityConfigurerAdapter→configure(HttpSecurity http) is deprecated so do not use.
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
http.formLogin();
http.httpBasic();
return http.build();
}
In memory authentication
- You can use In memory authentication for testing purpose lets say you don’t want to create user from database you can use in memory authentication.
Example:
- SecurityConfig.java
package org.example.springsecuritypractice.config;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
UserDetailsService userDetailsService() {
UserDetails user1 = User.withUsername("harsh")
.password("{noop}harsh")
.roles("USER")
.build();
UserDetails user2 = User.withUsername("prachi")
.password("{noop}harsh")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user1, user2);
}
}
Roles and PreAuthrorize in Spring security
What is @PreAuthorize
?
- The
@PreAuthorize
annotation in Spring Security is used to perform method-level security. It allows you to apply access control on individual methods based on specified security conditions, such as user roles, authorities, or custom expressions.
Common Usage
Role-Based Access Control
@PreAuthorize("hasRole('ADMIN')") public void adminOnlyMethod() { // Only accessible by users with the ADMIN role }
Authority-Based Access Control
@PreAuthorize("hasAuthority('READ_PRIVILEGE')") public void readOnlyMethod() { // Only accessible by users with the READ_PRIVILEGE authority }
Multiple Roles or Authorities
@PreAuthorize("hasAnyRole('ADMIN', 'USER')") public void adminOrUserMethod() { }
What is @EnableMethodSecurity
?
The @EnableMethodSecurity
annotation is used to enable method-level security in a Spring Security configuration class. Without this annotation, annotations like @PreAuthorize
, @PostAuthorize
, and others related to method security will not work.