oauth / check_token不检查与端点关联的角色/范围

时间:2016-04-23 10:44:37

标签: security spring-security oauth-2.0

我有一个授权服务器和一个资源服务器。我在授权服务器上创建访问令牌,并尝试在资源服务器上使用oauth2中的RemoteTokenServices,在内部命中'/ oauth / check_token'到授权服务器,它只检查令牌是否存在及其到期。但是它没有根据对于access_token的角色/范围给出针对端点的角色/范围。

@FrameworkEndpoint
public class CheckTokenEndpoint {
@RequestMapping(value = "/oauth/check_token")
@ResponseBody
public Map<String, ?> checkToken(@RequestParam("token") String value) {

    OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
    if (token == null) {
        throw new InvalidTokenException("Token was not recognised");
    }

    if (token.isExpired()) {
        throw new InvalidTokenException("Token has expired");
    }

    OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());

    Map<String, ?> response = accessTokenConverter.convertAccessToken(token, authentication);

    return response;
   }
}

上面的代码片段来自CheckTokenEndpoint.java。 有没有办法实现基于角色/范围的授权?

1 个答案:

答案 0 :(得分:0)

如果有其他人使用基于XML的配置遇到JWT令牌实现的类似问题,我已经通过以下方式解决了这个问题

哦,我可以找到关于如何使用基于XML的配置实现Spring OAuth2的详细帖子here

一些假设

  1. 您正在使用具有自定义声明的JWT令牌
  2. 您提供了JwtAccessTokenConvertor的自定义实现,后者又实现了TokenEnhancer接口(随意实现AccessTokenConvertor和TokenEnhancer接口,而无需使用JwtAccessTokenConvertor)
  3. 您正在使用基于XML的配置
  4. 仔细查看CheckTokenEndpoint source code会显示以下内容

    private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
    

    查看DefaultAccessTokenConvertor的{​​{3}},它是AccessTokenConvertor接口的默认实现,基本上有以下合同

    Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication);
    OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map);
    OAuth2Authentication extractAuthentication(Map<String, ?> map);
    

    就我而言,我使用了JWT令牌,这意味着我传递给/oauth/token_check端点的令牌值是带符号的(带有RSA密钥对)JWT,而TokenCheckEndpoint会做一些检查,例如如

    • 检查令牌是否在db(oauth_access_token表)中,这不适用于JWT实现,因为它们不一定存储在db
    • 首先检查其有效的JWT令牌
    • 检查令牌的签名是否正确且未被篡改
    • 检查其未过期
    • 我不知道的其他检查

    除了上述内容之外,我还需要检查自定义声明,例如范围(即基本上角色及其相关权限)在数据库中是否相同(确保角色没有更改)因为令牌已经发出)。

    根据我的调试,当命中/oauth/check_token端点时,分别调用extractAccessToken后跟extractAuthentication方法(至少在JWT实现时)。

    因为我扩展了JwtAccessTokenConvertor(后者又实现了AccessTokenConvertor&amp; TokenEnhancer接口)以增强我的JWT令牌以通过覆盖向其添加自定义声明(即范围) 增强方法如下所示

     @Component
     public class MyJwtAccessTokenConvertor extends JwtAccessTokenConverter {
            @Override
             public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                     DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
                    //enhance the token with custom claims (i.e. user role scope) 
                   //then return it 
                   return result; 
              }
    
        @Override
        public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
                OAuth2AccessToken mytoken = tokenConverter.extractAccessToken(value, map);
    
                /* validate the custom claims of token i.e. user role scopes
                 * and if any issue throw an exception
                 */
    
                return token; 
             }
      }
    

    我可以轻松验证JWT访问令牌在extractAccessToken方法中是否具有所需的用户角色范围。如果我检测到任何违规,那么我抛出InvalidTokenException(也可以是自定义异常)。