Spring OAuth2 隐式流程 - 身份验证服务器不处理 POST /oauth/authorize 请求

Posted

技术标签:

【中文标题】Spring OAuth2 隐式流程 - 身份验证服务器不处理 POST /oauth/authorize 请求【英文标题】:Spring OAuth2 Implicit Flow - Auth server not processing the POST /oauth/authorize request 【发布时间】:2017-08-08 23:35:58 【问题描述】:

我有一个授权服务器 (http://localhost:8082)、资源服务器和隐式客户端 (http://localhost:8080) 项目。问题是当客户端请求授权(令牌)时,身份验证服务器显示登录屏幕,但在成功登录后它重定向到 GET http://localhost:8082/ 而不是 http://localhost:8082/authorize?client_id=...(根据客户端的要求)

我看到了这个日志:

隐式客户端:

.s.o.c.t.g.i.ImplicitAccessTokenProvider : Retrieving token from http://localhost:8082/oauth/authorize
o.s.web.client.RestTemplate              : Created POST request for "http://localhost:8082/oauth/authorize"
.s.o.c.t.g.i.ImplicitAccessTokenProvider : Encoding and sending form: response_type=[token], client_id=[themostuntrustedclientid], scope=[read_users write_users], redirect_uri=[http://localhost:8080/api/accessTokenExtractor]
o.s.web.client.RestTemplate              : POST request for "http://localhost:8082/oauth/authorize" resulted in 302 (null)
o.s.s.web.DefaultRedirectStrategy        : Redirecting to 'http://localhost:8082/login?client_id=themostuntrustedclientid&response_type=token&redirect_uri=http://localhost:8080/api/accessTokenExtractor'

认证服务器:

o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /oauth/authorize' doesn't match 'GET /**
o.s.s.w.util.matcher.AndRequestMatcher   : Did not match
o.s.s.w.s.HttpSessionRequestCache        : Request not saved as configured RequestMatcher did not match
o.s.s.w.a.ExceptionTranslationFilter     : Calling Authentication entry point.
o.s.s.web.DefaultRedirectStrategy        : Redirecting to 'http://localhost:8082/login'

隐式客户端正在为 /oauth/authorize 进行 POST,而不是 GET,并且 authserver 不存储 POST 请求。认证服务器返回一个重定向 302,隐式客户端将浏览器重定向到这个 url:http://localhost:8082/login?client_id=themostuntrustedclientid&response_type=token&redirect_uri=http://localhost:8080/api/accessTokenExtractor

成功登录后,auth 服务器没有目标 url,所以它显示http://localhost:8082/,所以它不处理任何 /oauth/authorize 请求...问题出在哪里?

授权服务器配置:

@Configuration
class OAuth2Config extends AuthorizationServerConfigurerAdapter

    @Autowired
    private AuthenticationManager authenticationManager

    @Bean
    public TokenStore tokenStore() 
        return new InMemoryTokenStore();
    

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
        clients.inMemory()
            .withClient("themostuntrustedclientid")
            .secret("themostuntrustedclientsecret")
            .authorizedGrantTypes("implicit")
            .authorities("ROLE_USER")
            .scopes("read_users", "write_users")
            .accessTokenValiditySeconds(60)     
    

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
        endpoints.authenticationManager(this.authenticationManager);
    

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception 
        //security.checkTokenAccess('hasRole("ROLE_RESOURCE_PROVIDER")')
        security.checkTokenAccess('isAuthenticated()')
    



@Configuration
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception 
        auth.inMemoryAuthentication().withUser("jose").password("mypassword").roles('USER').and()
                                     .withUser("themostuntrustedclientid").password("themostuntrustedclientsecret").roles('USER')
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
        .csrf()
            //
            //XXX Si se usa implicit descomentar
            .ignoringAntMatchers("/oauth/authorize")
            .and()
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        //.httpBasic()
        .formLogin()
            .loginPage("/login").permitAll()
    


隐式客户端配置:

@Configuration
class OAuth2Config 

    @Value('$oauth.authorize:http://localhost:8082/oauth/authorize')
    private String authorizeUrl

    @Value('$oauth.token:http://localhost:8082/oauth/token')
    private String tokenUrl

    @Autowired
    private OAuth2ClientContext oauth2Context

    @Bean
    OAuth2ProtectedResourceDetails resource() 
        ImplicitResourceDetails resource = new ImplicitResourceDetails()
        resource.setAuthenticationScheme(AuthenticationScheme.header)
        resource.setAccessTokenUri(authorizeUrl)
        resource.setUserAuthorizationUri(authorizeUrl);
        resource.setClientId("themostuntrustedclientid")
        resource.setClientSecret("themostuntrustedclientsecret")
        resource.setScope(['read_users', 'write_users'])
        resource
    

    @Bean
    OAuth2RestTemplate restTemplate() 
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resource(), oauth2Context)
        //restTemplate.setAuthenticator(new ApiConnectOAuth2RequestAuthenticator())
        restTemplate
    

@Configuration
class SecurityConfig extends WebSecurityConfigurerAdapter

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception 
        auth.eraseCredentials(false)
            .inMemoryAuthentication().withUser("jose").password("mypassword").roles('USER')
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
        .csrf()
            .ignoringAntMatchers("/accessTokenExtractor")
        .and()
        .authorizeRequests()
        .anyRequest().hasRole('USER')
        .and()
        .formLogin()
            .loginPage("/login").permitAll()
    


【问题讨论】:

【参考方案1】:

问题出在 Auth 服务器的 SecurityConfig 中。隐式客户端自动发送带有 client_id 和 client_secret 的基本授权标头。我的身份验证服务器配置为使用表单登录而不是基本身份验证。我改变了它,现在它可以按预期工作了:

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
    .csrf()
        //
        //XXX Si se usa implicit descomentar
        .ignoringAntMatchers("/oauth/authorize")
        .and()
    .authorizeRequests()
        .anyRequest().authenticated()
        .and()
    .httpBasic()

【讨论】:

以上是关于Spring OAuth2 隐式流程 - 身份验证服务器不处理 POST /oauth/authorize 请求的主要内容,如果未能解决你的问题,请参考以下文章

OAuth2 隐式流程 - IFrame 刷新身份

使用 Spring Security 实现 OAuth2 隐式授权

具有基本身份验证和自定义 UserDetailsS​​ervice 的 Spring Boot OAuth2

Spring oauth2令牌请求中未实际使用的基本身份验证过滤器和身份验证入口点

Spring Security OAuth2 AngularJS |注销流程

OAuth2“社交登录”流程(允许通过 Facebook/Twitter 进行 OAuth2 身份验证):是不是有任何示例/文献?