CORS: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status

Asked

Viewed 3,730 times

2

I can get the TOKEN of my application by using Postman as follows.

This works perfectly, and return me the Token. inserir a descrição da imagem aqui

However when I try to make the same request, using Axios, in my application with Vue@cli I get the following error:

inserir a descrição da imagem aqui

I’m mounting the Axios requisition this way:

   axios({
        url: '/oauth/token',
        method: 'post',
        baseURL: 'http://prog06:8080',
        headers: { 'Authorization': 'Basic bWFzdGVyOjEyMzQ1', 'Content-Type': 'application/x-www-form-urlencoded', 'scope': 'password', },
          data: {
            username: 'user1',
            password: 'user1'
          }
      }).then(result => {
        console.log(result)
      })

Configurações

Basic I’m passing the following amount master:12345 in Base64.

data I’m passing the username and password of the user.

Back-end is in Java Spring Boot:

pom.xml

<dependencies>

        <!-- Segurança | Início -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>       

        <!-- Segurança | Fim -->

Securityconfig.java

//Edit02

package com.mfac.config;


import java.util.Arrays;
import java.util.Collections;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;



@EnableWebSecurity
@EnableAuthorizationServer
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@CrossOrigin
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
        .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .anyRequest().authenticated()
            .and()
                .httpBasic()
            .and()
                .csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

     @Bean
     CorsConfigurationSource corsConfigurationSource(){
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Collections.singletonList("*"));
            configuration.setAllowedMethods(Arrays.asList("GET","POST"));
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }
}


How can I fix this problem ? because the request to oauth/token by Postman works, now with Axios returns me the CORS error quoted above.

2 answers

3

You have to release CORS on the server, there is a policy/configuration in browsers that when you go to make a request first sends an OPTIONS to the server to know what is released, in Postman this does not work in it and not in browsers, as you have not configured any release occurs this ai console error, to release it has N modes:

From what I’ve seen of your pom will be that the easiest way to implement

Spring Security:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
            //other config
    }
 //Adicionar esse Bean no na sua classe WebSecurityConfigurerAdapter e configurar o que você quer liberar
    @Bean
    CorsConfigurationSource corsConfigurationSource(){
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

In each class/controller:

@CrossOrigin(origins = "*", allowedHeaders = "*")
@Controller
public class HomeController{
    @GetMapping(path="/")
    public String homeInit(Model model) {
        return "home";
    }
}

In a specific method:

@Controller
public class HomeController{
    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @GetMapping(path="/")
    public String homeInit(Model model) {
        return "home";
    }
}

Over writing in the method:

@Controller
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class HomeController{
    @CrossOrigin(origins = "http://example.com")
    @GetMapping(path="/")
    public String homeInit(Model model) {
        return "home";
    }
}

Globally with Webmvcconfiguraeradapter:

@Configuration
@EnableWebMvc
public class CorsConfiguration extends WebMvcConfigurerAdapter{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("GET", "POST");
    }
}

Globally with Webmvcconfigurer:

@Configuration
public class CorsConfiguration{
    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**");
            }
        };
    }
}

Using a filter

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

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

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN, ");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, resp);
        }

    }

    @Override
    public void destroy() {
    }
}

Withdrawn and adapted from: https://howtodoinjava.com/spring5/webmvc/spring-mvc-cors-configuration/

  • I made the changes, but I still have the same mistake. But I do not know if I did it correctly, because I had doubts, what to put here configuration.setAllowedOrigins(Arrays.asList("http://prog05:8080")); in the pro05 case is the machine being requested by the Front End using the Axios

  • When I deal with these things I usually release everything and close the few, it seems easier so, so I would put Configuration.setAllowedOrigins(Collections.singletonList("*")); but if you want to release only that pc if I’m not mistaken it has to be so Configuration.setAllowedOrigins(Arrays.asList("http://prog05","http://www.prog05"))

  • I made the change in the code as suggested and updated the question to release everything only for testing, however I am getting exactly the same error. Have some possibility of being mounted incorrectly the request in Axios ?

  • It is not a problem with Xios, nor is it still arriving in your call, if you open the Developer tools and see the network tab you will see that first the browser makes a call OPTIONS to see what has released, and only then makes your call, in case is giving problem in the options. I saw it now in my application and has a filter that treats Cors, try to add it in your application

  • I put Filter but it still didn’t work, what I find funny is that if I leave these two annotations Enableresourceserver Enableauthorizationserver. the Server returns me 401 OPTIONS and if you remove them return me OPTIONS 404. In the SPRING documentation link https://www.baeldung.com/spring-security-cors-preflight is informed that if you use ** http.Cors();*? SPRING would use a OPTIONS-ready solution, then I doubt, when I use the annotations Enableresourceserver and Enableauthorizationserver it overwrites http.Cors settings ?

0

As I replied in more detail in this answer for @Dup, I believe that setting the filter is unnecessary, since Spring Boot already provides resources to handle CORS.

To perform the change of headers, this can be done using the following configuration:

@Configuration
public class CorsConfig {
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("*"));
        config.setAllowedMethods(Arrays.asList("*"));
        config.setAllowCredentials(true);
        config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));

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

        return configSource;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.