Jordi
Jordi

Reputation: 23277

Spring security: Read jwt details

I'm receiving a jwt after a call to /login:

ResponseEntity<Void> responseEntity = restTemplate
  .postForEntity(url, entity, Void.class); 

String bearer = responseEntity
  .getHeaders()
  .get("Authorization")
  .stream().findFirst().get();

After that, I'm getting a jwt token on Authorization header like:

"Bearer eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1Mzg1NjExNDgsInN1YiI6ImFkbWluIiwiZXhwIjoxNTM5NDI1MTQ4fQ.mr4MdNzNC8h1uq-OF9DeEBGS8AFgkN6ysooptNrvJeyyn6L6TLV1W4hv6osMggNpo_Ee6RqBhwuJu1beA8OFoA"

I would like to read expiration date and other information related with it.

Is there any library to handle it?

Does Spring provide any Helper to treat it?

Obviously, I've the secret key.

Upvotes: 0

Views: 811

Answers (2)

Habil
Habil

Reputation: 540

here is the code sample from my project;

static final String CLAIM_KEY_USERNAME = "sub";
static final String CLAIM_KEY_AUDIENCE = "audience";
static final String CLAIM_KEY_CREATED = "created";

private static final String AUDIENCE_UNKNOWN = "unknown";
private static final String AUDIENCE_WEB = "web";
private static final String AUDIENCE_MOBILE = "mobile";
private static final String AUDIENCE_TABLET = "tablet";

@Value("${jwt.secret}")
private String secret;

@Value("${jwt.expiration}")
private Long expiration;

public String getUsernameFromToken(String token) {
    final Claims claims = getClaimsFromToken(token);
    return claims != null ? claims.getSubject() : null;
}

public Date getCreatedDateFromToken(String token) {
    final Claims claims = getClaimsFromToken(token);
    return claims != null ? new Date((Long) claims.get(CLAIM_KEY_CREATED)) : null;
}

public Date getExpirationDateFromToken(String token) {
    final Claims claims = getClaimsFromToken(token);
    return claims != null ? claims.getExpiration() : null;
}

public String getAudienceFromToken(String token) {
    final Claims claims = getClaimsFromToken(token);
    return claims != null ? (String) claims.get(CLAIM_KEY_AUDIENCE) : null;
}

private Claims getClaimsFromToken(String token) {
    return StringUtils.hasText(token) ? Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody() : null;
}

private Date generateExpirationDate() {
    return new Date(System.currentTimeMillis() + expiration * 1000);
}

private Boolean isTokenExpired(String token) {
    final Date expirationDate = getExpirationDateFromToken(token);
    return expirationDate.before(new Date());
}

private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
    return (lastPasswordReset != null && created.before(lastPasswordReset));
}

private String generateAudience(Device device) {
    String audience = AUDIENCE_UNKNOWN;
    if (device.isNormal()) {
        audience = AUDIENCE_WEB;
    } else if (device.isTablet()) {
        audience = AUDIENCE_TABLET;
    } else if (device.isMobile()) {
        audience = AUDIENCE_MOBILE;
    }
    return audience;
}

private Boolean ignoreTokenExpiration(String token) {
    String audience = getAudienceFromToken(token);
    return (AUDIENCE_TABLET.equals(audience) || AUDIENCE_MOBILE.equals(audience));
}

 public String generateToken(UserDetails userDetails, Device device) {
    Map<String, Object> claims = new HashMap<>();
    claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
    claims.put(CLAIM_KEY_AUDIENCE, generateAudience(device));
    claims.put(CLAIM_KEY_CREATED, new Date());
    return generateToken(claims);
}

String generateToken(Map<String, Object> claims) {
    return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()).signWith(SignatureAlgorithm.HS512, secret).compact();
}

public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
    final Date created = getCreatedDateFromToken(token);
    return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset) && (!isTokenExpired(token) || ignoreTokenExpiration(token));
}

public String refreshToken(String token) {
    String refreshedToken;
    try {
        final Claims claims = getClaimsFromToken(token);
        claims.put(CLAIM_KEY_CREATED, new Date());
        refreshedToken = generateToken(claims);
    } catch (Exception e) {
        refreshedToken = null;
    }
    return refreshedToken;
}

public Boolean validateToken(String token, UserDetails userDetails) {
    JwtUser user = (JwtUser) userDetails;
    final String username = getUsernameFromToken(token);
    final Date created = getCreatedDateFromToken(token);
    return (username.equals(user.getUsername()) && !isTokenExpired(token) && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate()));
}

Upvotes: 1

Royts
Royts

Reputation: 531

You can use jwt library to parse the jwt token you received.

For example, I am using jsonwebtoken to parse the token. Something like this;

public Claims getClaimsFromToken(String token) throws Exception {
        Claims claims;

        claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody(); 

        return claims;
    }

If you want to get the value of a specific key inside your claims, you can do it like this;

public Object getClaimsValueFromToken(String token, String key) throws Exception {
        Claims claims = getClaimsFromToken(token);
        Object value = claims.get(key);
        return value;
    }

Ideally, you can create your own custom util using jwt library to be used for parsing the token.


Don't forget also to add the library as a maven dependency;

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

Upvotes: 1

Related Questions