Refactored generic get with required type to handle the official claim types that are dates. Updated javadocs to reflect 'require' language.

This commit is contained in:
Micah Silverman 2015-09-23 17:03:07 -04:00
parent 5d320d22a5
commit 6401727b2a
4 changed files with 69 additions and 29 deletions

View File

@ -28,15 +28,17 @@ public interface JwtParser {
public static final char SEPARATOR_CHAR = '.'; public static final char SEPARATOR_CHAR = '.';
/** /**
* Sets an expected value for the jti claim. * Ensures that the specified {@code jti} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param id * @param id
* @return the parser for method chaining. * @return the parser method for chaining.
*/ */
JwtParser requireId(String id); JwtParser requireId(String id);
/** /**
* Sets an expected value for the subject claim. * Ensures that the specified {@code sub} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param subject * @param subject
* @return the parser for method chaining. * @return the parser for method chaining.
@ -44,7 +46,8 @@ public interface JwtParser {
JwtParser requireSubject(String subject); JwtParser requireSubject(String subject);
/** /**
* Sets an expected value for the audience claim. * Ensures that the specified {@code aud} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param audience * @param audience
* @return the parser for method chaining. * @return the parser for method chaining.
@ -52,7 +55,8 @@ public interface JwtParser {
JwtParser requireAudience(String audience); JwtParser requireAudience(String audience);
/** /**
* Sets an expected value for the issuer claim. * Ensures that the specified {@code iss} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param issuer * @param issuer
* @return the parser for method chaining. * @return the parser for method chaining.
@ -60,7 +64,8 @@ public interface JwtParser {
JwtParser requireIssuer(String issuer); JwtParser requireIssuer(String issuer);
/** /**
* Sets an expected value for the issuedAt claim. * Ensures that the specified {@code iat} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param issuedAt * @param issuedAt
* @return the parser for method chaining. * @return the parser for method chaining.
@ -68,7 +73,8 @@ public interface JwtParser {
JwtParser requireIssuedAt(Date issuedAt); JwtParser requireIssuedAt(Date issuedAt);
/** /**
* Sets an expected value for the expiration claim. * Ensures that the specified {@code exp} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param expiration * @param expiration
* @return the parser for method chaining. * @return the parser for method chaining.
@ -76,7 +82,8 @@ public interface JwtParser {
JwtParser requireExpiration(Date expiration); JwtParser requireExpiration(Date expiration);
/** /**
* Sets an expected value for the notBefore claim. * Ensures that the specified {@code nbf} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* @param notBefore * @param notBefore
* @return the parser for method chaining * @return the parser for method chaining
@ -84,15 +91,14 @@ public interface JwtParser {
JwtParser requireNotBefore(Date notBefore); JwtParser requireNotBefore(Date notBefore);
/** /**
* Sets an expected value for any given claim name. * Ensures that the specified {@code claimName} value is present when parsing the JWT. If not present,
* an exception will be thrown indicating that the JWT is invalid and may not be used.
* *
* If an expectation is set for a particular claim name and the JWT being parsed does not have that claim set, * If a particular claim is required and the JWT being parsed does not have that claim set,
* a {@Link MissingClaimException} will be thrown. * a {@Link MissingClaimException} will be thrown.
* *
* If an expectation is set for a particular claim name and the JWT being parsed has a value that is different than * If a particular claim is required and the JWT being parsed has a value that is different than
* the expected value, a {@link IncorrectClaimException} will be thrown. * the required value, a {@link IncorrectClaimException} will be thrown.
*
* If either {@code claimName} is null or empty or {@code value} is null, the expectation is simply ignored.
* *
* @param claimName * @param claimName
* @param value * @param value

View File

@ -66,7 +66,7 @@ public class DefaultClaims extends JwtMap implements Claims {
@Override @Override
public Date getExpiration() { public Date getExpiration() {
return getDate(Claims.EXPIRATION); return get(Claims.EXPIRATION, Date.class);
} }
@Override @Override
@ -77,7 +77,7 @@ public class DefaultClaims extends JwtMap implements Claims {
@Override @Override
public Date getNotBefore() { public Date getNotBefore() {
return getDate(Claims.NOT_BEFORE); return get(Claims.NOT_BEFORE, Date.class);
} }
@Override @Override
@ -88,7 +88,7 @@ public class DefaultClaims extends JwtMap implements Claims {
@Override @Override
public Date getIssuedAt() { public Date getIssuedAt() {
return getDate(Claims.ISSUED_AT); return get(Claims.ISSUED_AT, Date.class);
} }
@Override @Override
@ -113,6 +113,13 @@ public class DefaultClaims extends JwtMap implements Claims {
Object value = get(claimName); Object value = get(claimName);
if (value == null) { return null; } if (value == null) { return null; }
if (Claims.EXPIRATION.equals(claimName) ||
Claims.ISSUED_AT.equals(claimName) ||
Claims.NOT_BEFORE.equals(claimName)
) {
value = getDate(claimName);
}
if (requiredType == Date.class && value instanceof Long) { if (requiredType == Date.class && value instanceof Long) {
value = new Date((Long)value); value = new Date((Long)value);
} }

View File

@ -381,16 +381,18 @@ public class DefaultJwtParser implements JwtParser {
Object expectedClaimValue = expectedClaims.get(expectedClaimName); Object expectedClaimValue = expectedClaims.get(expectedClaimName);
Object actualClaimValue = claims.get(expectedClaimName); Object actualClaimValue = claims.get(expectedClaimName);
if (Claims.ISSUED_AT.equals(expectedClaimName)) { if (
expectedClaimValue = expectedClaims.getIssuedAt(); Claims.ISSUED_AT.equals(expectedClaimName) ||
actualClaimValue = claims.getIssuedAt(); Claims.EXPIRATION.equals(expectedClaimName) ||
} else if (Claims.EXPIRATION.equals(expectedClaimName)) { Claims.NOT_BEFORE.equals(expectedClaimName)
expectedClaimValue = expectedClaims.getExpiration(); ) {
actualClaimValue = claims.getExpiration(); expectedClaimValue = expectedClaims.get(expectedClaimName, Date.class);
} else if (Claims.NOT_BEFORE.equals(expectedClaimName)) { actualClaimValue = claims.get(expectedClaimName, Date.class);
expectedClaimValue = expectedClaims.getNotBefore(); } else if (
actualClaimValue = claims.getNotBefore(); expectedClaimValue instanceof Date &&
} else if (expectedClaimValue instanceof Date && actualClaimValue != null && actualClaimValue instanceof Long) { actualClaimValue != null &&
actualClaimValue instanceof Long
) {
actualClaimValue = new Date((Long)actualClaimValue); actualClaimValue = new Date((Long)actualClaimValue);
} }

View File

@ -64,7 +64,7 @@ class DefaultClaimsTest {
def actual = new Date(); def actual = new Date();
claims.put("aDate", actual) claims.put("aDate", actual)
Date expected = claims.get("aDate", Date.class); Date expected = claims.get("aDate", Date.class);
assertEquals(expected, actual); assertEquals(expected, actual)
} }
@Test @Test
@ -73,6 +73,31 @@ class DefaultClaimsTest {
// note that Long is stored in claim // note that Long is stored in claim
claims.put("aDate", actual.getTime()) claims.put("aDate", actual.getTime())
Date expected = claims.get("aDate", Date.class); Date expected = claims.get("aDate", Date.class);
assertEquals(expected, actual); assertEquals(expected, actual)
} }
@Test
void testGetClaimExpiration_Success() {
def now = new Date(System.currentTimeMillis())
claims.setExpiration(now)
Date expected = claims.get("exp", Date.class)
assertEquals(expected, claims.getExpiration())
}
@Test
void testGetClaimIssuedAt_Success() {
def now = new Date(System.currentTimeMillis())
claims.setIssuedAt(now)
Date expected = claims.get("iat", Date.class)
assertEquals(expected, claims.getIssuedAt())
}
@Test
void testGetClaimNotBefore_Success() {
def now = new Date(System.currentTimeMillis())
claims.setNotBefore(now)
Date expected = claims.get("nbf", Date.class)
assertEquals(expected, claims.getNotBefore())
}
} }