2

I have checked a lot of resources trying to find the right solution for my problem. From my point of view I think I have everything I need in place but I cannot figure out where the problem is.

I am using spring 5 with WebFlux with functional endpoints

When I send the GET request from my vuejs frontend, I get this:

Failed to load http://localhost:8080/test: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access. The response had HTTP status code 401.

Here is the request:

OPTIONS /test HTTP/1.1 Host: localhost:8080 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Access-Control-Request-Method: GET Origin: http://localhost:8081 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Access-Control-Request-Headers: authorization Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,ro;q=0.8

My Spring security config

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(
      ServerHttpSecurity http) {
    return http
        .authorizeExchange()
        .pathMatchers("/users/authenticate").permitAll()
        .anyExchange()
        .authenticated()
        .and()
        .httpBasic()
        .and()
        .build();
  }

And I tried a few different methods, these are the last two ones:

1.

  private static final List<String> ALLOWED_HEADERS = Arrays.asList(
      "x-requested-with",
      "authorization",
      "Content-Type",
      "Authorization",
      "credential",
      "X-XSRF-TOKEN",
      "Access-Control-Allow-Origin",
      "Access-Control-Allow-Methods",
      "Access-Control-Allow-Headers",
      "Access-Control-Max-Age",
      "Access-Control-Request-Headers",
      "Access-Control-Request-Method");
  private static final List<String> ALLOWED_METHODS = Arrays.asList("GET", "PUT", "POST", "DELETE", "OPTIONS");
  private static final String ALLOWED_ORIGIN = "*";
  private static final String MAX_AGE = "3600";

  @Bean
  CorsWebFilter corsWebFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowedOrigins(Collections.singletonList(ALLOWED_ORIGIN));
    corsConfig.setMaxAge(Long.valueOf(MAX_AGE));
    corsConfig.setAllowedMethods(ALLOWED_METHODS);
    corsConfig.setAllowedHeaders(ALLOWED_HEADERS);

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

    return new CorsWebFilter(source);
  }

2.

@Configuration
public class WebFluxSecurity implements WebFluxConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {

    registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("*")
        .allowedHeaders("*")
        .exposedHeaders("Access-Control-Allow-Origin",
            "Access-Control-Allow-Methods",
            "Access-Control-Allow-Headers",
            "Access-Control-Max-Age",
            "Access-Control-Request-Headers",
            "Access-Control-Request-Method")
        .maxAge(3600);

    // Add more mappings...
  }
}

Why isn't this working?

tzortzik
  • 4,993
  • 9
  • 57
  • 88
  • 1
    The server appears to be requiring authentication for OPTIONS requests. It needs to be fixed to not require authentication for OPTIONS requests — because whatever frontend JavaScript code is sending the requests is causing the browser to first make a CORS preflight OPTIONS request, and browsers never include authentication credentials (e.g., the Authorization request header) in CORS preflight OPTIONS requests. – sideshowbarker Oct 07 '18 at 23:28
  • @sideshowbarker as you can see I already have the OPTIONS method added to the CORS configuration – tzortzik Oct 08 '18 at 07:57
  • Yeah, simply adding the OPTIONS method to the CORS configuration isn’t sufficient. If it were, the server wouldn’t be responding with a 401. Some other change outside the CORS configuration is also necessary. See for example the answer at https://stackoverflow.com/questions/30622624/oauth2-status-401-on-options-request-while-retrieving-token/30632995#30632995 – sideshowbarker Oct 08 '18 at 08:11

1 Answers1

5

It seems that the problem was not actually the cors configuration.

Meanwhile I have adopted something a bit different.

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(
      ServerHttpSecurity http) {
    return http
        .authorizeExchange()
        .pathMatchers(HttpMethod.OPTIONS).permitAll()
        .anyExchange()
        .authenticated()
        .and()
        .httpBasic()
        .and()
        .build();
  }

The problem was in the spring security configuration. I was only allowing all requests for on /users/authenticate instead of allowing all OPTIONS methods.

My current cors config is:

  @Bean
  CorsWebFilter corsFilter() {

    CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

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

    return new CorsWebFilter(source);
  }
tzortzik
  • 4,993
  • 9
  • 57
  • 88