OAuth/check_token 不会检查与终结点关联的角色/作用域



我有一个授权服务器和一个资源服务器。我正在授权服务器上创建访问令牌,并尝试使用 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。有没有办法实现基于角色/范围的授权?

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

哦,我关于如何使用基于 XML 的配置实现 Spring OAuth2 的详细文章可以在这里找到

一些假设

  1. 您正在使用具有自定义声明的 JWT 令牌
  2. 您已经提供了JwtAccessTokenConvertor的自定义实现,而该实现又实现了TokenEnhancer接口(随意实现AccessTokenConvertor和TokenEnhancer接口,而无需使用JwtAccessTokenConvertor)
  3. 您正在使用基于 XML 的配置

仔细观察CheckTokenEndpoint源代码会发现以下内容

private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();

而看DefaultAccessTokenConvertor的源代码,是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将执行一些检查,例如

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

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

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

由于我已经扩展了JwtAccessTokenConvertor(这反过来又实现了AccessTokenConvertorTokenEnhancer接口),以便通过覆盖增强方法来增强我的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(也可以是自定义异常)。

相关内容

  • 没有找到相关文章

最新更新