简体   繁体   中英

Why am I getting 401 for authorization request when authorize with OAuth2 Server sent from localhost but works fine using Postman

I'm setting up an React and SpringBoot application, for Security method I am implementing OAuth2 with below configurations. I tested the Authorization endpoint "http:localhost:8080/oauth/token" along with the Client_id, Client_secret, user Credentials for the generated token on Postman, everything works just fine, I got back the token. However, when I tried to do the same action on the ReactJS server, I've always got the 401 Unauthorized Response, in addition, I've disable the CORS in my Spring Server (for testing purpose), eventually, I've been receiving the message

Access to fetch at ' http://localhost:8080/oauth/token ' from origin' http://localhost:3000 ' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

Here is my AuthorizationServerConfig

    @Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends 
AuthorizationServerConfigurerAdapter {

    @Autowired
    private CustomAuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // TODO Auto-generated method stub
        endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // TODO Auto-generated method stub
        clients
            .inMemory().withClient("client-id")
            .secret(new BCryptPasswordEncoder().encode("secret"))
            .scopes("resource:read")
            .authorizedGrantTypes("password");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // TODO Auto-generated method stub
        security
            .checkTokenAccess("isAuthenticated()")
            .passwordEncoder(new BCryptPasswordEncoder());
    }
}

Here is my ResourceServerConfig

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // TODO Auto-generated method stub
            http.cors().disable().csrf().disable()
                .authorizeRequests()
                    .antMatchers("/oauth/**").permitAll()
                    .anyRequest().authenticated();
        }
    }  

Overrided method in the effort to make sure CORS is disabled in the WebMvcConfigurer implemented class

@Override
public void addCorsMappings(CorsRegistry registry)  {
registry.addMapping("/**").allowedMethods("*").allowedHeaders("*").allowedOrigins("http://localhost:3000");
}

my React (client side) code

let form = new FormData();

form.append("grant_type", "password");
form.append("username", "myusername");
form.append("password", "mypassword");

let code = new Buffer("client-id:secret").toString('base64');

console.log(code); // gives the same string as appeared in Postman code snippets

fetch("http://localhost:8080/oauth/token", {
    method: "POST",
    mode: "no-cors", // even if I remove this or change it to 'cors', result was still the same but 
    // (but I want cors enabled when I've successfully test out this authorize method)
    headers: {
         "Authorization" : "Basic " + code
    },
    body: form
})
.then(
    res => console.log(res)
)

Any help would be appreciated. Thank you.

The browser is blocking your request as it usually allows a request in the same origin for security reasons. You can either ask the person maintaining the server to add your hostname to Access-Control-Allow-Origin hosts, the server should return a header similar to the following with the response:

Access-Control-Allow-Origin: yourhostname:port

Or you can simply disable the Same-origin policy on your browser. If it's chrome and you're using a linux, open terminal and run:

$ google-chrome --disable-web-security

In case you're using OSX:

$ open -a Google\ Chrome --args --disable-web-security --user-data-dir

or Windows go into the command prompt and go into the folder where Chrome.exe is and type:

chrome.exe --disable-web-security

so I've made some research on the CORS problem because I was thinking that OAuth might actually not following my CORS configuration and implement it's own policy. I found this question and the most upvoted answer solved my problem

https://stackoverflow.com/a/44819743/10264578

If anyone came across this issue like me, all you have to do is create the filter as given in the answer and then configure that filter into the Spring Security FilterChain like so

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Autowired
private CorsFilter filter;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // TODO Auto-generated method stub
        http.csrf().disable()
            .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                .anyRequest().authenticated();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM