Reputation: 365
I am creating a token string using JwtBuilder
. But while extracting a value using a key, it is giving ClassCastException
. For better understanding code snippet are provided below:
Token creation:
private JwtBuilder getJwtBuilder(
String jti,
Long issuedAt,
Long expiredAt,
Long businessAccountId,
Long consumerAccountId,
String deviceId
) {
JwtBuilder builder = Jwts.builder();
builder.setIssuer("SO");
builder.setSubject(TokenConstant.TOKEN_SUBJECT);
builder.setId(jti);
builder.setIssuedAt(new Date(issuedAt));
builder.setExpiration(new Date(expiredAt));
builder.claim(TokenConstant.BUSINESS_ACCOUNT_ID, businessAccountId);
builder.claim(TokenConstant.DEVICE_ID, deviceId);
builder.signWith(SignatureAlgorithm.HS512, secretKey);
return builder;
}
Decoding token:
private JsonWebToken decodeToken(String jsonWebToken) {
try {
Jws<Claims> map = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jsonWebToken);
Claims claims = map.getBody();
return getJsonWebTokenFromClaims(claims);
} catch (SignatureException | MalformedJwtException e) {
throw new InvalidTokenException(e.getMessage());
}
}
private JsonWebToken getJsonWebTokenFromClaims(Claims claims) {
JsonWebToken token = new JsonWebToken();
token.jti = claims.getId();
token.expirationTime = claims.getExpiration().getTime();
token.issuedAt = claims.getIssuedAt().getTime();
token.deviceId = (String) claims.get(TokenConstant.DEVICE_ID);
token.businessAccountId = (Long) claims.get(TokenConstant.BUSINESS_ACCOUNT_ID);
return token;
}
Exception:
2018-04-23 10:27:04.476 ERROR b.c.i.s.c.MyExceptionHandler - Application error: {} java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
jwt version:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
As you can see that my code is getting an error while casting Integer
type value to a Long
type. I am unable to understand, why Object
type is converted to Integer
implicitly?
Upvotes: 5
Views: 5027
Reputation: 24231
I would suggest upgrading the version of your jwt dependency to version 0.9.0
.
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
The issue was reported here as an issue in Github which indicates the auto binding to the data type based on smaller values set as a claim. I am copying the exact statement from the issue to elaborate more.
String claimName = "long"
Long claimVal = new Long(5)
String compact = Jwts.builder().setClaims([(claimName): claimVal]).compact();
Claims claims = Jwts.parser().parse(compact).body as Claims
// `claims.get` throws `RequiredTypeException`
assert claims.get(claimName, Long) == claimVal
Here, Jackson finds that a 5 is small enough to fit in the Integer and so unmarshalls into it, instead of expected Long.
What makes matters worse is that when a value is large enough (≥ 2^31), Jackson will switch to Long and so code that naively always get()-s Integer will stop working:
However, the issue has been fixed in this pull request and is available in the newer released version of the jwt library.
After updating the library you can get the proper value without having a RequiredTypeException
using the following code.
// businessAccountId is declared as Long I guess
token.businessAccountId = claims.get(TokenConstant.BUSINESS_ACCOUNT_ID, Long.class);
Hope that fixes your problem.
Upvotes: 7
Reputation: 72
Token creation file 3rd line from bottom you are doing ".longvalue()". I think you should try to change type of field "business AccountId"to Long
Upvotes: 0