Custom claims with date types inconsistent JSON format

Issue #133 closed
Timur Asanov created an issue

Hello, we have encountered an issue with how a LocalDateTime is formatted inside of the JSON of the generated token.

Given the code below:

JwtClaims claims = new JwtClaims();
claims.setIssuer("issuer");
claims.setExpirationTimeMinutesInTheFuture(5);
claims.setGeneratedJwtId();
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast(1);
claims.setClaim("some_date_time", LocalDateTime.now());

System.out.println(claims.toJson());

The JSON output is:

{"iss":"issuer","exp":1549406048,"jti":"z0XQzRm2CFkHnl7-gK29Kw","iat":1549405748,"nbf":1549405688,"some_date_time":"2019-02-05T17:29:08.546"}

As you can see the some_date_time format is yyyy-MM-dd'T'HH:mm:ss.SSS in this case.

However, there is a chance that when the token is generated the seconds and/or the milliseconds value of LocalDateTime.now() is 0. And you get output like below.

using this date time:

LocalDateTime noSecondsNoMilliseconds = LocalDate.now().atTime(17, 35);

you get:

{"iss":"issuer","exp":1549406530,"jti":"uehcm9kk0d3KqEpNWWDKOA","iat":1549406230,"nbf":1549406170,"some_date_time":"2019-02-05T17:35"}

using this date time:

LocalDateTime noMilliseconds = LocalDate.now().atTime(17, 35, 44);

you get:

{"iss":"issuer","exp":1549406530,"jti":"uehcm9kk0d3KqEpNWWDKOA","iat":1549406230,"nbf":1549406170,"some_date_time":"2019-02-05T17:35:44"}

The format changes. So when parsing a token with a custom claim with a date type, you must try at least 3 formats to parse that string back to a LocalDateTime object.

We can see that the issue is in org.jose4j.json.internal.json_simple.JSONValue.writeJSONString method which does not handle any date types so the JSON is generated by doing writeJSONString(value.toString(), out); which calls Java's implementation of the toString() method of the LocalDateTime object which omits seconds and milliseconds if they are 0.

As a workaround, we changed the claims to hold epoch times instead of dates.

We are proposing that better handling of date types inside of claims is implemented so that you always know how the date is stored in the token and how you can parse the date strings back to dates without having to try multiple formats.

Comments (2)

  1. Brian Campbell repo owner

    JWT defined a NumericDate to facilitate passing dates in JSON and uses it for the exp, nbf and iat claims . See the end of https://tools.ietf.org/html/rfc7519#section-2 but it's basically the epoch approach you mentioned. NumericDate along with void setNumericDateClaim(String claimName, NumericDate value) and NumericDate getNumericDateClaimValue(String claimName) on JwtClaims provide some help working with that type.

    If you really want a String representation, convert to and from a consistent formatted string before and after setting/getting on JwtClaims. See https://www.mkyong.com/java8/java-8-how-to-format-localdatetime/ for example on using LocalDateTime with DateTimeFormatter.

  2. Log in to comment