根据规范,只要client_id
包含在请求和 client_id
中,就不需要对使用授权代码授权的令牌进行身份验证}与用于生成代码的那个相同。但是,使用Spring Security OAuth 2.0实现,即使客户端从未被分配秘密,似乎始终需要/oauth/token
端点上的基本身份验证。
由于isSecretRequired()
接口中的ClientDetails
方法,似乎支持允许没有机密的客户端。我需要做些什么才能在没有秘密的情况下通过/oauth/token
URL验证客户端?
4.1.3。访问令牌请求
客户端通过发送
向令牌端点发出请求 以下参数使用" application / x-www-form-urlencoded"
格式为附录B,HTTP中的字符编码为UTF-8 请求entity-body:grant_type 需要。值必须设置为" authorization_code"。
代码 需要。从中收到的授权码 授权服务器。
REDIRECT_URI 需要,如果" redirect_uri"参数包含在 第4.1.1节中描述的授权请求及其 值必须相同。
CLIENT_ID 如果客户端未通过身份验证,则需要 授权服务器,如第3.2.1节中所述。
如果客户端类型是机密或客户端是客户端 凭证(或指定的其他认证要求),
客户端必须按授权服务器进行身份验证,如上所述 在第3.2.1节中。
答案 0 :(得分:6)
使用allowFormAuthenticationForClients()
方法启用使用表单参数而不是基本身份验证来验证客户端,如下面的代码示例所示。
class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
@Override
void configure(AuthorizationServerSecurityConfigurer security) {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients()
}
}
allowFormAuthenticationForClients()
方法触发添加ClientCredentialsTokenEndpointFilter
,允许通过表单参数进行身份验证。
答案 1 :(得分:4)
Spring允许您使用空密钥定义OAuth2客户端。 这些可以被视为" public"客户或无法保密的客户。想想Javascript应用程序,移动应用程序,.....你通常不希望存储客户机密。
正如您所指出的,根据OAuth2规范,令牌端点可以选择不要求这些公共客户端的秘密。
所以在Spring中,只需定义一个空密钥的OAuth2客户端,并为一组有限的授权类型(authorization_code和refresh_token)配置它
Spring Security实现令牌url将接受令牌交换而没有该特定OAuth2客户端的客户端密钥。
答案 2 :(得分:0)
最初,我对接受的答案进行了类似的设置,这绝对是完成此工作的前提。但是缺少的是您不能简单地将密码设置为null。您必须将其设置为空密码,例如:
String secret = PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("");
clientDetails.setClientSecret(secret);
如果您不这样做,您仍然会得到401!
答案 3 :(得分:0)
要解决此问题,请参见类loadUserByUsername
的方法org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
:
if (clientSecret == null || clientSecret.trim().length() == 0) {
clientSecret = this.emptyPassword;
}
在您的情况下,emptyPassword
可能尚未由密码编码器使用空的编码密码初始化。
在AuthorizationServerConfigurerAdapter
中设置缺少的密码编码器:
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(passwordEncoder);
}
答案 4 :(得分:0)
这对我有用
@Override
public void configure(AuthorizationServerSecurityConfigurer cfg) throws Exception {
cfg
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients()
.passwordEncoder(clientPasswordEncoder());
}
@Bean("clientPasswordEncoder")
PasswordEncoder clientPasswordEncoder() {
return new BCryptPasswordEncoder(4);
}
答案 5 :(得分:-1)
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client").secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("")) //empty
.authorizedGrantTypes("authorization_code", "refresh_token")
.redirectUris("http://www.dev.com")
.scopes("all")
.autoApprove(true);
} @Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
没关系。