是否可以在没有客户端机密的情况下从 Spring OAuth2 服务器获取 access_token?

Ang*_*ket 5 spring oauth spring-security spring-security-oauth2

我正在使用 Spring Security 的 OAuth2 服务器实现。我正在尝试/oauth/token使用 OAuth2“密码”授权类型从服务器的端点获取 access_token,方法是仅提供用户名和密码以及客户端 ID,而不提供客户端密码。只要我在AuthorizationHTTP 请求的标头中提供客户端 ID 和客户端密钥,这就可以正常工作,如下所示:

curl -u clientid:clientsecret http://myhost ... -d "grant_type=password&username=user&password=pw&client_id=OAUTH_CLIENT"
Run Code Online (Sandbox Code Playgroud)

遵循此处的建议:Spring OAuth2 disable HTTP Basic Auth for TokenEndpoint,我设法禁用了/auth/token端点的HTTP Basic 身份验证。但是当我尝试通过 cURL 获取 access_token 时:

curl http://myhost ... -d "grant_type=password&username=user&password=pw&client_id=OAUTH_CLIENT"
Run Code Online (Sandbox Code Playgroud)

我得到了一个BadCredentialsException并且可以看到消息:

身份验证失败:密码与存储值不匹配

在我的服务器日志中。在这一点上,我有点恼火,因为我的理解是,只有在用户名和/或密码有问题时才会显示此消息,而不是客户端 ID 和/或密码有问题。在 cURL 命令中额外提供客户端密码后,如下所示:

 curl http://myhost ... -d "grant_type=password&username=user&password=pw&client_id=OAUTH_CLIENT&client_secret=SECRET"
Run Code Online (Sandbox Code Playgroud)

一切又好了。

那么这是否意味着我必须以一种或另一种方式提供客户端机密才能访问/auth/token端点?

PS:我知道这样一个事实,关于安全性,通过 HTTP 基本身份验证保护此端点通常是一个好主意,但在某些用例中,人们宁愿不这样做。

编辑:

我似乎找到了一种省略客户端机密的方法。这是我的 OAuth2 服务器配置(注意对allowFormAuthenticationForClients()和的调用autoApprove(true)):

@Configuration
@EnableAuthorizationServer
class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    private final AuthenticationManager authenticationManager;

    public OAuth2Config(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

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

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauth) throws Exception {
        // allows access of /auth/token endpoint without HTTP Basic authentication
        oauth.allowFormAuthenticationForClients();  
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
        .inMemory()
        .withClient("acme")
        .autoApprove(true) // <- allows for client id only
        .authorizedGrantTypes("authorization_code", "refresh_token", "password").scopes("openid");
    }

}
Run Code Online (Sandbox Code Playgroud)

编辑二:

这里的问题:Spring Security OAuth 2.0 - 授权代码授予始终需要的客户端机密与此密切相关,但处理 OAuth2 授权类型“授权代码”,这会导致与您使用授权类型获得的工作流程不同的工作流程“密码”。

Tak*_*aki 5

根据规范 (RFC 6749),如果您的应用程序的客户端类型是public,则不需要客户端机密。相反,如果客户类型是保密的,需要客户端机密。

如果 Spring 提供 API 来设置客户端类型,请尝试将客户端类型设置为public