2014-03-25 71 views
6

我使用Spring Security OAuth2。客户端应用程序(我们拥有的)发出一个“密码”授予请求,以传递用户的用户名和密码。就像草案所规定的一样。OAuth2是否允许使用非密码或自定义凭证进行授权?

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

请注意,这些请求只能通过特权client_id来获得,该特权只能从我们拥有的应用程序中使用。

回答

5

Dave,感谢您的快速响应。我居然找到了完美的解决方案,其中一个你的一部分。它与“定制批”令牌granters做... https://jira.spring.io/browse/SECOAUTH-347

如果我更新了我的很旧1.0.0.M5版本我早就知道关于那些。

我的方法是扩展AbstractTokenGranter一个支持自定义授权类型的类(我称之为“studentCard”)。一旦身份验证请求将其发送到此处,我将检查参数列表,如ResourceOwnerPasswordTokenGranter,但请查找我的自定义“cardNumber”参数。然后,我将我自己的,基于id的版本UsernamePasswordAuthenticationToken传递给我的AuthenticationProvider,该AuthenticationProvider知道如何基于身份证对用户进行身份验证。

这里是我想出了一个自定义的令牌授予者类:

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); 
    } 
} 

我的授权服务器的配置:

<!-- 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> 
+0

我也在寻找类似的东西。但'AbstractTokenGranter'在其构造函数中有4个参数,所以'super'调用在上例中显示编译错误。 –

+1

我在这里找到了解决方案,用于我的查询。 http://stackoverflow.com/questions/25264358/spring-security-oauth2-with-custom-tokengranter-in-version-2-0/25270572#25270572 –

2

该规范没有明确允许直接在客户端和auth服务器之间直接进行基于密码的用户令牌交换。我认为将口令授权扩展到其他形式的认证是非常自然的。如果不是这封信的话,它本着规范的精神,所以如果你拥有关系的双方,没有什么可以出错的。 Spring OAuth并没有明确地支持以这种方式扩展密码授权的任何东西,但它并不难(这实际上只是关于/ token端点的安全性)。我见过的另一种方法是坚持使用密码授权协议,但将“密码”作为一次性令牌,客户端只有通过了解用户使用其中一种替代方式进行身份验证后才能获得该令牌。

+0

考虑您的第一句话:“客户端凭证授予”创建启用预授权客户。这难道不是那么完美吗? –

+0

不适用于用户令牌(不是来自规范的术语,而是我认为有用的术语)。客户端凭据授予不会导致绑定到特定用户的令牌。 –

+0

你说得对,这种绑定不在规格范围内。但是如果需要的话,这可以通过最小程度的扩展来完成。 –

相关问题