5
votes

I'm using spring security with OAuth2 (version: 4.0.4.RELEASE) and spring (verison: 4.3.1.RELEASE).

I'm developing frontend in Angular and I'm using grunt connect:dev (http://127.0.0.1:9000). When I trying to login by localhost address everything working fine but from other I'm getting error:

"XMLHttpRequest cannot load http://localhost:8084/oauth/token?client_id=MY_CLIENT_ID. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:9000' is therefore not allowed access. The response had HTTP status code 401."

I have configured mapping (Overrided public void addCorsMappings(CorsRegistry registry)) in WebMvcConfigurerAdapter (like below) but it still not working for http://127.0.0.1:9000.

    registry.addMapping("/**")
            .allowedOrigins("http://127.0.0.1:9000")
            .allowedMethods("POST", "OPTIONS", "GET", "DELETE", "PUT")
            .allowedHeaders("X-Requested-With,Origin,Content-Type,Accept,Authorization")
            .allowCredentials(true).maxAge(3600);

Configuration based on: https://spring.io/guides/gs/rest-service-cors/

Please, point me the right directon to resolve this issue.

4
If I understand correctly you are trying to access from a different ip 127.0.0.1. (you are not in localhost anymore). But you are only permit access from localhost (127.0.0.1)Periklis Douvitsas
Periklis - yes I'm trying to access from different IP. I have permit access only from localhost:8084.Matt
Oleg Kurbatov - Thanks, I know this link but there is everything according and from documentation. I done everything like in docs but it still no working correctly. In my configuration I don't use web.xmlMatt
Haw about ordering filters? Any ideas?Matt

4 Answers

18
votes

Hopefully, you found an answer long ago, but if not (and if anyone else finds this question searching as I was):

The issue is that Spring Security operates using filters and those filters generally have precedence over user defined filters, @CrossOrigin and similar annotations, etc.

What worked for me was to define the CORS filter as a bean with highest precedence, as suggested here.

@Configuration
public class MyConfiguration {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://127.0.0.1:9000");
        config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
        config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}
1
votes

Sorry for long time response. I resolved the issue by configuring my CORS filter like below:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {

    private static final Logger LOGGER = LogManager.getLogger(CORSFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;
        final String origin = ((HttpServletRequest) req).getHeader("Origin");

        if (ofNullable(origin).isPresent() && origin.equals("http://127.0.0.1:9000")) {
            LOGGER.info("CORSFilter run");
            response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:9000");
            response.addHeader("Access-Control-Allow-Credentials", "true");

            if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
                response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization");
                response.setStatus(200);
            }
        }
        chain.doFilter(addNessesaryHeaders(request), response);
    }


    private MutableHttpServletRequest addNessesaryHeaders(final HttpServletRequest request) {
        final MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(request);
        mutableRequest.putHeader("Accept", "application/json");
        mutableRequest.putHeader("Authorization", "Basic" + " bXVzaWNzY2hvb2w6");
        return mutableRequest;
    }

    @Override
    public void destroy() {
    }
}
0
votes

You can try something like that

@Configuration
public class CorsConfig {
   @Bean
   public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
          @Override
          public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedMethods(HttpMethod.OPTIONS.name(),
                            HttpMethod.PATCH.name(),
                            HttpMethod.PUT.name(),
                            HttpMethod.DELETE.name(),
                            HttpMethod.GET.name(),
                            HttpMethod.POST.name())
                    .maxAge(360);
            }
       };
   }
}

Note: Spring version should be 4.2 or later

0
votes

below worked for me.

  import org.springframework.context.annotation.Configuration;
  import org.springframework.web.servlet.config.annotation.CorsRegistry;
  import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

  @Configuration
  @EnableWebMvc
  public class MvcConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");     
  }
}