24 - Spring Security Architecture
What is Spring Security?
Spring Security is a framework for securing Java applications, especially applications built with Spring Boot.
It provides mechanisms to protect application resources by controlling:
- Who can access the application? β Authentication
- What can an authenticated user access? β Authorization
- How are security rules applied to HTTP requests? β Security Architecture
Why do we need Spring Security?
Imagine an application with the following endpoints:
GET /productsβ Anyone can access.POST /productsβ Only authenticated users can access.DELETE /products/1β Only administrators can access.
Without a security framework, we would need to implement authentication and authorization manually in every endpoint.
Spring Security provides a centralized and configurable way to enforce these rules.
Example
@RestController
@RequestMapping("/products")
public class ProductController {
@GetMapping
public String getProducts() {
return "Public products";
}
@PostMapping
public String createProduct() {
return "Product created";
}
@DeleteMapping("/{id}")
public String deleteProduct(@PathVariable Long id) {
return "Product deleted";
}
}
With Spring Security, we can configure:
GET /products
β Public
POST /products
β Requires authentication
DELETE /products/{id}
β Requires ADMIN role
The controller does not need to implement the authentication logic itself.
Authentication
What is Authentication?
Authentication is the process of verifying the identity of a user or system.
In simple terms:
Authentication answers: βWho are you?β
Real-world example
When you log in to your bank:
- You enter your username.
- You enter your password.
- The bank verifies your credentials.
- If they are valid, you are authenticated.
The same concept applies to Spring Security.
Example
Username: bruno
Password: 123456
β
Spring Security verifies credentials
β
Credentials are valid
β
User is authenticated
Authentication flow
Client
β
Sends credentials
β
Spring Security
β
AuthenticationManager
β
AuthenticationProvider
β
UserDetailsService
β
PasswordEncoder
β
Credentials verified
β
Authenticated user
Important components
Authentication
Authentication is an interface that represents the authentication request or the authenticated user.
It contains information such as:
- Principal
- Credentials
- Authorities
- Authentication status
Example:
Authentication authentication;
After successful authentication:
authentication.isAuthenticated();
Returns:
true
AuthenticationManager
AuthenticationManager is the main interface responsible for authenticating a user.
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
Its responsibility is to delegate the authentication process to an appropriate AuthenticationProvider.
AuthenticationProvider
AuthenticationProvider contains the actual authentication logic for a particular authentication mechanism.
For example:
-
Username and password
-
LDAP
-
OAuth2
-
JWT
-
Custom authentication
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication);}
Example:
AuthenticationManager
β
AuthenticationProvider
β
Verify username and password
β
Return authenticated user
UserDetailsService
UserDetailsService is responsible for loading user information.
public interface UserDetailsService {
UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException;
}
Example:
@Service
public class CustomUserDetailsService
implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
return User.withUsername(username)
.password("{noop}123456")
.roles("USER")
.build();
}
}
In a real application, passwords should not be stored using
{noop}. Use a properPasswordEncoder.
PasswordEncoder
PasswordEncoder is responsible for encoding passwords and verifying passwords against their encoded values.
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(
CharSequence rawPassword,
String encodedPassword
);
}
Example:
PasswordEncoder encoder =
new BCryptPasswordEncoder();
String encodedPassword =
encoder.encode("123456");
The password is not stored as plain text.
Raw password:
123456
Encoded password:
$2a$10$...
Authentication vs Credentials
These concepts are related but different.
| Concept | Meaning |
|---|---|
| Credentials | Information used to prove identity |
| Authentication | The process of verifying identity |
| Authenticated user | The identity after successful verification |
Example:
Username + Password
β
Credentials
β
Authentication process
β
Authenticated user
Authorization
What is Authorization?
Authorization is the process of determining what an authenticated user is allowed to access.
In simple terms:
Authorization answers: βWhat are you allowed to do?β
Real-world example
Imagine a company system:
User: Bruno
Role: USER
Bruno can:
- View products.
- Create orders.
But Bruno cannot:
- Delete products.
- Manage users.
An administrator can perform those operations.
Authentication vs Authorization
This is one of the most important concepts in Spring Security.
| Authentication | Authorization |
|---|---|
| Verifies identity | Verifies permissions |
| βWho are you?" | "What can you do?β |
| Happens before authorization | Happens after authentication |
| Example: Login | Example: Access /admin |
| Uses credentials | Uses roles/authorities |
Example
User enters username and password
β
Authentication
β
User is authenticated
β
User requests /admin
β
Authorization
β
Does the user have ADMIN authority?
β
Yes β Allow
No β Deny
Roles and Authorities
Spring Security uses authorities to represent permissions.
A role is a special type of authority.
Example:
ROLE_USER
ROLE_ADMIN
ROLE_MANAGER
Authorities can represent more specific permissions:
READ_PRODUCTS
CREATE_PRODUCTS
DELETE_PRODUCTS
Role example
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**")
.hasRole("ADMIN")
)
This means:
User must have ROLE_ADMIN
Authority example
.authorizeHttpRequests(auth -> auth
.requestMatchers("/products")
.hasAuthority("READ_PRODUCTS")
)
This means:
User must have READ_PRODUCTS authority
Important difference
.hasRole("ADMIN")
Internally checks:
ROLE_ADMIN
While:
.hasAuthority("ROLE_ADMIN")
Checks the exact authority:
ROLE_ADMIN
Authorization example
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(
HttpSecurity http
) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
What happens here?
/public/**
β Anyone can access
/admin/**
β Requires ADMIN role
Any other endpoint
β Requires authentication
Spring Security Architecture
Overview
Spring Security is based on a filter-based security architecture.
Instead of implementing security logic inside every controller, Spring Security intercepts HTTP requests before they reach the application.
Client
β
HTTP Request
β
Spring Security Filters
β
Authentication
β
Authorization
β
Controller
β
HTTP Response
Why use filters?
Filters allow Spring Security to apply security rules consistently across the application.
For example:
Every request
β
Check authentication
β
Check authorization
β
Allow or reject request
This avoids duplicating security logic in every controller.
Main Components of Spring Security Architecture
1. SecurityFilterChain
SecurityFilterChain defines the security rules that apply to incoming HTTP requests.
It is one of the most important components in Spring Security.
Example:
@Bean
SecurityFilterChain securityFilterChain(
HttpSecurity http
) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
What does it do?
It configures:
- Which requests are public.
- Which requests require authentication.
- Which requests require specific roles.
- How authentication is performed.
- How security exceptions are handled.
Example
GET /public/products
β
SecurityFilterChain
β
permitAll()
β
Controller
GET /admin/users
β
SecurityFilterChain
β
Requires ADMIN
β
Authenticated?
β
Yes β Authorization check
No β 401 Unauthorized
2. DelegatingFilterProxy
Spring Security integrates with the Servlet container through a filter called DelegatingFilterProxy.
Its responsibility is to delegate requests to Spring-managed security components.
Servlet Container
β
DelegatingFilterProxy
β
Spring Security
β
SecurityFilterChain
Why is it needed?
The Servlet container manages servlet filters, while Spring manages Spring beans.
DelegatingFilterProxy acts as a bridge between them.
Servlet Filter
β
DelegatingFilterProxy
β
Spring Application Context
β
SecurityFilterChain
3. FilterChainProxy
FilterChainProxy is the main entry point into Spring Securityβs filter system.
It receives the request and delegates it to the appropriate SecurityFilterChain.
HTTP Request
β
DelegatingFilterProxy
β
FilterChainProxy
β
SecurityFilterChain
β
Security Filters
Important distinction
DelegatingFilterProxy
β Integrates Servlet container with Spring
FilterChainProxy
β Delegates requests to the appropriate security filter chain
4. Security Filters
Security filters are responsible for processing HTTP requests and applying security logic.
Examples include filters that:
- Authenticate users.
- Process login requests.
- Process JWT tokens.
- Handle security context.
- Apply authorization rules.
- Handle security exceptions.
Example filter flow
HTTP Request
β
SecurityContextHolderFilter
β
Authentication Filter
β
Authorization Filter
β
Controller
The exact filters and their order depend on the Spring Security configuration and authentication mechanism.
5. SecurityContextHolder
SecurityContextHolder is used to store the security context for the current execution.
The security context contains information about the currently authenticated user.
SecurityContext context =
SecurityContextHolder.getContext();
To retrieve the authenticated user:
Authentication authentication =
context.getAuthentication();
Example:
Authentication authentication =
SecurityContextHolder
.getContext()
.getAuthentication();
String username =
authentication.getName();
What is stored?
SecurityContext
β
Authentication
β
Principal
β
Authorities
Example
Authenticated user:
bruno
Authorities:
ROLE_USER
READ_PRODUCTS
Important concept
The SecurityContextHolder provides access to the authentication information during request processing.
6. SecurityContext
SecurityContext is an object that stores the current authentication information.
public interface SecurityContext {
Authentication getAuthentication();
void setAuthentication(Authentication authentication);
}
Example:
SecurityContext context =
SecurityContextHolder.getContext();
Authentication authentication =
context.getAuthentication();
7. Authentication
The Authentication object represents the current authentication state.
It contains information such as:
Principal
Credentials
Authorities
Authenticated status
Example:
Authentication authentication =
SecurityContextHolder
.getContext()
.getAuthentication();
Example output
Principal: bruno
Authorities: ROLE_USER
Authenticated: true
8. AuthenticationManager
AuthenticationManager is responsible for authenticating the user.
Authentication Filter
β
AuthenticationManager
β
AuthenticationProvider
β
UserDetailsService
β
PasswordEncoder
Example
Authentication authentication =
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
username,
password
)
);
What happens?
Username + Password
β
AuthenticationManager
β
AuthenticationProvider
β
Load user
β
Verify password
β
Return Authentication
9. AuthenticationProvider
AuthenticationProvider performs the actual authentication logic.
For username/password authentication, a common implementation is:
DaoAuthenticationProvider
Example flow
AuthenticationManager
β
DaoAuthenticationProvider
β
UserDetailsService
β
PasswordEncoder
β
Authenticated user
Responsibilities
- Load user information.
- Verify credentials.
- Create an authenticated
Authenticationobject. - Return authentication or throw an exception.
10. UserDetailsService
UserDetailsService loads user information from a data source.
The data source could be:
- Database.
- In-memory storage.
- LDAP.
- Custom service.
Example:
@Service
public class CustomUserDetailsService
implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
return User.withUsername(username)
.password("{noop}123456")
.roles("USER")
.build();
}
}
Important concept
UserDetailsService does not authenticate the user by itself.
It loads the user information.
UserDetailsService
β Loads user
AuthenticationProvider
β Verifies credentials
11. UserDetails
UserDetails represents the user information used by Spring Security.
public interface UserDetails {
Collection<? extends GrantedAuthority>
getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
Example
Username:
bruno
Password:
Encoded password
Authorities:
ROLE_USER
12. GrantedAuthority
GrantedAuthority represents an authority granted to an authenticated user.
Example:
new SimpleGrantedAuthority("ROLE_ADMIN");
Or:
new SimpleGrantedAuthority("READ_PRODUCTS");
Example
User:
bruno
Authorities:
ROLE_USER
READ_PRODUCTS
13. PasswordEncoder
PasswordEncoder is responsible for password encoding and verification.
Example:
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Why use a password encoder?
Passwords should not be stored as plain text.
Plain password:
123456
Encoded password:
$2a$10$...
During login:
Raw password
β
PasswordEncoder.matches()
β
Compare with stored encoded password
β
Valid or invalid
Complete Authentication Architecture
Username and Password Authentication
ββββββββββββββββββββββββ
β Client β
β Username + Password β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Security Filters β
β Authentication Filterβ
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β AuthenticationManagerβ
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β AuthenticationProviderβ
β DaoAuthenticationProviderβ
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β UserDetailsService β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Database β
β User + Password β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β PasswordEncoder β
β Verify Password β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Authenticated User β
β Authentication objectβ
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β SecurityContext β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Authorization β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Controller β
ββββββββββββββββββββββββ
Complete Request Flow
Example: GET /admin/users
Imagine a user sends:
GET /admin/users
Step 1 β Client sends request
Client
β
GET /admin/users
Step 2 β Request enters Spring Security
HTTP Request
β
DelegatingFilterProxy
β
FilterChainProxy
β
SecurityFilterChain
Step 3 β Authentication is checked
Spring Security checks whether the request contains valid authentication information.
For example:
Session
JWT
Basic Authentication
OAuth2
Step 4 β Authentication is loaded
If the user is authenticated:
SecurityContextHolder
β
Authentication
Example:
Username:
bruno
Authorities:
ROLE_USER
Step 5 β Authorization is checked
The security configuration says:
.requestMatchers("/admin/**")
.hasRole("ADMIN")
Spring Security checks:
Does the user have ROLE_ADMIN?
Step 6 β Access decision
ROLE_ADMIN exists?
β
Yes β Allow request
No β Deny request
Step 7 β Controller executes
If authorized:
@GetMapping("/admin/users")
public String getUsers() {
return "Users";
}
Step 8 β Response is returned
Controller
β
HTTP Response
β
Client
Authentication and Authorization in One Flow
ββββββββββββββββββββββββ
β Client β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β HTTP Request β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Spring Security β
β Security Filters β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Authentication β
β "Who are you?" β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Authenticated User β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Authorization β
β "What can you do?" β
ββββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββ
β Allowed?β
ββββββ¬βββββ
β
ββββββ΄βββββ
β β
Yes No
β β
βΌ βΌ
Controller 403 Forbidden
β
βΌ
HTTP Response
Authentication vs Authorization: Practical Example
Imagine a banking application.
User logs in
Username: bruno
Password: ********
Spring Security verifies the credentials.
Authentication successful
User accesses account
GET /accounts
The user has:
ROLE_USER
Access is allowed.
User tries to delete another account
DELETE /accounts/10
The endpoint requires:
ROLE_ADMIN
The user only has:
ROLE_USER
Access is denied.
403 Forbidden
Summary
Authentication:
"Are you Bruno?"
Authorization:
"Are you allowed to delete this account?"
401 Unauthorized vs 403 Forbidden
These two HTTP status codes are very important.
401 Unauthorized
The request is not authenticated.
Example:
User tries to access a protected endpoint
β
No valid authentication
β
401 Unauthorized
In simple terms:
βYou need to authenticate first.β
403 Forbidden
The user is authenticated but does not have permission.
Example:
User is authenticated
β
User requests admin endpoint
β
User does not have ADMIN authority
β
403 Forbidden
In simple terms:
βWe know who you are, but you are not allowed to do this.β
Comparison
| Status | Meaning | Example |
|---|---|---|
| 401 | Not authenticated | Missing or invalid credentials |
| 403 | Not authorized | Authenticated user lacks permission |
Spring Security Architecture with JWT
Spring Security can also authenticate requests using JWT tokens.
What is JWT?
JWT (JSON Web Token) is a token format commonly used for stateless authentication.
Instead of sending username and password on every request, the client sends a token.
Example
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
JWT authentication flow
Client
β
Login
β
Authentication
β
JWT Token Generated
β
Client Stores Token
β
Client Sends Token
β
Spring Security JWT Filter
β
Validate Token
β
Create Authentication
β
SecurityContextHolder
β
Authorization
β
Controller
Example request
GET /products
Authorization: Bearer <JWT>
What happens?
JWT Token
β
JWT Authentication Filter
β
Validate token
β
Extract username and authorities
β
Create Authentication object
β
Store in SecurityContext
β
Authorization
β
Controller
Important concept
With JWT authentication, the application usually does not need to store a server-side session for every user.
This is called stateless authentication.
Stateless vs Stateful Authentication
Stateful Authentication
The server stores authentication information in a session.
Client
β
Login
β
Server creates session
β
Client receives session ID
β
Client sends session ID
β
Server loads session
β
Authenticated user
Stateless Authentication
The client sends a token with every request.
Client
β
Login
β
Server generates JWT
β
Client receives JWT
β
Client sends JWT
β
Server validates JWT
β
Authenticated user
Comparison
| Stateful | Stateless |
|---|---|
| Uses server-side session | Uses token |
| Server stores authentication state | Server does not need to store session state |
| Common with session-based login | Common with JWT |
| Client sends session ID | Client sends token |
SecurityContextHolder and ThreadLocal
By default, Spring Security uses a ThreadLocal-based strategy to associate the security context with the current thread.
What is ThreadLocal?
ThreadLocal allows each thread to have its own independent value.
Example:
Thread 1
β
SecurityContext β User A
Thread 2
β
SecurityContext β User B
Why is this useful?
When a request is processed, Spring Security can access the authenticated user through:
SecurityContextHolder.getContext()
Example
@GetMapping("/profile")
public String profile() {
Authentication authentication =
SecurityContextHolder
.getContext()
.getAuthentication();
return authentication.getName();
}
If Bruno is authenticated:
bruno
Important concept
The security context is associated with the current execution context, not simply with the application as a whole.
SecurityContext Lifecycle
The security context is associated with the current request and execution context.
A simplified flow is:
Request starts
β
SecurityContext is loaded
β
Authentication is available
β
Controller executes
β
Request finishes
β
SecurityContext is handled according to the configured strategy
Important note
In modern Spring Security, SecurityContextHolderFilter is commonly used to load the security context, while persistence behavior depends on the configured security context strategy.
For session-based applications, the context can be associated with the HTTP session.
For stateless applications, the context is typically created for the request and does not need to be persisted as a server-side session.
Request Authorization Architecture
Spring Security can apply authorization rules at different levels.
URL-based authorization
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
Method-based authorization
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) {
// Delete user
}
Important concept
Authorization can happen:
HTTP Request Level
β
Method Level
Example
GET /users/1
β
URL authorization
β
Controller method
β
Method authorization
β
Business logic
Example: Spring Boot Security Configuration
Dependency
In a Spring Boot application, add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(
HttpSecurity http
) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
What does this configuration do?
/public/**
β Public
/admin/**
β Requires ADMIN role
Any other endpoint
β Requires authentication
Authentication mechanism
β HTTP Basic
Example request
GET /public/products
Result:
200 OK
Example request
GET /admin/users
Without authentication:
401 Unauthorized
With authentication but without ADMIN role:
403 Forbidden
Important Spring Security Interfaces
| Interface | Responsibility |
|---|---|
SecurityFilterChain | Defines security rules |
AuthenticationManager | Authenticates users |
AuthenticationProvider | Performs authentication logic |
UserDetailsService | Loads user information |
UserDetails | Represents user information |
PasswordEncoder | Encodes and verifies passwords |
Authentication | Represents authentication |
SecurityContext | Stores authentication |
SecurityContextHolder | Provides access to security context |
GrantedAuthority | Represents permissions |
Important Classes
| Class | Responsibility |
|---|---|
DelegatingFilterProxy | Connects Servlet filters to Spring |
FilterChainProxy | Delegates requests to security filter chains |
DaoAuthenticationProvider | Authenticates using user details and password |
UsernamePasswordAuthenticationToken | Represents username/password authentication |
SecurityContextHolder | Stores and retrieves security context |
BCryptPasswordEncoder | Encodes passwords using BCrypt |
Authentication Flow vs Authorization Flow
Authentication flow
Request
β
Authentication Filter
β
AuthenticationManager
β
AuthenticationProvider
β
UserDetailsService
β
PasswordEncoder
β
Authentication
β
SecurityContextHolder
Authorization flow
Request
β
SecurityContextHolder
β
Authentication
β
GrantedAuthority
β
Authorization rules
β
Allow or deny
Common Interview Questions
1. What is Spring Security?
Spring Security is a framework that provides authentication, authorization, and protection mechanisms for Spring applications.
2. What is the difference between authentication and authorization?
Authentication verifies identity.
Authorization verifies permissions.
3. What is SecurityFilterChain?
It defines the security rules and filters that apply to HTTP requests.
4. What is AuthenticationManager?
It is responsible for authenticating users by delegating to an appropriate AuthenticationProvider.
5. What is AuthenticationProvider?
It performs the actual authentication logic for a specific authentication mechanism.
6. What is UserDetailsService?
It loads user information, usually from a database or another data source.
7. What is PasswordEncoder?
It encodes passwords and verifies raw passwords against encoded passwords.
8. What is SecurityContextHolder?
It provides access to the security context containing the current authentication.
9. What is the difference between 401 and 403?
401 means the request is not authenticated.
403 means the user is authenticated but does not have permission.
10. What is the role of GrantedAuthority?
It represents permissions granted to an authenticated user.
Final Summary
Spring Security is built around two fundamental concepts:
Authentication
β
Who are you?
Authorization
β
What can you do?
The architecture connects these concepts through security filters and authentication components.
HTTP Request
β
SecurityFilterChain
β
Authentication
β
SecurityContextHolder
β
Authorization
β
Controller
The most important components to remember
SecurityFilterChain
β
AuthenticationManager
β
AuthenticationProvider
β
UserDetailsService
β
PasswordEncoder
β
Authentication
β
SecurityContextHolder
β
Authorization
The most important idea
Spring Security intercepts requests, authenticates the user, stores the authentication information, and then checks whether the user is authorized to access the requested resource.