spring-attic / spring-security-oauth

Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
http://github.com/spring-projects/spring-security-oauth
Apache License 2.0
4.69k stars 4.05k forks source link

OAuth 2 Autoconfiguration 401 Error for preflight request #1749

Open rolaca11 opened 4 years ago

rolaca11 commented 4 years ago

Summary

OAuth 2 Autoconfigurer doesn't take into account the preflight requests sent by browsers typically before requests with Authorization header.

Actual Behavior

The browser sends a request with method OPTIONS with some Access-Control-Allow-* headers. Even though the request has been set up for HTTP Basic authentication, this preflight request doesn't have this yet.

Because of this, Spring Security falsely responds with a 401 status and the message "access-denied"

Expected Behavior

The browser sends a request with method OPTIONS with some Access-Control-Allow-* headers. Even though the request has been set up for HTTP Basic authentication, this preflight request doesn't have this yet.

Spring Security realises that this is only a preflight request and responds with a status code of 200, allowing the browser to continue with the real request.

Configuration

The configuration comes from the org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure. More specifically, from class org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerSecurityConfiguration:89, where only the fullyAuthenticated option is passed and there is no exception set for when a preflight request arrives.

Version

The version is: org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.8.RELEASE

Sample

https://bitbucket.org/rolaca11/spring-security-sample/ In this project, the /rest/oauth/token resource should be queried.

I tried implementing a workaround, where I register a filter checking for preflight requests, which solves the immediate problem of these kinds of requests resulting in 401 Unauthorized status.

However, in order for it to have an effect, I need to set the highest precedence to the configuration bean. This, however, hijacks the request from the desired filter chain as well, resulting in all kinds of errors along the way, when the browser sends the real authentication request.

diegobmd commented 4 years ago

I had the same problem, I solve add a filter with high precedence, I tried add the "ignoring" to OPTIONS /oauth/token, but this make the TokenEndpoint call and return 401 too, even the token method annotated with POST

@Configuration
public class CorsConfig {
    @Bean
    public FilterRegistrationBean corsFilterRegistrationBean() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.applyPermitDefaultValues();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Collections.singletonList("*"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowedMethods(Collections.singletonList("*"));
        //config.setExposedHeaders(Arrays.asList("content-length"));
        config.setMaxAge(3600L);
        source.registerCorsConfiguration("/**", config);

        FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);

        return bean;
    }
}