Search code examples
springspring-bootspring-security

Spring Security: Applying a SecurityConfigurer and performing further customizations in the SecurityFilterChain


I have a Spring Boot project and am trying to do the following three things at the same time:

  1. Disable CSRF protection as described here (This application is not meant to be accessed via a browser, so this is my approach for handling Spring Security's default CSRF protection for non-GET endpoints)

  2. Apply a SecurityConfigurer as described here, in the "Spring Cloud Azure 5.X" tab

  3. Follow the new lambda format (which I'm not sure is even possible for applying a SecurityConfigurer, despite the SecurityConfigurerAdapter.and() method being deprecated for this reason)

Right now I have the following SecurityFilterChain method:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .apply(AadResourceServerHttpSecurityConfigurer.aadResourceServer())
            .and()
        .authorizeHttpRequests(authorizeHttpRequests -> 
            authorizeHttpRequests
                .anyRequest()
                .authenticated())
        .csrf(csrf -> csrf.disable());
    return http.build();
}

This is getting me the desired functionality from applying the SecurityConfigurer (as it can properly use the @PreAuthorize annotation to check against authorities on Azure apps/users/etc), but it looks like it's not properly disabling CSRF, because I'm getting a 401 error on any non-GET endpoint when calling from Postman.

What's the proper way to perform further customizations after applying a SecurityConfigurer, and is it possible to do this while also following the new lambda format?

EDIT: I have figured out a workaround for my original situation but am leaving the question up in case anyone can answer this for theoretical purposes. In this specific situation, the MS-supplied configurer already disables CSRF protection for OAuth2-authorized requests, which makes the task of globally disabling CSRF protection kind of irrelevant, since all non-GET endpoints should be OAuth2-authorized anyway. I ran into this issue when building this app because I was trying to leave the OAuth2 authorization out for the time being while I was experimenting.

So if anyone's specifically trying to implement this MS configurer and running into CSRF issues: Just don't bother including the custom SecurityFilterChain, and make sure all your non-GET endpoints are OAuth2-authorized anyway.

EDIT 2: Updating this again because I've found the answer to my original question of how to do all of these things in the lambda format. The key bit I was missing was that apply() is no longer the proper method for applying a security configurer; it's now with(). So the correct way to do what I was originally hoping for is:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .with(AadResourceServerHttpSecurityConfigurer.aadResourceServer(), Customizer.withDefaults())
        .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
        .csrf(csrf -> csrf.disable());
    return http.build();
}

Solution

  • Edited the original question to include the solution I found - In short, the apply() method does not have a lambda version, but the with() method does, and that's what should be used here.