0

I have spring boot REST API secured using OAuth2. My authentication server and resource server are two applications. All the REST API security properly working with REST client. Then I need to write security test cases. I generate access token using following code. Some end points need manually added claims inside REST method. Program given valid access token, but claims not include in this token.

private String generateToken(String... authorities) {

    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("123");

    tokenService = new DefaultTokenServices();

    JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
    tokenService.setTokenStore(jwtTokenStore);

    tokenService.setTokenEnhancer(converter);

    Collection<GrantedAuthority> grantAuthorities = new ArrayList<>();

    if (authorities != null) {
        for (String authority: authorities) {
            grantAuthorities.add(new SimpleGrantedAuthority(authority));
        }
    }

    Set<String> resourceIds = Collections.emptySet();
    Set<String> scopes = Collections.emptySet();

    Map<String, String> requestParameters = Collections.emptyMap();
    boolean approved = true;
    String redirectUrl = null;
    Set<String> responseTypes = Collections.emptySet();
    Map<String, Serializable> extensionProperties = Collections.emptyMap();

    OAuth2Request oAuth2Request = new OAuth2Request(requestParameters, "web-client", grantAuthorities,
            approved, scopes, resourceIds, redirectUrl, responseTypes, extensionProperties);

    User userPrincipal = new User("user", "", true, true,
            true, true, grantAuthorities);
    UsernamePasswordAuthenticationToken authenticationToken =
            new UsernamePasswordAuthenticationToken(userPrincipal, null, grantAuthorities);

    OAuth2Authentication auth = new OAuth2Authentication(oAuth2Request, authenticationToken);

    OAuth2AccessToken accessToken = tokenService.createAccessToken(auth);

    Map<String, Object> claims = new HashMap<>();

    List<Long> tenantIds = new ArrayList<>();
    tenantIds.add(1L);

    claims.put("role", 1L);
    claims.put("tenants", tenantIds);

    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(claims);

    return accessToken.getValue();

}

How I add claims to this token.

Nuwan Sameera
  • 739
  • 1
  • 8
  • 25

1 Answers1

-1

Finally found the solution. Add TokenEnhancerChain to code

Following is the final code

private String generateToken(String... authorities) {

    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("123");

    tokenService = new DefaultTokenServices();

    JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
    tokenService.setTokenStore(jwtTokenStore);

    Collection<GrantedAuthority> grantAuthorities = new ArrayList<>();

    if (authorities != null) {
        for (String authority: authorities) {
            grantAuthorities.add(new SimpleGrantedAuthority(authority));
        }
    }

    Set<String> resourceIds = Collections.emptySet();
    Set<String> scopes = Collections.emptySet();

    Map<String, String> requestParameters = Collections.emptyMap();
    boolean approved = true;
    String redirectUrl = null;
    Set<String> responseTypes = Collections.emptySet();
    Map<String, Serializable> extensionProperties = Collections.emptyMap();

    OAuth2Request oAuth2Request = new OAuth2Request(requestParameters, "web-client", grantAuthorities,
            approved, scopes, resourceIds, redirectUrl, responseTypes, extensionProperties);

    User userPrincipal = new User("user", "", true, true,
            true, true, grantAuthorities);
    UsernamePasswordAuthenticationToken authenticationToken =
            new UsernamePasswordAuthenticationToken(userPrincipal, null, grantAuthorities);

    OAuth2Authentication auth = new OAuth2Authentication(oAuth2Request, authenticationToken);

    Map<String, Object> claims = new HashMap<>();

    List<Long> tenantIds = new ArrayList<>();
    tenantIds.add(1L);

    claims.put("role", 1L);
    claims.put("tenants", tenantIds);

    OAuth2AccessToken accessToken = tokenService.createAccessToken(auth);

    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    tokenEnhancerChain.setTokenEnhancers(
            Arrays.asList(new CustomTokenEnhancer(), converter));

    accessToken = tokenEnhancerChain.enhance(accessToken, auth);

    return accessToken.getValue();

}

IMPORTANT : Add JwtAccessTokenConverter as final element of token enhancer list

Following is the CustomTokenEnhancer class.

public class CustomTokenEnhancer extends JwtAccessTokenConverter {

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        Map<String, Object> claims = new HashMap<>();

        List<Long> tenantIds = new ArrayList<>();
        tenantIds.add(1L);

        claims.put("role", 1L);
        claims.put("tenants", tenantIds);
        claims.put("userId", "admin@abc.com");

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(claims);

        return accessToken;

    }
}
Nuwan Sameera
  • 739
  • 1
  • 8
  • 25
  • what is `DefaultTokenServices`? How `OAuth2Request ` behaviour? How `OAuth2Authentication ` works and where it authenticate? In suggested answer, you say, just add `tokenEnhancerChain`, but inside you use `CustomTokenEnhancer` class, how it works? It looks like, you just posted question, to answer on it by yourself. – BSeitkazin Jan 03 '19 at 07:29
  • Sorry. I edit answer with CutomTokenEnhancer code. This is only for the testing. Create JWT token with claims for the testing. – Nuwan Sameera Jan 03 '19 at 09:09