diff --git a/lib/src/main/java/com/auth0/jwt/JWTCreator.java b/lib/src/main/java/com/auth0/jwt/JWTCreator.java index e2c22434..7d58fe2f 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTCreator.java +++ b/lib/src/main/java/com/auth0/jwt/JWTCreator.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.*; import java.util.Map.Entry; @@ -152,7 +153,19 @@ public Builder withExpiresAt(Date expiresAt) { } /** - * Add a specific Not Before ("nbf") claim to the Payload. The claim will be written as seconds since the epoch. + * Add a specific Expires At ("exp") claim to the payload. The claim will be written as seconds since the epoch; + * Milliseconds will be truncated by rounding down to the nearest second. + * + * @param expiresAt the Expires At value. + * @return this same Builder instance. + */ + public Builder withExpiresAt(Instant expiresAt) { + addClaim(PublicClaims.EXPIRES_AT, expiresAt); + return this; + } + + /** + * Add a specific Not Before ("nbf") claim to the Payload. The claim will be written as seconds since the epoch; * Milliseconds will be truncated by rounding down to the nearest second. * * @param notBefore the Not Before value. @@ -164,7 +177,19 @@ public Builder withNotBefore(Date notBefore) { } /** - * Add a specific Issued At ("iat") claim to the Payload. The claim will be written as seconds since the epoch. + * Add a specific Not Before ("nbf") claim to the Payload. The claim will be written as seconds since the epoch; + * Milliseconds will be truncated by rounding down to the nearest second. + * + * @param notBefore the Not Before value. + * @return this same Builder instance. + */ + public Builder withNotBefore(Instant notBefore) { + addClaim(PublicClaims.NOT_BEFORE, notBefore); + return this; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. The claim will be written as seconds since the epoch; * Milliseconds will be truncated by rounding down to the nearest second. * * @param issuedAt the Issued At value. @@ -175,6 +200,18 @@ public Builder withIssuedAt(Date issuedAt) { return this; } + /** + * Add a specific Issued At ("iat") claim to the Payload. The claim will be written as seconds since the epoch; + * Milliseconds will be truncated by rounding down to the nearest second. + * + * @param issuedAt the Issued At value. + * @return this same Builder instance. + */ + public Builder withIssuedAt(Instant issuedAt) { + addClaim(PublicClaims.ISSUED_AT, issuedAt); + return this; + } + /** * Add a specific JWT Id ("jti") claim to the Payload. * @@ -271,6 +308,21 @@ public Builder withClaim(String name, Date value) throws IllegalArgumentExceptio return this; } + /** + * Add a custom Claim value. The claim will be written as seconds since the epoch. + * Milliseconds will be truncated by rounding down to the nearest second. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Builder instance. + * @throws IllegalArgumentException if the name is null. + */ + public Builder withClaim(String name, Instant value) throws IllegalArgumentException { + assertNonNull(name); + addClaim(name, value); + return this; + } + /** * Add a custom Array Claim with the given items. * @@ -453,7 +505,7 @@ private static boolean isBasicType(Object value) { if (c.isArray()) { return c == Integer[].class || c == Long[].class || c == String[].class; } - return c == String.class || c == Integer.class || c == Long.class || c == Double.class || c == Date.class || c == Boolean.class; + return c == String.class || c == Integer.class || c == Long.class || c == Double.class || c == Date.class || c == Instant.class || c == Boolean.class; } /** diff --git a/lib/src/main/java/com/auth0/jwt/JWTDecoder.java b/lib/src/main/java/com/auth0/jwt/JWTDecoder.java index 71acbe59..55855241 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTDecoder.java +++ b/lib/src/main/java/com/auth0/jwt/JWTDecoder.java @@ -9,6 +9,7 @@ import java.io.Serializable; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.Base64; import java.util.Date; import java.util.List; @@ -93,16 +94,31 @@ public Date getExpiresAt() { return payload.getExpiresAt(); } + @Override + public Instant getExpiresAtAsInstant() { + return payload.getExpiresAtAsInstant(); + } + @Override public Date getNotBefore() { return payload.getNotBefore(); } + @Override + public Instant getNotBeforeAsInstant() { + return payload.getNotBeforeAsInstant(); + } + @Override public Date getIssuedAt() { return payload.getIssuedAt(); } + @Override + public Instant getIssuedAtAsInstant() { + return payload.getIssuedAtAsInstant(); + } + @Override public String getId() { return payload.getId(); diff --git a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java b/lib/src/main/java/com/auth0/jwt/JWTVerifier.java index 9a7ea2b2..8dfb6dbf 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java +++ b/lib/src/main/java/com/auth0/jwt/JWTVerifier.java @@ -9,8 +9,11 @@ import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.Verification; -import java.util.*; import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.*; /** * The JWTVerifier class holds the verify method to assert that a given Token has not only a proper JWT format, but also its signature matches. @@ -327,13 +330,13 @@ private void verifyClaimValues(DecodedJWT jwt, Map.Entry expecte assertValidAudienceClaim(jwt.getAudience(), (List) expectedClaim.getValue(), false); break; case PublicClaims.EXPIRES_AT: - assertValidDateClaim(jwt.getExpiresAt(), (Long) expectedClaim.getValue(), true); + assertValidInstantClaim(jwt.getExpiresAtAsInstant(), (Long) expectedClaim.getValue(), true); break; case PublicClaims.ISSUED_AT: - assertValidDateClaim(jwt.getIssuedAt(), (Long) expectedClaim.getValue(), false); + assertValidInstantClaim(jwt.getIssuedAtAsInstant(), (Long) expectedClaim.getValue(), false); break; case PublicClaims.NOT_BEFORE: - assertValidDateClaim(jwt.getNotBefore(), (Long) expectedClaim.getValue(), false); + assertValidInstantClaim(jwt.getNotBeforeAsInstant(), (Long) expectedClaim.getValue(), false); break; case PublicClaims.ISSUER: assertValidIssuerClaim(jwt.getIssuer(), (List) expectedClaim.getValue()); @@ -403,27 +406,24 @@ private void assertValidStringClaim(String claimName, String value, String expec } } - private void assertValidDateClaim(Date date, long leeway, boolean shouldBeFuture) { - Date today = new Date(clock.millis()); - today.setTime(today.getTime() / 1000 * 1000); // truncate millis + private void assertValidInstantClaim(Instant claimVal, long leeway, boolean shouldBeFuture) { + Instant now = clock.instant().truncatedTo(ChronoUnit.SECONDS); if (shouldBeFuture) { - assertDateIsFuture(date, leeway, today); + assertInstantIsFuture(claimVal, leeway, now); } else { - assertDateIsPast(date, leeway, today); + assertInstantIsPast(claimVal, leeway, now); } } - private void assertDateIsFuture(Date date, long leeway, Date today) { - today.setTime(today.getTime() - leeway * 1000); - if (date != null && today.after(date)) { - throw new TokenExpiredException(String.format("The Token has expired on %s.", date)); + private void assertInstantIsFuture(Instant claimVal, long leeway, Instant now) { + if (claimVal != null && now.minus(Duration.ofSeconds(leeway)).isAfter(claimVal)) { + throw new TokenExpiredException(String.format("The Token has expired on %s.", claimVal)); } } - private void assertDateIsPast(Date date, long leeway, Date today) { - today.setTime(today.getTime() + leeway * 1000); - if (date != null && today.before(date)) { - throw new InvalidClaimException(String.format("The Token can't be used before %s.", date)); + private void assertInstantIsPast(Instant claimVal, long leeway, Instant now) { + if (claimVal != null && now.plus(Duration.ofSeconds(leeway)).isBefore(claimVal)) { + throw new InvalidClaimException(String.format("The Token can't be used before %s.", claimVal)); } } diff --git a/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java b/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java index ae266798..0d816128 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java +++ b/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java @@ -6,11 +6,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import java.io.IOException; import java.lang.reflect.Array; +import java.time.Instant; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -63,6 +63,15 @@ public Date asDate() { return new Date(seconds * 1000); } + @Override + public Instant asInstant() { + if (!data.canConvertToLong()) { + return null; + } + long seconds = data.asLong(); + return Instant.ofEpochSecond(seconds); + } + @Override @SuppressWarnings("unchecked") public T[] asArray(Class tClazz) throws JWTDecodeException { diff --git a/lib/src/main/java/com/auth0/jwt/impl/NullClaim.java b/lib/src/main/java/com/auth0/jwt/impl/NullClaim.java index 2e9a38c2..664328de 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/NullClaim.java +++ b/lib/src/main/java/com/auth0/jwt/impl/NullClaim.java @@ -3,6 +3,7 @@ import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.Claim; +import java.time.Instant; import java.util.Date; import java.util.List; import java.util.Map; @@ -46,6 +47,11 @@ public Date asDate() { return null; } + @Override + public Instant asInstant() { + return null; + } + @Override public T[] asArray(Class tClazz) throws JWTDecodeException { return null; diff --git a/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java b/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java index 8935a277..46bd7ebe 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java +++ b/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; +import java.time.Instant; import java.util.*; /** @@ -45,9 +46,9 @@ public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOE String issuer = getString(tree, PublicClaims.ISSUER); String subject = getString(tree, PublicClaims.SUBJECT); List audience = getStringOrArray(tree, PublicClaims.AUDIENCE); - Date expiresAt = getDateFromSeconds(tree, PublicClaims.EXPIRES_AT); - Date notBefore = getDateFromSeconds(tree, PublicClaims.NOT_BEFORE); - Date issuedAt = getDateFromSeconds(tree, PublicClaims.ISSUED_AT); + Instant expiresAt = getInstantFromSeconds(tree, PublicClaims.EXPIRES_AT); + Instant notBefore = getInstantFromSeconds(tree, PublicClaims.NOT_BEFORE); + Instant issuedAt = getInstantFromSeconds(tree, PublicClaims.ISSUED_AT); String jwtId = getString(tree, PublicClaims.JWT_ID); return new PayloadImpl(issuer, subject, audience, expiresAt, notBefore, issuedAt, jwtId, tree, objectReader); @@ -73,7 +74,7 @@ List getStringOrArray(Map tree, String claimName) thro return list; } - Date getDateFromSeconds(Map tree, String claimName) { + Instant getInstantFromSeconds(Map tree, String claimName) { JsonNode node = tree.get(claimName); if (node == null || node.isNull()) { return null; @@ -81,8 +82,7 @@ Date getDateFromSeconds(Map tree, String claimName) { if (!node.canConvertToLong()) { throw new JWTDecodeException(String.format("The claim '%s' contained a non-numeric date value.", claimName)); } - final long ms = node.asLong() * 1000; - return new Date(ms); + return Instant.ofEpochSecond(node.asLong()); } String getString(Map tree, String claimName) { diff --git a/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java b/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java index f056c038..a446741c 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java +++ b/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectReader; import java.io.Serializable; +import java.time.Instant; import java.util.*; import static com.auth0.jwt.impl.JsonNodeClaim.extractClaim; @@ -24,14 +25,14 @@ class PayloadImpl implements Payload, Serializable { private final String issuer; private final String subject; private final List audience; - private final Date expiresAt; - private final Date notBefore; - private final Date issuedAt; + private final Instant expiresAt; + private final Instant notBefore; + private final Instant issuedAt; private final String jwtId; private final Map tree; private final ObjectReader objectReader; - PayloadImpl(String issuer, String subject, List audience, Date expiresAt, Date notBefore, Date issuedAt, String jwtId, Map tree, ObjectReader objectReader) { + PayloadImpl(String issuer, String subject, List audience, Instant expiresAt, Instant notBefore, Instant issuedAt, String jwtId, Map tree, ObjectReader objectReader) { this.issuer = issuer; this.subject = subject; this.audience = audience != null ? Collections.unmodifiableList(audience) : null; @@ -64,19 +65,35 @@ public List getAudience() { @Override public Date getExpiresAt() { - return expiresAt; + return (expiresAt != null) ? Date.from(expiresAt) : null; } + @Override - public Date getNotBefore() { - return notBefore; + public Instant getExpiresAtAsInstant() { + return expiresAt; } @Override public Date getIssuedAt() { + return (issuedAt != null) ? Date.from(issuedAt) : null; + } + + @Override + public Instant getIssuedAtAsInstant() { return issuedAt; } + @Override + public Date getNotBefore() { + return (notBefore != null) ? Date.from(notBefore) : null; + } + + @Override + public Instant getNotBeforeAsInstant() { + return notBefore; + } + @Override public String getId() { return jwtId; diff --git a/lib/src/main/java/com/auth0/jwt/impl/PayloadSerializer.java b/lib/src/main/java/com/auth0/jwt/impl/PayloadSerializer.java index 9ec6dc89..0389121c 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/PayloadSerializer.java +++ b/lib/src/main/java/com/auth0/jwt/impl/PayloadSerializer.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; +import java.time.Instant; import java.util.*; /** @@ -71,13 +72,15 @@ private void writeAudience(JsonGenerator gen, Map.Entry e) throw } /** - * Serializes {@linkplain Date} to epoch second values, traversing maps and lists as needed. + * Serializes {@linkplain Instant} to epoch second values, traversing maps and lists as needed. * @param value the object to serialize * @param gen the JsonGenerator to use for JSON serialization */ private void handleSerialization(Object value, JsonGenerator gen) throws IOException { - if (value instanceof Date) { // EXPIRES_AT, ISSUED_AT, NOT_BEFORE, custom date claims + if (value instanceof Date) { gen.writeNumber(dateToSeconds((Date) value)); + } else if (value instanceof Instant) { // EXPIRES_AT, ISSUED_AT, NOT_BEFORE, custom Instant claims + gen.writeNumber(instantToSeconds((Instant) value)); } else if (value instanceof Map) { serializeMap((Map) value, gen); } else if (value instanceof List) { @@ -105,6 +108,10 @@ private void serializeList(List list, JsonGenerator gen) throws IOException { gen.writeEndArray(); } + private long instantToSeconds(Instant instant) { + return instant.getEpochSecond(); + } + private long dateToSeconds(Date date) { return date.getTime() / 1000; } diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/Claim.java b/lib/src/main/java/com/auth0/jwt/interfaces/Claim.java index b3d41b1d..cc5256f4 100644 --- a/lib/src/main/java/com/auth0/jwt/interfaces/Claim.java +++ b/lib/src/main/java/com/auth0/jwt/interfaces/Claim.java @@ -2,6 +2,7 @@ import com.auth0.jwt.exceptions.JWTDecodeException; +import java.time.Instant; import java.util.Date; import java.util.List; import java.util.Map; @@ -66,6 +67,17 @@ public interface Claim { */ Date asDate(); + /** + * Get this Claim as an Instant. + * If the value can't be converted to an Instant, null will be returned. + * + * @return the value as a Date or null. + */ + default Instant asInstant() { + Date date = asDate(); + return date != null ? date.toInstant() : null; + } + /** * Get this Claim as an Array of type T. * If the value isn't an Array, null will be returned. diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java b/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java index b999ad43..b3bf71f5 100644 --- a/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java +++ b/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java @@ -1,5 +1,6 @@ package com.auth0.jwt.interfaces; +import java.time.Instant; import java.util.Date; import java.util.List; import java.util.Map; @@ -37,6 +38,15 @@ public interface Payload { */ Date getExpiresAt(); + /** + * Get the value of the "exp" claim as an {@linkplain Instant}, or null if it's not available. + * + * @return the Expiration Time value or null. + */ + default Instant getExpiresAtAsInstant() { + return getExpiresAt() != null ? getExpiresAt().toInstant() : null; + } + /** * Get the value of the "nbf" claim, or null if it's not available. * @@ -44,6 +54,15 @@ public interface Payload { */ Date getNotBefore(); + /** + * Get the value of the "nbf" claim as an {@linkplain Instant}, or null if it's not available. + * + * @return the Not Before value or null. + */ + default Instant getNotBeforeAsInstant() { + return getNotBefore() != null ? getNotBefore().toInstant() : null; + } + /** * Get the value of the "iat" claim, or null if it's not available. * @@ -51,6 +70,15 @@ public interface Payload { */ Date getIssuedAt(); + /** + * Get the value of the "iat" claim as an {@linkplain Instant}, or null if it's not available. + * + * @return the Issued At value or null. + */ + default Instant getIssuedAtAsInstant() { + return getIssuedAt() != null ? getIssuedAt().toInstant() : null; + } + /** * Get the value of the "jti" claim, or null if it's not available. * diff --git a/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java b/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java index fe15f3db..c6fff1f2 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java @@ -13,6 +13,7 @@ import java.nio.charset.StandardCharsets; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.RSAPrivateKey; +import java.time.Instant; import java.util.*; import static org.hamcrest.Matchers.*; @@ -64,7 +65,7 @@ public void shouldReturnBuilderIfNullMapIsProvided() { @Test public void shouldOverwriteExistingHeaderIfHeaderMapContainsTheSameKey() { - Map header = new HashMap(); + Map header = new HashMap<>(); header.put(PublicClaims.KEY_ID, "xyz"); String signed = JWTCreator.init() @@ -80,7 +81,7 @@ public void shouldOverwriteExistingHeaderIfHeaderMapContainsTheSameKey() { @Test public void shouldOverwriteExistingHeadersWhenSettingSameHeaderKey() { - Map header = new HashMap(); + Map header = new HashMap<>(); header.put(PublicClaims.KEY_ID, "xyz"); String signed = JWTCreator.init() @@ -96,7 +97,7 @@ public void shouldOverwriteExistingHeadersWhenSettingSameHeaderKey() { @Test public void shouldRemoveHeaderIfTheValueIsNull() { - Map header = new HashMap(); + Map header = new HashMap<>(); header.put(PublicClaims.KEY_ID, null); header.put("test2", "isSet"); @@ -271,6 +272,17 @@ public void shouldAddExpiresAt() { assertThat(TokenUtils.splitToken(signed)[1], is("eyJleHAiOjE0Nzc1OTJ9")); } + @Test + public void shouldAddExpiresAtInstant() { + String signed = JWTCreator.init() + .withExpiresAt(Instant.ofEpochSecond(1477592)) + .sign(Algorithm.HMAC256("secret")); + + System.out.println(signed); + assertThat(signed, is(notNullValue())); + assertThat(TokenUtils.splitToken(signed)[1], is("eyJleHAiOjE0Nzc1OTJ9")); + } + @Test public void shouldAddNotBefore() { String signed = JWTCreator.init() @@ -281,6 +293,16 @@ public void shouldAddNotBefore() { assertThat(TokenUtils.splitToken(signed)[1], is("eyJuYmYiOjE0Nzc1OTJ9")); } + @Test + public void shouldAddNotBeforeInstant() { + String signed = JWTCreator.init() + .withNotBefore(Instant.ofEpochSecond(1477592)) + .sign(Algorithm.HMAC256("secret")); + + assertThat(signed, is(notNullValue())); + assertThat(TokenUtils.splitToken(signed)[1], is("eyJuYmYiOjE0Nzc1OTJ9")); + } + @Test public void shouldAddIssuedAt() { String signed = JWTCreator.init() @@ -291,6 +313,16 @@ public void shouldAddIssuedAt() { assertThat(TokenUtils.splitToken(signed)[1], is("eyJpYXQiOjE0Nzc1OTJ9")); } + @Test + public void shouldAddIssuedAtInstant() { + String signed = JWTCreator.init() + .withIssuedAt(Instant.ofEpochSecond(1477592)) + .sign(Algorithm.HMAC256("secret")); + + assertThat(signed, is(notNullValue())); + assertThat(TokenUtils.splitToken(signed)[1], is("eyJpYXQiOjE0Nzc1OTJ9")); + } + @Test public void shouldAddJWTId() { String signed = JWTCreator.init() @@ -430,6 +462,18 @@ public void shouldAcceptCustomClaimOfTypeDate() { assertThat(parts[1], is("eyJuYW1lIjoxNDc4ODkxNTIxfQ")); } + @Test + public void shouldAcceptCustomClaimOfTypeDateInstant() { + Instant instant = Instant.ofEpochSecond(1478891521); + String jwt = JWTCreator.init() + .withClaim("name", instant) + .sign(Algorithm.HMAC256("secret")); + + assertThat(jwt, is(notNullValue())); + String[] parts = jwt.split("\\."); + assertThat(parts[1], is("eyJuYW1lIjoxNDc4ODkxNTIxfQ")); + } + @Test public void shouldAcceptCustomArrayClaimOfTypeString() { String jwt = JWTCreator.init() @@ -499,7 +543,8 @@ public void shouldAcceptCustomMapClaimOfBasicObjectTypes() throws Exception { data.put("integer", 1); data.put("long", Long.MAX_VALUE); data.put("double", 123.456d); - data.put("date", new Date(123000)); + data.put("date", new Date(123000L)); + data.put("instant", Instant.ofEpochSecond(123)); data.put("boolean", true); // array types @@ -531,12 +576,13 @@ public void shouldAcceptCustomMapClaimOfBasicObjectTypes() throws Exception { assertThat(map.get("double"), is(123.456d)); assertThat(map.get("date"), is(123)); + assertThat(map.get("instant"), is(123)); assertThat(map.get("boolean"), is(true)); // array types assertThat(map.get("intArray"), is(Arrays.asList(3, 5))); assertThat(map.get("longArray"), is(Arrays.asList(Long.MAX_VALUE, Long.MIN_VALUE))); - assertThat(map.get("stringArray"), is(Arrays.asList("string"))); + assertThat(map.get("stringArray"), is(Collections.singletonList("string"))); // list assertThat(map.get("list"), is(Arrays.asList("a", "b", "c"))); @@ -554,7 +600,8 @@ public void shouldAcceptCustomListClaimOfBasicObjectTypes() throws Exception { data.add(1); data.add(Long.MAX_VALUE); data.add(123.456d); - data.add(new Date(123000)); + data.add(new Date(123000L)); + data.add(Instant.ofEpochSecond(123)); data.add(true); // array types @@ -585,17 +632,17 @@ public void shouldAcceptCustomListClaimOfBasicObjectTypes() throws Exception { assertThat(list.get(2), is(Long.MAX_VALUE)); assertThat(list.get(3), is(123.456d)); assertThat(list.get(4), is(123)); - assertThat(list.get(5), is(true)); + assertThat(list.get(5), is(123)); + assertThat(list.get(6), is(true)); // array types - assertThat(list.get(6), is(Arrays.asList(3, 5))); - assertThat(list.get(7), is(Arrays.asList(Long.MAX_VALUE, Long.MIN_VALUE))); - assertThat(list.get(8), is(Arrays.asList("string"))); + assertThat(list.get(7), is(Arrays.asList(3, 5))); + assertThat(list.get(8), is(Arrays.asList(Long.MAX_VALUE, Long.MIN_VALUE))); + assertThat(list.get(9), is(Arrays.asList("string"))); // list - assertThat(list.get(9), is(Arrays.asList("a", "b", "c"))); - assertThat(list.get(10), is(sub)); - + assertThat(list.get(10), is(Arrays.asList("a", "b", "c"))); + assertThat(list.get(11), is(sub)); } @Test @@ -681,7 +728,7 @@ public void shouldRefuseCustomMapClaimForNonStringKey() { @Test public void shouldRefuseCustomListClaimForUnknownListElement() { - List list = Arrays.asList(new UserPojo("Michael", 255)); + List list = Collections.singletonList(new UserPojo("Michael", 255)); exception.expect(IllegalArgumentException.class); @@ -692,7 +739,7 @@ public void shouldRefuseCustomListClaimForUnknownListElement() { @Test public void shouldRefuseCustomListClaimForUnknownListElementWrappedInAMap() { - List list = Arrays.asList(new UserPojo("Michael", 255)); + List list = Collections.singletonList(new UserPojo("Michael", 255)); Map data = new HashMap<>(); data.put("someList", list); @@ -798,7 +845,7 @@ public void withPayloadShouldNotAllowCustomType() { Map payload = new HashMap<>(); payload.put("entry", "value"); payload.put("pojo", new UserPojo("name", 42)); - String jwt = JWTCreator.init() + JWTCreator.init() .withPayload(payload) .sign(Algorithm.HMAC256("secret")); } @@ -824,7 +871,7 @@ public void withPayloadShouldNotAllowListWithCustomType() { Map payload = new HashMap<>(); payload.put("list", Arrays.asList("item1", new UserPojo("name", 42))); - String jwt = JWTCreator.init() + JWTCreator.init() .withPayload(payload) .sign(Algorithm.HMAC256("secret")); } @@ -837,7 +884,7 @@ public void withPayloadShouldNotAllowMapWithCustomType() { Map payload = new HashMap<>(); payload.put("entry", "value"); payload.put("map", Collections.singletonMap("pojo", new UserPojo("name", 42))); - String jwt = JWTCreator.init() + JWTCreator.init() .withPayload(payload) .sign(Algorithm.HMAC256("secret")); } diff --git a/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java b/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java index 536c2dbb..a9e8f248 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java @@ -12,6 +12,7 @@ import java.io.*; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.Base64; import java.util.Date; import java.util.Map; @@ -156,33 +157,27 @@ public void shouldGetStringAudience() { public void shouldGetExpirationTime() { DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NzY3MjcwODZ9.L9dcPHEDQew2u9MkDCORFkfDGcSOsgoPqNY-LUMLEHg"); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(instanceOf(Date.class))); long ms = 1476727086L * 1000; - Date expectedDate = new Date(ms); - assertThat(jwt.getExpiresAt(), is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(equalTo(expectedDate))); + assertThat(jwt.getExpiresAt(), is(equalTo(new Date(ms)))); + assertThat(jwt.getExpiresAtAsInstant(), is(equalTo(Instant.ofEpochMilli(ms)))); } @Test public void shouldGetNotBefore() { DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0NzY3MjcwODZ9.tkpD3iCPQPVqjnjpDVp2bJMBAgpVCG9ZjlBuMitass0"); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getNotBefore(), is(instanceOf(Date.class))); long ms = 1476727086L * 1000; - Date expectedDate = new Date(ms); - assertThat(jwt.getNotBefore(), is(notNullValue())); - assertThat(jwt.getNotBefore(), is(equalTo(expectedDate))); + assertThat(jwt.getNotBefore(), is(equalTo(new Date(ms)))); + assertThat(jwt.getNotBeforeAsInstant(), is(equalTo(Instant.ofEpochMilli(ms)))); } @Test public void shouldGetIssuedAt() { DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NzY3MjcwODZ9.KPjGoW665E8V5_27Jugab8qSTxLk2cgquhPCBfAP0_w"); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(instanceOf(Date.class))); long ms = 1476727086L * 1000; - Date expectedDate = new Date(ms); - assertThat(jwt.getIssuedAt(), is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(equalTo(expectedDate))); + assertThat(jwt.getIssuedAt(), is(equalTo(new Date(ms)))); + assertThat(jwt.getIssuedAtAsInstant(), is(equalTo(Instant.ofEpochMilli(ms)))); } @Test @@ -272,6 +267,15 @@ public void shouldGetCustomClaimOfTypeDate() { assertThat(jwt.getClaim("name").asDate().getTime(), is(date.getTime())); } + @Test + public void shouldGetCustomClaimOfTypeInstant() { + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxNDc4ODkxNTIxfQ.mhioumeok8fghQEhTKF3QtQAksSvZ_9wIhJmgZLhJ6c"; + Instant instant = Instant.ofEpochSecond(1478891521L); + DecodedJWT jwt = JWT.decode(token); + assertThat(jwt, is(notNullValue())); + assertThat(jwt.getClaim("name").asInstant(), is(equalTo(instant))); + } + @Test public void shouldGetCustomArrayClaimOfTypeString() { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbInRleHQiLCIxMjMiLCJ0cnVlIl19.lxM8EcmK1uSZRAPd0HUhXGZJdauRmZmLjoeqz4J9yAA"; @@ -294,9 +298,9 @@ public void shouldGetCustomMapClaim() { DecodedJWT jwt = JWT.decode(token); assertThat(jwt, is(notNullValue())); Map map = jwt.getClaim("name").asMap(); - assertThat(map, hasEntry("string", (Object) "value")); - assertThat(map, hasEntry("number", (Object) 1)); - assertThat(map, hasEntry("boolean", (Object) true)); + assertThat(map, hasEntry("string", "value")); + assertThat(map, hasEntry("number", 1)); + assertThat(map, hasEntry("boolean", true)); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/JWTTest.java b/lib/src/test/java/com/auth0/jwt/JWTTest.java index bf7e07da..2015c037 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTTest.java @@ -21,8 +21,6 @@ import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class JWTTest { @@ -285,9 +283,9 @@ public void shouldGetExpirationTime() { .verify(token); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(instanceOf(Date.class))); - assertThat(jwt.getExpiresAt(), is(notNullValue())); assertThat(jwt.getExpiresAt(), is(equalTo(new Date(seconds * 1000)))); + assertThat(jwt.getExpiresAtAsInstant(), is(equalTo(Instant.ofEpochSecond(seconds)))); + } @Test @@ -302,9 +300,8 @@ public void shouldGetNotBefore() { .verify(token); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getNotBefore(), is(instanceOf(Date.class))); - assertThat(jwt.getNotBefore(), is(notNullValue())); assertThat(jwt.getNotBefore(), is(equalTo(new Date(seconds * 1000)))); + assertThat(jwt.getNotBeforeAsInstant(), is(equalTo(Instant.ofEpochSecond(seconds)))); } @Test @@ -319,9 +316,8 @@ public void shouldGetIssuedAt() { .verify(token); assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(instanceOf(Date.class))); - assertThat(jwt.getIssuedAt(), is(notNullValue())); assertThat(jwt.getIssuedAt(), is(equalTo(new Date(seconds * 1000)))); + assertThat(jwt.getIssuedAtAsInstant(), is(equalTo(Instant.ofEpochSecond(seconds)))); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java index 4a3dbb65..acc633fc 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java @@ -19,17 +19,15 @@ import java.util.HashMap; import java.util.Map; -import static org.hamcrest.Matchers.startsWith; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.*; -import static org.junit.Assert.assertThrows; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.mock; public class JWTVerifierTest { - private Clock mockNow = Clock.fixed(Instant.ofEpochSecond(1477592), ZoneId.of("UTC")); - private Clock mockOneSecondEarlier = Clock.offset(mockNow, Duration.ofSeconds(-1)); - private Clock mockOneSecondLater = Clock.offset(mockNow, Duration.ofSeconds(1)); + private final Clock mockNow = Clock.fixed(Instant.ofEpochSecond(1477592), ZoneId.of("UTC")); + private final Clock mockOneSecondEarlier = Clock.offset(mockNow, Duration.ofSeconds(-1)); + private final Clock mockOneSecondLater = Clock.offset(mockNow, Duration.ofSeconds(1)); @Rule public ExpectedException exception = ExpectedException.none(); diff --git a/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java b/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java index 3299134d..3c744487 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java @@ -20,14 +20,14 @@ import org.mockito.ArgumentMatchers; import java.io.IOException; +import java.time.Instant; import java.util.*; import static com.auth0.jwt.impl.JWTParser.getDefaultObjectMapper; -import static com.auth0.jwt.impl.JsonNodeClaim.claimFromNode; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.*; public class JsonNodeClaimTest { @@ -117,20 +117,23 @@ public void shouldGetNullDoubleIfNotDoubleValue() { } @Test - public void shouldGetDateValue() { - JsonNode value = mapper.valueToTree(1476824844L); + public void shouldGetNumericDateValue() { + long seconds = 1476824844L; + JsonNode value = mapper.valueToTree(seconds); Claim claim = claimFromNode(value); - assertThat(claim.asDate(), is(notNullValue())); - assertThat(claim.asDate(), is(new Date(1476824844L * 1000))); + assertThat(claim.asDate(), is(new Date(seconds * 1000))); + assertThat(claim.asInstant(), is(Instant.ofEpochSecond(seconds))); } @Test - public void shouldGetNullDateIfNotDateValue() { + public void shouldGetNullIfNotNumericDateValue() { JsonNode objectValue = mapper.valueToTree(new Object()); assertThat(claimFromNode(objectValue).asDate(), is(nullValue())); + assertThat(claimFromNode(objectValue).asInstant(), is(nullValue())); JsonNode stringValue = mapper.valueToTree("1476824844"); assertThat(claimFromNode(stringValue).asDate(), is(nullValue())); + assertThat(claimFromNode(stringValue).asInstant(), is(nullValue())); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/impl/NullClaimTest.java b/lib/src/test/java/com/auth0/jwt/impl/NullClaimTest.java index 84f91c78..bd478130 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/NullClaimTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/NullClaimTest.java @@ -50,6 +50,11 @@ public void shouldGetAsDate() { assertThat(claim.asDate(), is(nullValue())); } + @Test + public void shouldGetAsInstant() { + assertThat(claim.asInstant(), is(nullValue())); + } + @Test public void shouldGetAsArray() { assertThat(claim.asArray(Object.class), is(nullValue())); diff --git a/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java b/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java index 16a7198d..96b79afa 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java @@ -19,6 +19,7 @@ import org.junit.rules.ExpectedException; import java.io.StringReader; +import java.time.Instant; import java.util.*; import static org.hamcrest.Matchers.*; @@ -96,6 +97,9 @@ public void shouldNotRemoveKnownPublicClaimsFromTree() throws Exception { assertThat(payload.getIssuedAt().getTime(), is(10101010L * 1000)); assertThat(payload.getExpiresAt().getTime(), is(11111111L * 1000)); assertThat(payload.getNotBefore().getTime(), is(10101011L * 1000)); + assertThat(payload.getIssuedAtAsInstant().getEpochSecond(), is(10101010L)); + assertThat(payload.getExpiresAtAsInstant().getEpochSecond(), is(11111111L)); + assertThat(payload.getNotBeforeAsInstant().getEpochSecond(), is(10101011L)); assertThat(payload.getId(), is("idid")); assertThat(payload.getClaim("roles").asString(), is("admin")); @@ -177,24 +181,23 @@ public void shouldGetNullArrayWhenParsingNonArrayOrTextNode() { assertThat(values, is(nullValue())); } - @Test - public void shouldGetNullDateWhenParsingNullNode() { + public void shouldGetNullInstantWhenParsingNullNode() { Map tree = new HashMap<>(); NullNode node = NullNode.getInstance(); tree.put("key", node); - Date date = deserializer.getDateFromSeconds(tree, "key"); - assertThat(date, is(nullValue())); + Instant instant = deserializer.getInstantFromSeconds(tree, "key"); + assertThat(instant, is(nullValue())); } @Test - public void shouldGetNullDateWhenParsingNull() { + public void shouldGetNullInstantWhenParsingNull() { Map tree = new HashMap<>(); tree.put("key", null); - Date date = deserializer.getDateFromSeconds(tree, "key"); - assertThat(date, is(nullValue())); + Instant instant = deserializer.getInstantFromSeconds(tree, "key"); + assertThat(instant, is(nullValue())); } @Test @@ -206,32 +209,33 @@ public void shouldThrowWhenParsingNonNumericNode() { TextNode node = new TextNode("123456789"); tree.put("key", node); - deserializer.getDateFromSeconds(tree, "key"); + deserializer.getInstantFromSeconds(tree, "key"); } @Test - public void shouldGetDateWhenParsingNumericNode() { + public void shouldGetInstantWhenParsingNumericNode() { Map tree = new HashMap<>(); long seconds = 1478627949 / 1000; LongNode node = new LongNode(seconds); tree.put("key", node); - Date date = deserializer.getDateFromSeconds(tree, "key"); - assertThat(date, is(notNullValue())); - assertThat(date.getTime(), is(seconds * 1000)); + Instant instant = deserializer.getInstantFromSeconds(tree, "key"); + assertThat(instant, is(notNullValue())); + assertThat(instant.toEpochMilli(), is(seconds * 1000)); } + @Test - public void shouldGetLargeDateWhenParsingNumericNode() { + public void shouldGetLargeInstantWhenParsingNumericNode() { Map tree = new HashMap<>(); long seconds = Integer.MAX_VALUE + 10000L; LongNode node = new LongNode(seconds); tree.put("key", node); - Date date = deserializer.getDateFromSeconds(tree, "key"); - assertThat(date, is(notNullValue())); - assertThat(date.getTime(), is(seconds * 1000)); - assertThat(date.getTime(), is(2147493647L * 1000)); + Instant instant = deserializer.getInstantFromSeconds(tree, "key"); + assertThat(instant, is(notNullValue())); + assertThat(instant.toEpochMilli(), is(seconds * 1000)); + assertThat(instant.toEpochMilli(), is(2147493647L * 1000)); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java b/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java index 3cf6e023..1d3218ed 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java @@ -11,8 +11,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Mockito; +import java.time.Instant; import java.util.*; import static com.auth0.jwt.impl.JWTParser.getDefaultObjectMapper; @@ -25,38 +25,33 @@ public class PayloadImplTest { public ExpectedException exception = ExpectedException.none(); private PayloadImpl payload; - private Date expiresAt; - private Date notBefore; - private Date issuedAt; + private final Instant expiresAt = Instant.now().plusSeconds(10); + private final Instant notBefore = Instant.now(); + private final Instant issuedAt = Instant.now(); - private ObjectMapper mapper; private ObjectReader objectReader; @Before public void setUp() { - mapper = getDefaultObjectMapper(); + ObjectMapper mapper = getDefaultObjectMapper(); objectReader = mapper.reader(); - expiresAt = Mockito.mock(Date.class); - notBefore = Mockito.mock(Date.class); - issuedAt = Mockito.mock(Date.class); Map tree = new HashMap<>(); tree.put("extraClaim", new TextNode("extraValue")); payload = new PayloadImpl("issuer", "subject", Collections.singletonList("audience"), expiresAt, notBefore, issuedAt, "jwtId", tree, objectReader); } - @SuppressWarnings("Convert2Diamond") @Test public void shouldHaveUnmodifiableTree() { exception.expect(UnsupportedOperationException.class); - PayloadImpl payload = new PayloadImpl(null, null, null, null, null, null, null, new HashMap(), objectReader); + PayloadImpl payload = new PayloadImpl(null, null, null, null, null, null, null, new HashMap<>(), objectReader); payload.getTree().put("something", null); } @Test public void shouldHaveUnmodifiableAudience() { exception.expect(UnsupportedOperationException.class); - PayloadImpl payload = new PayloadImpl(null, null, new ArrayList(), null, null, null, null, null, objectReader); + PayloadImpl payload = new PayloadImpl(null, null, new ArrayList<>(), null, null, null, null, null, objectReader); payload.getAudience().add("something"); } @@ -104,7 +99,8 @@ public void shouldGetNullAudienceIfMissing() { @Test public void shouldGetExpiresAt() { assertThat(payload, is(notNullValue())); - assertThat(payload.getExpiresAt(), is(expiresAt)); + assertThat(payload.getExpiresAt(), is(Date.from(expiresAt))); + assertThat(payload.getExpiresAtAsInstant(), is(expiresAt)); } @Test @@ -112,12 +108,14 @@ public void shouldGetNullExpiresAtIfMissing() { PayloadImpl payload = new PayloadImpl(null, null, null, null, null, null, null, null, objectReader); assertThat(payload, is(notNullValue())); assertThat(payload.getExpiresAt(), is(nullValue())); + assertThat(payload.getExpiresAtAsInstant(), is(nullValue())); } @Test public void shouldGetNotBefore() { assertThat(payload, is(notNullValue())); - assertThat(payload.getNotBefore(), is(notBefore)); + assertThat(payload.getNotBefore(), is(Date.from(notBefore))); + assertThat(payload.getNotBeforeAsInstant(), is(notBefore)); } @Test @@ -125,12 +123,14 @@ public void shouldGetNullNotBeforeIfMissing() { PayloadImpl payload = new PayloadImpl(null, null, null, null, null, null, null, null, objectReader); assertThat(payload, is(notNullValue())); assertThat(payload.getNotBefore(), is(nullValue())); + assertThat(payload.getNotBeforeAsInstant(), is(nullValue())); } @Test public void shouldGetIssuedAt() { assertThat(payload, is(notNullValue())); - assertThat(payload.getIssuedAt(), is(issuedAt)); + assertThat(payload.getIssuedAt(), is(Date.from(issuedAt))); + assertThat(payload.getIssuedAtAsInstant(), is(issuedAt)); } @Test @@ -138,6 +138,7 @@ public void shouldGetNullIssuedAtIfMissing() { PayloadImpl payload = new PayloadImpl(null, null, null, null, null, null, null, null, objectReader); assertThat(payload, is(notNullValue())); assertThat(payload.getIssuedAt(), is(nullValue())); + assertThat(payload.getIssuedAtAsInstant(), is(nullValue())); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/interfaces/ClaimTest.java b/lib/src/test/java/com/auth0/jwt/interfaces/ClaimTest.java new file mode 100644 index 00000000..120f6a9d --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/interfaces/ClaimTest.java @@ -0,0 +1,93 @@ +package com.auth0.jwt.interfaces; + +import com.auth0.jwt.exceptions.JWTDecodeException; +import org.junit.Test; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ClaimTest { + + @Test + public void shouldGetInstantUsingDefault() { + Date date = new Date(1646667492000L); + Claim claim = new ClaimImplForTest(date); + assertThat(claim.asInstant(), is(date.toInstant())); + } + + @Test + public void shouldGetNullInstantUsingDefault() { + Claim claim = new ClaimImplForTest(null); + assertThat(claim.asInstant(), is(nullValue())); + } + + /** + * Implementation that does not override {@code asInstant()} + */ + static class ClaimImplForTest implements Claim { + private final Date date; + + ClaimImplForTest(Date date) { + this.date = date; + } + + @Override + public boolean isNull() { + return false; + } + + @Override + public Boolean asBoolean() { + return null; + } + + @Override + public Integer asInt() { + return null; + } + + @Override + public Long asLong() { + return null; + } + + @Override + public Double asDouble() { + return null; + } + + @Override + public String asString() { + return null; + } + + @Override + public Date asDate() { + return date; + } + + @Override + public T[] asArray(Class tClazz) throws JWTDecodeException { + return null; + } + + @Override + public List asList(Class tClazz) throws JWTDecodeException { + return null; + } + + @Override + public Map asMap() throws JWTDecodeException { + return null; + } + + @Override + public T as(Class tClazz) throws JWTDecodeException { + return null; + } + } +} diff --git a/lib/src/test/java/com/auth0/jwt/interfaces/PayloadTest.java b/lib/src/test/java/com/auth0/jwt/interfaces/PayloadTest.java new file mode 100644 index 00000000..c5d2bd00 --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/interfaces/PayloadTest.java @@ -0,0 +1,83 @@ +package com.auth0.jwt.interfaces; + +import org.junit.Test; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class PayloadTest { + + @Test + public void shouldGetInstantFromDefault() { + Date date = new Date(1646667492000L); + Payload payload = new PayloadImplForTest(date); + assertThat(payload.getExpiresAtAsInstant(), is(date.toInstant())); + assertThat(payload.getIssuedAtAsInstant(), is(date.toInstant())); + assertThat(payload.getNotBeforeAsInstant(), is(date.toInstant())); + } + + @Test + public void shouldGetInstantFromDefaultAsNu() { + Payload payload = new PayloadImplForTest(null); + assertThat(payload.getExpiresAtAsInstant(), is(nullValue())); + assertThat(payload.getIssuedAtAsInstant(), is(nullValue())); + assertThat(payload.getNotBeforeAsInstant(), is(nullValue())); + } + + static class PayloadImplForTest implements Payload { + private final Date date; + + PayloadImplForTest(Date date) { + this.date = date; + } + + @Override + public String getIssuer() { + return null; + } + + @Override + public String getSubject() { + return null; + } + + @Override + public List getAudience() { + return null; + } + + @Override + public Date getExpiresAt() { + return date; + } + + @Override + public Date getNotBefore() { + return date; + } + + @Override + public Date getIssuedAt() { + return date; + } + + @Override + public String getId() { + return null; + } + + @Override + public Claim getClaim(String name) { + return null; + } + + @Override + public Map getClaims() { + return null; + } + } +}