spring-security icon indicating copy to clipboard operation
spring-security copied to clipboard

CorsConfigurationSource seems makes no effect

Open chuklov opened this issue 11 months ago • 0 comments

Describe the bug I am working on a small project to have a 'gateway' application in between Landing page and Backend API servers. Following the admin guide of Spring boot 3.2.0 that I'm currently using in my project I have created the following class for the security filter:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
 
@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        LOGGER.info("<================   securityFilterChain =================>");

        http
//       NO DIFFERENCE         .cors(Customizer.withDefaults())
//       NO DIFFERENCE          .cors((cors) -> cors
//       NO DIFFERENCE                  .configurationSource(corsConfigurationSource()))
//       NO DIFFERENCE                 .cors(cors -> cors.configurationSource(request -> {
//                            CorsConfiguration configuration = new CorsConfiguration();
//                            configuration.setAllowedOrigins(Arrays.asList(landing, gateway, php));
//                            configuration.addAllowedHeader("Authorization, Origin, X-Requested-With, Content-Type, Accept, cache-control");
                            configuration.addAllowedMethod("HEAD, GET, PUT, POST, OPTIONS");
                            configuration.addExposedHeader("Authorization, Cache-Control");
                            configuration.setAllowCredentials(true);
                            return configuration;

                }))

                .addFilterBefore(corsFilter(), CorsFilter.class)
                .authorizeRequests(authorize -> authorize
                        .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        .requestMatchers("/info/**").permitAll()
                        .requestMatchers("/register/**").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oAuth -> oAuth.jwt(jwt -> {
                    jwt.decoder(jwtDecoder());
                    jwt.jwtAuthenticationConverter(jwtAuthConverter);
                }))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .httpBasic(Customizer.withDefaults())
                .formLogin(Customizer.withDefaults())
                .csrf(Customizer.withDefaults())
                ;

        return http.build();
    }

    @Bean
    public CorsFilter corsFilter() {
        CorsFilter corsFilter = new CorsFilter(corsConfigurationSource());
        return corsFilter;
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        LOGGER.info("<================  CORS config load =================>");

        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(landing, gateway, php));
        configuration.addAllowedHeader("Authorization, Origin, X-Requested-With, Content-Type, Accept, cache-control");
        configuration.addAllowedMethod("HEAD, GET, PUT, POST, OPTIONS");
        configuration.addExposedHeader("Authorization, Cache-Control");
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }
}

Commented-out lines make no difference to the errors I'm having with this setup.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://gateway/. host.com/biosamples/storage/count. (Reason: CORS header 'Access-Control-Allow-Origin' missing). Status code: 403.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://gateway/. host.com/api/v0.0.3/visits/count. (Reason: CORS header 'Access-Control-Allow-Origin' missing). Status code: 403.

To Reproduce I cannot share any of my projects but my Gateway is a Spring boot Java application, my Landing server is React.js and my backends API servers are PHP. So without GW in between everything works fine, Gateway itself can call API and get the data from backend over Poastman, however, the Landing page is unable to get anything but login functionality.

Expected behavior As the config shows that the AllowedOrigins is provided, however on the errors we see that it isn't.

But if I will add this lines to the HTTP config: http.headers(header -> header.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", landing)));

Then the error changed to: CORS Missing Allow Credentials

Furthermore, if I add http.headers(header -> header.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))); then the error is: CORS PreFlight is not Allowed

In the config and documentation is clearly states that it should allow preflight and Allowed Origin, but it is not.

I would like to have some explanations on this one as it seems that either the documentation is incorrect or the CorsConfigurationSource doesn't work the way it should.

Thanks

chuklov avatar Mar 18 '24 15:03 chuklov