0

I have added custom claims in token using TokenEnhancer, I need some of the custom claims to be available in Principal and/or authentication object.

I am using JdbcTokenStore and not JwtTokenStore.

I have gone through a couple of forum and articles but most talk about JwtTokenStore and not JdbcTokenStore.

public class AuthTokenEnhancer implements TokenEnhancer {

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

        Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put("claim1", "claimVal");
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
        return accessToken;
    }

}

2 Answers2

0

Your question has the answer within it.

JWT is used to represent claims between two parties securely. Without JWT, there is no question of claims.

That means how can you add a claim into a normal token and expect it to be read by the resource server. This token enhancer will provide the additional information to the client and won't be stored into any database and hence there is no way for the resource server to know it.

The simplest solution for your case is to use JWT. But if it is a sensitive information, maybe you should store it within the database and expose via an API which will check for the authority of the user accessing it.

Shubham
  • 97
  • 1
  • 14
  • I am aware of JWT custom claims. I was looking to implement when using JdbcTokneStore. It can be done by overriding ResourceServerConfigurerAdapter's `configure(ResourceServerSecurityConfigurer resources)` and supply it with a tokenService. – Shubhashish Shukla Aug 02 '19 at 15:45
  • Yes. You can choose the tokenStore that way. But, when you switch to JWT, it does not get stored to the OAUTH_ACCESS_TOKEN table. It gets created on the fly and never stored. That is the reason you cannot invalidate a JWT on logout simply. And that’s the reason it’s recommended to create a JWT access token which expires in less than an hour. – Shubham Aug 02 '19 at 16:14
0

Basically you could:

  1. At the AuthorizationServer: Provide your custom TokenEnhancer implementation and configure it via AuthorizationServerConfigurer
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenEnhancer(tokenEnhancer());
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new TestTokenEnhancer();
    }

}
  1. At the ResourceServer: Extend DefaultUserAuthenticationConverter and override extractAuthentication in which you can read the custom claim from the Map and add it to the Authentication (or your own extension of it).
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    RemoteTokenServices tokenServices;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenServices(testTokenServices());
    }

    private ResourceServerTokenServices testTokenServices() {
        tokenServices.setAccessTokenConverter(testAccessTokenConverter());
        return tokenServices;
    }

    private AccessTokenConverter testAccessTokenConverter() {
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(testUserTokenConverter());
        return accessTokenConverter;
    }

    /**
     * Retrieve additional claims that were set in the TokenEnhancer of the Authorization server during Oauth token creation.
     */
    private UserAuthenticationConverter testUserTokenConverter() {

        return new DefaultUserAuthenticationConverter() {

            @Override
            public Authentication extractAuthentication(Map<String, ?> map) {
                Authentication authentication = super.extractAuthentication(map);

                if (authentication != null) {
                    authentication = new TestAuthenticationToken(authentication.getPrincipal(),
                            authentication.getCredentials(), authentication.getAuthorities(),
                            (String) map.get("testKey"));
                }

                return authentication;
            }
        };

    }

}

This thread contains related solutions.

Don't forget to delete the token from the database (table oauth_access_token) during development iterations! Otherwise you could get an "old" (not expired) token not reflecting your current custom claims.

Dr. Oste
  • 40
  • 1
  • 9