Skip to main content

6.2 Modern Security Configuration

← Back to Chapter 6: Spring Security & Authentication

In Spring Boot 3 and Spring Security 6, WebSecurityConfigurerAdapter is completely removed. Configuration is now entirely component-based, using functional Lambda DSL.


1. Component-Based SecurityFilterChain​

Modern security configuration defines a @Bean returning SecurityFilterChain:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity // Activates @PreAuthorize and @Secured
public class SecurityConfig {

private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;

public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter,
AuthenticationProvider authenticationProvider) {
this.jwtAuthFilter = jwtAuthFilter;
this.authenticationProvider = authenticationProvider;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
// 1. Disable CSRF for stateless REST APIs
.csrf(AbstractHttpConfigurer::disable)

// 2. Configure CORS
.cors(cors -> cors.configurationSource(corsConfigurationSource()))

// 3. Stateless Session Management (No HttpSession)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)

// 4. Authorization Rules
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/api/v1/auth/**",
"/actuator/health",
"/swagger-ui/**",
"/v3/api-docs/**"
).permitAll()
.requestMatchers(HttpMethod.GET, "/api/v1/products/**").permitAll()
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)

// 5. Wire AuthenticationProvider and JWT Filter
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)

.build();
}
}

2. CORS (Cross-Origin Resource Sharing)​

Frontends running on http://localhost:3000 calling backends on http://localhost:8080 are blocked by browser same-origin policy without CORS:

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:3000", "https://codewithsarvy.dev"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type", "X-Correlation-Id"));
config.setAllowCredentials(true);
config.setMaxAge(3600L);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}

3. Why Disable CSRF in Stateless REST APIs?​

Cross-Site Request Forgery (CSRF) relies on browsers automatically appending session cookies on cross-origin requests. Since stateless REST APIs authenticate via the Authorization: Bearer <token> header (which browsers never attach automatically), CSRF attacks are impossible, making CSRF tokens unnecessary overhead.