Reputation: 2473
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.
Upvotes: 4
Views: 7499
Reputation: 2473
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;
}
}
Upvotes: 13