0

I have a method that tries to extract information from a Jwt token to instantiate a UserDetails instance from. The method looks like this:

public UserDetails loadUserByAuthToken(String authToken){
    Claims claims = getClaimsFromToken(authToken);
    return JwtUserFactory.create(
            claims.get(CLAIM_KEY_USER_ID, Long.class),
              ....
            Collection<? extends GrantedAuthority>claims.get(CLAIM_KEY_GRANTED_AUTHORITIES, Collection.class),
    );

Despite explicitly casting the list value from CLAIM_KEY_GRANTED_AUTHORITIES to (List<GrantedAuthority>) it still converts the list to a linked hashmap.

I've read here that when the type is not defined Jackson automatically converts a list to a linked hashmap. Resteasy converting List to LinkedHashMap The thread is about resteasy but i think the same thing is happening in my code. In this thread Class cast exception in JWT I've read that Jackson is also used for determining data types when extracting data from a jwt token.

The point is that i am declaring a type, namely List.class. Thats as specific as i can give it because List<GrantedAuthority>.class results in a compile error. When i log the content of the list in the console it looks like this:

[{authority=ROLE_USER}, {authority=ROLE_ADMIN}]

How can i prevent Jackson from implicitly converting the GrantedAuthorityList to a List of LinkedHashMap and avoid a class cast exception?

I am using jjwt version 0.9.0

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>

Thank you

EDIT: Heres the getClaimsFromToken method

public Claims getClaimsFromToken(String token) {
    Claims claims;
    try {
        claims = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    } catch (Exception e) {
        e.printStackTrace();
        claims = null;
    }
    return claims;
}
Maurice
  • 6,698
  • 9
  • 47
  • 104

1 Answers1

0

Well after doing some more research i've found out that there is no solution in my case. According to Baeldung https://www.baeldung.com/jackson-collection-array jackson will convert custom object lists to LinkedHashMap lists. There is a way around this using jackson ObjectMapper together with TypeReference, but that only works when the custom object has a default no-args constructor, which mine doesn't.

So my work around is this:

convertListOfLinkedHashMapsToSimpleGrantedAuthorityList(objectMapper.convertValue(claims.get(CLAIM_KEY_GRANTED_AUTHORITIES, ArrayList.class),
                        new TypeReference<List<LinkedHashMap<String, SimpleGrantedAuthority>>>() { }));

    private Set<? extends GrantedAuthority> convertListOfLinkedHashMapsToSimpleGrantedAuthorityList(List<LinkedHashMap<String, SimpleGrantedAuthority>> linkedHashMapList){
        return linkedHashMapList.stream().flatMap(linkedHashMap -> linkedHashMap.values().stream()).collect(Collectors.toSet());
    }

Hope it will help anyone

Maurice
  • 6,698
  • 9
  • 47
  • 104