Chapter 1: Introduction to Spring Security
Introduction
Before configuring anything, it is essential to understand how Spring Security works. This chapter lays the foundations that will allow you to configure security correctly.
🎯 Chapter Objectives
By the end of this chapter, you will know:
- ✅ Why security is essential
- ✅ The difference between Authentication and Authorization
- ✅ The architecture of Spring Security
- ✅ How the filter chain works
- ✅ Key concepts: Principal, Credentials, Authorities
1. Why Secure an Application?
Threats
Real Examples
| Year | Company | Impact |
|---|---|---|
| 2023 | MOVEit | 60M+ users affected |
| 2021 | 533M accounts exposed | |
| 2019 | Capital One | 100M+ data stolen |
| 2017 | Equifax | 147M personal data |
The 3 Pillars of Security (CIA)
┌─────────────────────────────────────────────────┐
│ │
│ C - Confidentiality │
│ Only authorized people │
│ can view the data │
│ │
│ I - Integrity │
│ Data cannot be │
│ modified without authorization │
│ │
│ A - Availability │
│ The system remains accessible │
│ to legitimate users │
│ │
└─────────────────────────────────────────────────┘
2. Authentication vs Authorization
The Fundamental Difference
| Concept | Question | Example |
|---|---|---|
| Authentication | "Who are you?" | Login with email/password |
| Authorization | "Do you have the right?" | Access /admin (reserved for admins) |
Analogy: The VIP Club
In Spring Security
// Authentication: Who is logged in?
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); // "john@example.com"
// Authorization: What are their rights?
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
// [ROLE_USER] - Not ROLE_ADMIN!
3. Architecture of Spring Security
Overview
Key Components
1. SecurityFilterChain
The filter chain that intercepts ALL requests:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
}
2. AuthenticationManager
Coordinates authentication:
3. UserDetailsService
Interface for loading users:
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
4. PasswordEncoder
Encodes passwords (NEVER in plain text!):
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// Usage
String encoded = passwordEncoder.encode("myPassword");
// $2a$10$N9qo8uLOickgx2ZMRZoMye...
boolean matches = passwordEncoder.matches("myPassword", encoded);
// true
4. The Filter Chain in Detail
Order of Filters (Simplified)
1. CorsFilter → CORS Management
2. CsrfFilter → CSRF Protection
3. LogoutFilter → Logout Management
4. UsernamePasswordAuthFilter → Form Login
5. BasicAuthenticationFilter → HTTP Basic Auth
6. BearerTokenAuthFilter → JWT/OAuth2
7. AnonymousAuthenticationFilter → Anonymous User
8. ExceptionTranslationFilter → Error Management
9. FilterSecurityInterceptor → Final Access Decision
Flow Visualization
5. Key Concepts
Principal
The identity of the logged-in user:
@GetMapping("/profile")
public String profile(Principal principal) {
String username = principal.getName();
return "Welcome " + username;
}
Authentication Object
Contains all authentication information:
public interface Authentication {
Collection<? extends GrantedAuthority> getAuthorities(); // Roles/Permissions
Object getCredentials(); // Password (often erased after auth)
Object getDetails(); // Additional details (IP, etc.)
Object getPrincipal(); // The user (UserDetails)
boolean isAuthenticated();
}
GrantedAuthority
Represents a role or permission:
// Roles (prefix ROLE_)
new SimpleGrantedAuthority("ROLE_ADMIN");
new SimpleGrantedAuthority("ROLE_USER");
// Permissions
new SimpleGrantedAuthority("READ_USERS");
new SimpleGrantedAuthority("WRITE_USERS");
new SimpleGrantedAuthority("DELETE_USERS");
SecurityContext
Stores the current user's Authentication:
// Retrieve the logged-in user
SecurityContext context = SecurityContextHolder.getContext();
Authentication auth = context.getAuthentication();
if (auth != null && auth.isAuthenticated()) {
String username = auth.getName();
// ...
}
UserDetails
Interface representing a user:
public interface UserDetails {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
6. Types of Authentication
1. Form Login (Session)
Client → POST /login (user, pass)
Server → Set-Cookie: JSESSIONID=xyz
Client → GET /api/data (Cookie: JSESSIONID=xyz)
Server → Verify session → 200 OK
Advantages: Simple, managed by the browser Disadvantages: Not suitable for stateless REST APIs
2. HTTP Basic
Client → GET /api/data
Server → 401 + WWW-Authenticate: Basic
Client → GET /api/data (Authorization: Basic base64(user:pass))
Server → 200 OK
Advantages: Simple Disadvantages: Credentials sent with every request
3. JWT (Token)
Client → POST /login (user, pass)
Server → {"token": "eyJhbGciOiJIUzI1..."}
Client → GET /api/data (Authorization: Bearer eyJhbGciOiJIUzI1...)
Server → Verify token → 200 OK
Advantages: Stateless, perfect for REST APIs Disadvantages: Expiration management
4. OAuth2
Client → Redirect to Google
Google → User login
Google → Redirect with code
Server → Exchange code for token
Server → Retrieve user profile
Advantages: No password management, modern UX Disadvantages: External dependency
7. Modern Configuration (Spring Security 6+)
Old Method (Deprecated)
// ❌ DO NOT USE
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
New Method (Spring Security 6+)
// ✅ USE THIS APPROACH
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
8. First Configuration
Maven Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Default Behavior
Without any configuration, Spring Security:
- Protects ALL endpoints
- Generates a random password (displayed in logs)
- Activates form login on
/login - Activates logout on
/logout
Using generated security password: 8e3d7a2c-1234-5678-abcd-ef0123456789
Minimal Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/home", "/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
)
.logout(logout -> logout
.permitAll()
)
.build();
}
}
9. Summary
Key Concepts
| Concept | Description |
|---|---|
| Authentication | Verify identity (who?) |
| Authorization | Verify rights (what?) |
| SecurityFilterChain | Security filter chain |
| AuthenticationManager | Orchestrates authentication |
| UserDetailsService | Loads users |
| PasswordEncoder | Encodes passwords |
| SecurityContext | Stores the current user |
Simplified Architecture
HTTP Request
↓
SecurityFilterChain (filters)
↓
AuthenticationManager
↓
UserDetailsService + PasswordEncoder
↓
SecurityContext (storage)
↓
Application (Controller)
Important Points
✅ Spring Security 6+ uses @Bean, not extends WebSecurityConfigurerAdapter
✅ Always encode passwords (BCrypt)
✅ Understand Authentication vs Authorization
✅ Security is configured via SecurityFilterChain
🎯 Next Step
Now that you understand the architecture, let's move on to practice with basic authentication.
➡️ Chapter 2: Basic Authentication