| π Articles | π€ My Profile |
It offers:
| Area | Description |
|---|---|
| Authentication | Verifying who the user is β can be local login or via IAM/IdP (Keycloak, Okta, Auth0, Azure AD). |
| Authorization | Deciding what the user can do β includes roles, permissions, IAM policies. |
| Data Security | Protecting sensitive data at rest and in transit. |
| API Security | Securing API endpoints from unauthorized access (CSRF, CORS, rate limiting, API keys). |
| Configuration Security | Protecting secrets, credentials, and environment settings. |
| Transport Security | Encrypting communication (HTTPS/TLS). |
| Deployment Security | Hardening servers, containers, and networks. |
BCrypt, Argon2, or PBKDF2.| Term | Meaning | Why It Matters |
|---|---|---|
| MFA (Multi-Factor Authentication) | Multiple verification methods (e.g., password + OTP + biometric) | Reduces risk from stolen passwords |
| 2FA (Two-Factor Authentication) | One extra verification step (usually OTP) | Easier to implement than full MFA |
| IdP (Identity Provider) | Service that manages user identity (Okta, Auth0, Azure AD) | Centralizes authentication |
| IAM (Identity & Access Management) | Framework for managing identities and permissions in large organizations | Ensures consistent, secure access control |
| Threat | Protection |
|---|---|
| CSRF | Enabled by default for web apps |
| XSS | Encode output, validate inputs |
| SQL Injection | Use JPA / Prepared Statements |
| Session Fixation | Automatically mitigated |
| Clickjacking | Uses X-Frame-Options header |
Spring Securityβs architecture is built around a set of core components that work in harmony to protect your applications. In this section, weβll break down these components and illustrate them with examples following modern best practices.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
}
Types of authentication methods in Spring Security:
1. Basic Authentication
2. Form-based Login
3. Token-based Authentication (JWT)
4. OAuth2 / OpenID Connect (OIDC)
5. LDAP Authentication
6. SAML Authentication
7. IAM Integration
Once authentication is complete, authorization takes over to determine whether the verified user has the necessary permissions to perform a specific action or access a particular resource. In other words, it answers the question, βAre you allowed to do this?β β
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize -> authorize
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated())
.formLogin().and()
.httpBasic();
return http.build();
}
π Method-Level Security
We can enforce authorization rules directly within service methods by applying annotations like @PreAuthorize or @Secured.
Step 1: Enable Method Security
To apply Spring Security to specific methods in the REST Controller class of your Spring Boot application, you must enable method-level security. This is done using the @EnableMethodSecurity annotation.
@Configuration
@EnableMethodSecurity
public class SpringSecurityConfig {
}
@EnableMethodSecurity is a Spring annotation that turns on method-level security in a Spring application. When used, Spring creates proxies for the classes containing secured methods and intercepts method calls to check whether the current user has the required permissions.
It works with other security annotations such as:
@PreAuthorize β Check permissions before method execution.@PostAuthorize β Check permissions after method execution.@Secured β Restrict method access based on roles.@RolesAllowed β Similar to @Secured, role-based method access control.For example:
@PreAuthorize("hasRole('ADMIN')") β Allows access only to ADMIN role.@PostAuthorize β Can be used to return only the data a user is allowed to see.Step 2: Apply Role-Based Access Control
@RestController
@RequestMapping("/api/")
public class AdminController {
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public ResponseEntity<String> helloAdmin() {
return ResponseEntity.ok("Hello Admin");
}
@PreAuthorize("hasRole('USER')")
@GetMapping("/user")
public ResponseEntity<String> helloUser() {
return ResponseEntity.ok("Hello User");
}
}
Different authorization methods:
Authorization can be implemented in several different ways depending on your applicationβs architecture, authentication method, and security requirements.
1. Role-Based Access Control (RBAC)
ROLE_ADMIN, ROLE_USER) and access is granted based on those roles.http.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
);
2. Permission/Authority-Based Access Control
READ_PRIVILEGE, WRITE_PRIVILEGE).http.authorizeHttpRequests(auth -> auth
.requestMatchers("/reports/**").hasAuthority("REPORT_VIEW")
.anyRequest().authenticated()
);
3. URL/Endpoint-Based Authorization
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/secure/**").authenticated()
);
4. Method-Level Authorization
@PreAuthorize, @PostAuthorize, @Secured to secure service or controller methods.@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }
5. Expression-Based Authorization
@PreAuthorize("#username == authentication.name or hasRole('ADMIN')")
public void updateProfile(String username) { ... }
6. OAuth2 / OpenID Connect Authorization
http.oauth2Login(); // OAuth2 login
http.oauth2ResourceServer().jwt(); // JWT validation
7. Attribute-Based Access Control (ABAC)
AccessDecisionVoter or use SpEL with attributes.8. Custom Voter / Access Decision Manager
AccessDecisionVoter to decide based on your own rules.9. Multi-Factor Authorization Checks
@PreAuthorize with multiple clauses.β Summary Table
| Method | Granularity | Example Use Case |
|---|---|---|
| RBAC | Coarse | Admin vs User |
| Permission-Based | Medium | CRUD privileges |
| URL-Based | Coarse | API endpoint restrictions |
| Method-Level | Fine | Secure service methods |
| Expression-Based | Very Fine | Conditional rules |
| OAuth2/OIDC | Token-Based | SSO, federated login |
| ABAC | Very Fine | Context & attribute-based |
| Custom Voter | Fully Custom | Department-based logic |
A principal represents the details of the currently authenticated user and is accessible across the application to perform user-specific operations.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
Granted authorities specify the permissions assigned to an authenticated user, defining the actions they are allowed to perform and the resources they can access.
.antMatchers("/api/private/**").hasAuthority("ROLE_USER")
At the core of Spring Security lies the SecurityContext, which stores information about the currently authenticated user, known as the principal. This context can be accessed anywhere in the application through the SecurityContextHolder, enabling you to make decisions and perform operations based on the userβs authentication status and granted authorities.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
}
The UserDetails interface is a core component in Spring Security, representing the user data that the framework relies on for authentication and authorization. It provides essential information to Spring Security, including:
GrantedAuthority objects that define the userβs roles and permissions, essential for authorization checks.By implementing UserDetails, you can seamlessly connect your applicationβs user model with Spring Security, enabling customized authentication and authorization logic.
UserDetailsService is a core Spring Security interface responsible for fetching user-specific data during the authentication process. It contains a single method:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
This method locates a user by their username and returns a UserDetails object, which Spring Security then uses for authentication and authorization.
When you implement a custom UserDetailsService, you typically:
UserDetails object.UserDetails object so Spring Security can perform authentication checks and determine authorities for authorization.A custom UserDetailsService acts as the bridge between your applicationβs user repository and Spring Securityβs authentication framework.
In Spring Security, the AuthenticationManager serves as the central entry point for processing authentication requests.
Think of it as the orchestrator that delegates the verification of user credentials to one or more configured AuthenticationProvider instances.
Key Responsibilities
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
How it works:
SecurityFilterChain defines request authorization rules and enables form login.AuthenticationManager is obtained from AuthenticationConfiguration, which auto-registers configured providers.configureGlobal() binds the UserDetailsService and PasswordEncoder to the authentication process.The PasswordEncoder interface in Spring Security is used to encode raw passwords and verify encoded ones. It supports multiple hashing algorithms, ensuring that passwords are stored securely rather than in plain text.
Spring Security provides several PasswordEncoder implementations based on popular hashing algorithms:
BCryptPasswordEncoder β bcryptPbkdf2PasswordEncoder β PBKDF2SCryptPasswordEncoder β scryptArgon2PasswordEncoder β Argon2π§© **BCryptPasswordEncoder**
BCryptPasswordEncoder is the most commonly used implementation for hashing passwords with the bcrypt algorithm.10 in Spring Security). Higher values increase security but also processing time.@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
This ensures that passwords are hashed securely before being stored and can be safely verified during authentication.
AuthenticationEntryPoint in Spring Security decides what to do when someone tries to access a secured resource without being logged in.
AuthenticationEntryPoint is important to
How it works:
When Spring Security detects an unauthenticated request to a protected resource, it calls the AuthenticationEntryPoint to handle it β either by redirecting, sending an error, or running custom logic.
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"message\": \"Please log in to access this resource.\"}");
}
}
Configuration:
@Configuration
public class SpringSecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.httpBasic();
return http.build();
}
}