2
votes

I develop an angular app with a spring webflux backend. Up so far, the CorsFilter worked fine and allowed requests from the frontend.

Then I added a SecurityConfig. Since then the CorsFilter stopped working and I get an exception in the angular app:

Access to XMLHttpRequest at 'http://localhost:8080/users/999/folders/%2F/media/' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

This filter worked fine:

@Configuration
public class CorsFilter {

    private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
    private static final String FRONTEND_STAGING = "https://somehost.github.io";

    @Bean
    CorsWebFilter corsWebFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.applyPermitDefaultValues();
        corsConfig.addAllowedMethod(HttpMethod.PUT);
        corsConfig.addAllowedMethod(HttpMethod.DELETE);
        corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));

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

        return new CorsWebFilter(source);
    }
}

Then I added authorization (bearer token) with following SecurityConfig:

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http.cors().and().csrf()
            .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .authorizeExchange()
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
        return http.build();
    }

It seems with the security config my CorsFilter is not taken into account anymore. I red that the corsfilter needs to be added explicity in the config, but the examples I found didnt work. I hope somebody can help and knows why.

EDIT: To address the duplication concerns: I already tried adding cors() and cors().configurationSource(corsConfig()) into my security config, but didnt helped either.

2
Thanks for your continued help :), I've been already through that. I found a solution now. Will post as answer.Joker
Its an old question but it was the only answer that worked for me. It is also not a duplicate @jww as the configuration in your link is for non-reactive java while this question and answer are about reactive java.Simas Joneliunas

2 Answers

10
votes

I found a working way in Enable CORS in Spring 5 Webflux? by implementing a custom corsfilter.

However I still wasnt happy with the solution as it looked quite like a workaround.

Finally I found the culprit(s)... one is quite embarassing. My posted SecurityConfig was in the wrong package (it was in the default package by accident) and for this reason the config didnt picked up.

Also the cors filter from the question started working when I pasted the code to the securityconfig.

So my final SecurityConfig looks like this:

import java.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {

    private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
    private static final String FRONTEND_STAGING = "https://somehost.github.io";

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http
                .csrf()
                .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
    }


    @Bean
    CorsConfigurationSource corsConfiguration() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.applyPermitDefaultValues();
        corsConfig.addAllowedMethod(HttpMethod.PUT);
        corsConfig.addAllowedMethod(HttpMethod.DELETE);
        corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));

        UrlBasedCorsConfigurationSource source =
                new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);
        return source;
    }
}
-1
votes

try add this config

corsConfig.setAllowCredentials(true);