Spring OAuth2是否允许使用非密码或自定义凭据进行授权?

Spring OAuth2是否允许使用非密码或自定义凭据进行授权?,spring,security,oauth-2.0,spring-security-oauth2,Spring,Security,Oauth 2.0,Spring Security Oauth2,我正在使用SpringSecurityOAuth2。客户端应用程序(我们自己的)发出“密码”授权请求,该请求传递用户的用户名和密码。就像草案规定的那样 我需要这个机制来支持其他类型的凭证,比如卡号、PIN,甚至是预认证的、不需要授权的密码 请记住,这些请求将仅由特权客户端id允许,该id将仅从我们拥有的应用程序中使用。规范不明确允许客户端和身份验证服务器之间直接、非基于密码的用户令牌交换。我认为将密码授权扩展到其他形式的身份验证是很自然的。这是在规范的精神,如果不是字面上,所以如果你拥有双方的关

我正在使用SpringSecurityOAuth2。客户端应用程序(我们自己的)发出“密码”授权请求,该请求传递用户的用户名和密码。就像草案规定的那样

我需要这个机制来支持其他类型的凭证,比如卡号、PIN,甚至是预认证的、不需要授权的密码


请记住,这些请求将仅由特权客户端id允许,该id将仅从我们拥有的应用程序中使用。

规范不明确允许客户端和身份验证服务器之间直接、非基于密码的用户令牌交换。我认为将密码授权扩展到其他形式的身份验证是很自然的。这是在规范的精神,如果不是字面上,所以如果你拥有双方的关系,没有太多的错。SpringOAuth并不明确支持以这种方式扩展密码授权的任何内容,但这并不难做到(实际上只是关于/token端点的安全性)。我见过的另一种方法是坚持使用密码授予协议,但要使“密码”成为一次性令牌,客户端只有在知道用户已通过其中一种方法进行身份验证后才能获得该令牌。

Dave,感谢您的快速响应。我真的找到了完美的解决方案,你也参与了。它与“自定义授权”令牌授权人有关

如果我更新了我相当旧的1.0.0.M5版本,我可能已经知道了这些

我的方法是用一个支持自定义授权类型(我称之为“studentCard”)的类扩展
AbstractTokenGranter
。一旦身份验证请求出现在这里,我会像检查
ResourceOwnerPasswordTokenGranter
一样检查参数列表,而是查找我的自定义“cardNumber”参数。然后,我将自己的、基于id的
UsernamePasswordAuthenticationToken
版本传递给我的AuthenticationProvider,它知道如何基于id卡对用户进行身份验证

下面是我提出的自定义令牌granter类:

public class StudentCardTokenGranter extends AbstractTokenGranter {
    private static final String         GRANT_TYPE = "studentCard";

    private final AuthenticationManager authenticationManager;

    public StudentCardTokenGranter(AuthenticationManager authenticationManager,
        AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) {
    super(tokenServices, clientDetailsService, GRANT_TYPE);
    this.authenticationManager = authenticationManager;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) {

    Map<String, String> parameters = clientToken.getAuthorizationParameters();
    String cardNumber = parameters.get("cardNumber");

    Authentication userAuth = new StudentCardAuthenticationToken(cardNumber);
    try {
        userAuth = authenticationManager.authenticate(userAuth);
    } catch (BadCredentialsException e) {
        // If the username/password are wrong the spec says we should send 400/bad grant
        throw new InvalidGrantException(e.getMessage());
    }
    if (userAuth == null || !userAuth.isAuthenticated()) {
        throw new InvalidGrantException("Could not authenticate student: " + cardNumber);
    }

    return new OAuth2Authentication(clientToken, userAuth);
    }
}
公共类StudentCardTokenGranter扩展了AbstractTokenGranter{
私有静态最终字符串GRANT_TYPE=“studentCard”;
私人最终身份验证经理AuthenticationManager;
公共学生卡TokenGranter(AuthenticationManager AuthenticationManager,
授权服务器令牌服务令牌服务,客户端详细信息服务客户端详细信息服务){
超级(令牌服务、客户端详细信息服务、授权类型);
this.authenticationManager=authenticationManager;
}
@凌驾
受保护的OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken){
映射参数=clientToken.getAuthorizationParameters();
字符串cardname=parameters.get(“cardname”);
Authentication userAuth=新的StudentCardAuthenticationToken(cardNumber);
试一试{
userAuth=authenticationManager.authenticate(userAuth);
}捕获(BadCredentialsException e){
//如果用户名/密码错误,规范会说我们应该发送400/错误授权
抛出新的InvalidGrantException(例如getMessage());
}
如果(userAuth==null | |!userAuth.isAuthenticated()){
抛出新的InvalidGrantException(“无法验证学生:+cardNumber”);
}
返回新的OAuth2Authentication(clientToken、userAuth);
}
}
和我的授权服务器配置:

<!-- Issues tokens for both client and client/user authorization requests -->
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:refresh-token />
    <oauth:client-credentials />
    <oauth:password authentication-manager-ref="myUserManager" />
    <oauth:custom-grant token-granter-ref="studentCardGranter" />
</oauth:authorization-server>
<bean id="studentCardGranter" class="com.api.security.StudentCardTokenGranter">
    <constructor-arg name="authenticationManager" ref="myUserManager" />
    <constructor-arg name="tokenServices" ref="tokenServices" />
    <constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>


考虑到您的第一句话:“客户端凭据授予”是为了启用预授权客户端而创建的。这不正是实现这一点吗?不是针对用户令牌(不是规范中的术语,而是我觉得有用的术语)。客户端凭据授予不会产生绑定到特定用户的令牌。您是对的,此类绑定不在规范的范围内。但如果需要的话,这可以通过对场景的最小扩展来实现。我也在寻找类似的东西。但是
AbstractTokenGranter
的构造函数中有4个参数,因此
super
调用在上面的示例中显示了编译错误。我在这里找到了查询的解决方案。