oauth/check_token does not check for roles/scopes associated with endpoint

大兔子大兔子 提交于 2020-01-14 05:51:25

问题


I have one Authorization server and one resource server. I am creating access token at authorization server and try to use it at Resource server using RemoteTokenServices in oauth2 which hits '/oauth/check_token' internally to authorization server, where it only checks for token existence and its expiry. But it does not check for roles/scopes against endpoint given vs roles/scopes against 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;
   }
}

Above code snippet is from CheckTokenEndpoint.java. Is there any way to achieve roles/scopes based authorization also?


回答1:


If anyone else come across a similar issue with JWT token implementation using XML-based configuration, I have solved it the following way

Oh and my detailed post on how to implement Spring OAuth2 using XML-based configuration can be found here

Some assumptions

  1. You are using JWT tokens that have custom claims
  2. You have provided a custom implementation of JwtAccessTokenConvertor which in turn implements TokenEnhancer interface (feel free to implement AccessTokenConvertor & TokenEnhancer interfaces without having to use JwtAccessTokenConvertor)
  3. You are using XML-based configuration

A closer look at the CheckTokenEndpoint source code reveals the follow

private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();

And looking at the source code of DefaultAccessTokenConvertor, it is the default implementation of AccessTokenConvertor interface which basically have the following contracts

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

In my case, I used JWT tokens, meaning that the token value that I pass to the /oauth/token_check endpoint is a signed (with RSA keypair) JWT and the TokenCheckEndpoint will do a few checks such as

  • Checks if the token is in the db (oauth_access_token table), this does not apply to JWT implementation as they are not necessarily stored in db
  • Check that its valid JWT token in the first place
  • Check that the signature of the token is correct and it has not be tampered
  • Check that its not expired
  • Other checks that I don't know of

In addition to the above, I needed to check that the custom claim such as scope (i.e. basically role and its associated permissions) is same in the database (making sure that roles didn't change since token was issued).

Based on my debugging, when the /oauth/check_token endpoint is hit, the extractAccessToken followed by extractAuthentication methods is called respectively (at least with JWT implementation).

Since I have extended JwtAccessTokenConvertor (which in turn implements AccessTokenConvertor & TokenEnhancer interfaces) in order to enhance my JWT token to add custom claims (i.e. scope) to it by overriding the enhance method as shown below

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

I could easily validate that the JWT access token has the required user role scopes in the extractAccessToken method. If I detect any violation then I throw InvalidTokenException (can be custom exception too).



来源:https://stackoverflow.com/questions/36809746/oauth-check-token-does-not-check-for-roles-scopes-associated-with-endpoint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!