How to configure CORS and Basic Authorization in Spring Boot?

13,872

Solution 1

I think you need to allow OPTION requests into your web security config. Something like:

.antMatchers(HttpMethod.OPTIONS, "/your-url").permitAll()

Solution 2

The browser checks CORS settings via a request with OPTIONS header. And if you've configured authorization, OPTIONS request will be blocked as unauthorized.

You can simply allow OPTIONS request via cors support in WebConfigurerAdapter.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ...
        http.cors();
    }
}

Check this link for more info: https://www.baeldung.com/spring-security-cors-preflight

Solution 3

Try this:

@Configuration
public class CorsConfig {

  @Bean
  public CorsFilter corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(false); //updated to false
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
  }

  @Bean
  public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/").allowedOrigins("http://localhost:3000");
      }
    };
  }

}
Share:
13,872

Related videos on Youtube

Ferran Maylinch
Author by

Ferran Maylinch

Developer at Yandex, and sometimes a teacher.

Updated on June 04, 2022

Comments

  • Ferran Maylinch
    Ferran Maylinch almost 2 years

    I'm trying to configure CORS in a Spring boot application that already has Basic auth set up.

    I've searched in many places, including this answer, that points to Filter based CORS support in the official docs.

    So far no luck.

    My AJAX request is done this way. It works if done from same origin http://localhost:8080.

    fetch('http://localhost:8080/api/lists', {
      headers: {
        'Authorization': 'Basic dXNlckB0ZXN0LmNvbToxMjM0NQ=='
      }
    }
    

    The AJAX request is done from a React app at http://localhost:3000, so I tried the following Spring boot CORS config:

    @Configuration
    class MyConfiguration {
    
        @Bean
        public FilterRegistrationBean corsFilter()
        {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
            // Maybe I can just say "*" for methods and headers
            // I just copied these lists from another Dropwizard project
            config.setAllowedMethods(Arrays.asList("GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD"));
            config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept",
                "Authorization", "Access-Control-Allow-Credentials", "Access-Control-Allow-Headers", "Access-Control-Allow-Methods",
                "Access-Control-Allow-Origin", "Access-Control-Expose-Headers", "Access-Control-Max-Age",
                "Access-Control-Request-Headers", "Access-Control-Request-Method", "Age", "Allow", "Alternates",
                "Content-Range", "Content-Disposition", "Content-Description"));
            config.setAllowCredentials(true);
    
            source.registerCorsConfiguration("/**", config);
            FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
            bean.setOrder(0);
            return bean;
        }
    }
    

    My WebSecurityConfig:

    @Configuration
    class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http.httpBasic().and()
                .authorizeRequests()
                .antMatchers("/", "/index.html").permitAll()
                .anyRequest().fullyAuthenticated();
        }
    }
    

    The fetch call from http://localhost:3000 displays this 401 error in the console:

    Fetch API cannot load http://localhost:8080/api/lists. Response for preflight has invalid HTTP status code 401.

    enter image description here

    An in the network tab of chrome dev tools I see this OPTIONS request:

    enter image description here

  • Ferran Maylinch
    Ferran Maylinch over 7 years
    Thank you but same result... I've also added my config setting to your solution but nothing changes. I'm not using Spring MVC, but I included your WebMvcConfigurer too just in case.
  • Mike3355
    Mike3355 over 7 years
    Are you using Boot with Angular 2
  • Ferran Maylinch
    Ferran Maylinch over 7 years
    Why do you ask? I'm using React right now, to try it, but I'm planning to try Angular 2 too. Anyway, I'm calling the @RestController using the fetch function. I mean that no React components are involved in the call.
  • Ferran Maylinch
    Ferran Maylinch over 7 years
    Thanks! You were right! For now, just to see it works, I used .antMatchers(HttpMethod.OPTIONS, "/**").permitAll(). It works with my FilterRegistrationBean. Maybe it also works with the CorsFilter, but the problem was the OPTIONS call was being blocked.