diff --git a/lib/src/main/java/com/auth0/jwt/ClockImpl.java b/lib/src/main/java/com/auth0/jwt/ClockImpl.java index 45e3edfc..d565acc7 100644 --- a/lib/src/main/java/com/auth0/jwt/ClockImpl.java +++ b/lib/src/main/java/com/auth0/jwt/ClockImpl.java @@ -4,9 +4,9 @@ import java.util.Date; -final class ClockImpl implements Clock { +public final class ClockImpl implements Clock { - ClockImpl() { + public ClockImpl() { } @Override diff --git a/lib/src/main/java/com/auth0/jwt/JWT.java b/lib/src/main/java/com/auth0/jwt/JWT.java deleted file mode 100644 index f8e5cfc3..00000000 --- a/lib/src/main/java/com/auth0/jwt/JWT.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.auth0.jwt; - -import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.interfaces.DecodedJWT; -import com.auth0.jwt.interfaces.Verification; - -@SuppressWarnings("WeakerAccess") -public abstract class JWT { - - /** - * Decode a given Json Web Token. - *

- * Note that this method doesn't verify the token's signature! Use it only if you trust the token or you already verified it. - * - * @param token with jwt format as string. - * @return a decoded JWT. - * @throws JWTDecodeException if any part of the token contained an invalid jwt or JSON format of each of the jwt parts. - */ - public static DecodedJWT decode(String token) throws JWTDecodeException { - return new JWTDecoder(token); - } - - /** - * Returns a {@link JWTVerifier} builder with the algorithm to be used to validate token signature. - * - * @param algorithm that will be used to verify the token's signature. - * @return {@link JWTVerifier} builder - * @throws IllegalArgumentException if the provided algorithm is null. - */ - public static Verification require(Algorithm algorithm) { - return JWTVerifier.init(algorithm); - } - - /** - * Returns a Json Web Token builder used to create and sign tokens - * - * @return a token builder. - */ - public static JWTCreator.Builder create() { - return JWTCreator.init(); - } -} diff --git a/lib/src/main/java/com/auth0/jwt/JWTDecoder.java b/lib/src/main/java/com/auth0/jwt/JWTDecoder.java index 7921c128..367643e9 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTDecoder.java +++ b/lib/src/main/java/com/auth0/jwt/JWTDecoder.java @@ -17,13 +17,13 @@ * The JWTDecoder class holds the decode method to parse a given JWT token into it's JWT representation. */ @SuppressWarnings("WeakerAccess") -final class JWTDecoder implements DecodedJWT { +public final class JWTDecoder implements DecodedJWT { private final String[] parts; private final Header header; private final Payload payload; - JWTDecoder(String jwt) throws JWTDecodeException { + public JWTDecoder(String jwt) throws JWTDecodeException { parts = TokenUtils.splitToken(jwt); final JWTParser converter = new JWTParser(); String headerJson; @@ -64,12 +64,12 @@ public Claim getHeaderClaim(String name) { } @Override - public String getIssuer() { + public List getIssuer() { return payload.getIssuer(); } @Override - public String getSubject() { + public List getSubject() { return payload.getSubject(); } diff --git a/lib/src/main/java/com/auth0/jwt/TokenUtils.java b/lib/src/main/java/com/auth0/jwt/TokenUtils.java index cb6cff3e..46f05d74 100644 --- a/lib/src/main/java/com/auth0/jwt/TokenUtils.java +++ b/lib/src/main/java/com/auth0/jwt/TokenUtils.java @@ -2,7 +2,7 @@ import com.auth0.jwt.exceptions.JWTDecodeException; -abstract class TokenUtils { +public abstract class TokenUtils { /** * Splits the given token on the "." chars into a String array with 3 parts. @@ -11,7 +11,7 @@ abstract class TokenUtils { * @return the array representing the 3 parts of the token. * @throws JWTDecodeException if the Token doesn't have 3 parts. */ - static String[] splitToken(String token) throws JWTDecodeException { + public static String[] splitToken(String token) throws JWTDecodeException { String[] parts = token.split("\\."); if (parts.length == 2 && token.endsWith(".")) { //Tokens with alg='none' have empty String as Signature. diff --git a/lib/src/main/java/com/auth0/jwt/algorithms/Algorithm.java b/lib/src/main/java/com/auth0/jwt/algorithms/Algorithm.java index 12080a02..e6e60a56 100644 --- a/lib/src/main/java/com/auth0/jwt/algorithms/Algorithm.java +++ b/lib/src/main/java/com/auth0/jwt/algorithms/Algorithm.java @@ -373,4 +373,17 @@ public String toString() { * @throws SignatureGenerationException if the Key is invalid. */ public abstract byte[] sign(byte[] contentBytes) throws SignatureGenerationException; + + @Override + public boolean equals(Object algorithmParam) { + if(this == algorithmParam) + return true; + if(algorithmParam == null) + return false; + if(getClass() != algorithmParam.getClass()) + return false; + + Algorithm algorithm = (Algorithm) algorithmParam; + return this.description.equals(algorithm.description) && this.name.equals(algorithm.name); + } } diff --git a/lib/src/main/java/com/auth0/jwt/creators/AccessJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/AccessJwtCreator.java new file mode 100644 index 00000000..af19342a --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/AccessJwtCreator.java @@ -0,0 +1,237 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.jwts.JWT; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * The AccessJwtCreator class holds the sign method to generate a complete Access JWT (with Signature) from a given Header and Payload content. + */ +public class AccessJwtCreator { + + protected JWTCreator.Builder jwt; + protected HashMap addedClaims; + protected Set publicClaims; + + public AccessJwtCreator() { + jwt = JWT.create(); + addedClaims = new HashMap() {{ + put("Issuer", false); + put("Subject", false); + put("Iat", false); + }}; + publicClaims = new HashSet() {{ + add(PublicClaims.ISSUER); + add(PublicClaims.SUBJECT); + add(PublicClaims.EXPIRES_AT); + add(PublicClaims.NOT_BEFORE); + add(PublicClaims.ISSUED_AT); + add(PublicClaims.JWT_ID); + add(PublicClaims.AUDIENCE); + }}; + } + + /** + * Add a specific Issuer ("issuer") claim to the Payload. + * Allows for multiple issuers + * + * @param issuer the Issuer value. + * @return this same Builder instance. + */ + public AccessJwtCreator withIssuer(String... issuer) { + jwt.withIssuer(issuer); + addedClaims.put("Issuer", true); + return this; + } + + /** + * Add a specific Subject ("subject") claim to the Payload. + * Allows for multiple subjects + * + * @param subject the Subject value. + * @return this same Builder instance. + */ + public AccessJwtCreator withSubject(String... subject) { + jwt.withSubject(subject); + addedClaims.put("Subject", true); + return this; + } + + /** + * Add a specific Audience ("audience") claim to the Payload. + * Allows for multiple audience + * + * @param audience the Audience value. + * @return this same Builder instance. + */ + public AccessJwtCreator withAudience(String... audience) { + jwt.withAudience(audience); + return this; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. + * + * @param iat the Issued At value. + * @return this same Builder instance. + */ + public AccessJwtCreator withIat(Date iat) { + jwt.withIssuedAt(iat); + addedClaims.put("Iat", true); + return this; + } + + /** + * Add a specific Expires At ("exp") claim to the Payload. + * + * @param exp the Expires At value. + * @return this same Builder instance. + */ + public AccessJwtCreator withExp(Date exp) { + jwt.withExpiresAt(exp); + return this; + } + + /** + * Require a specific Claim value. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public AccessJwtCreator withNonStandardClaim(String name, String value) { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 AccessJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 AccessJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 AccessJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 AccessJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 AccessJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Require a specific Array Claim to contain at least the given items. + * + * @param name the Claim's name. + * @param items the items the Claim must contain. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public AccessJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException { + jwt.withArrayClaim(name, items); + if(publicClaims.contains(name)) + addedClaims.put(name, true); + return this; + } + + /** + * Developer explicitly specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public AccessJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static AccessJwtCreator build() { + return new AccessJwtCreator(); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/creators/ExtendedJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/ExtendedJwtCreator.java new file mode 100644 index 00000000..f5d358d4 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/ExtendedJwtCreator.java @@ -0,0 +1,59 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; + +import java.util.Date; + +/** + * The ExtendedJwtCreator class holds the sign method to generate a complete Extended JWT (with Signature) from a given Header and Payload content. + */ +public class ExtendedJwtCreator extends GoogleJwtCreator{ + + public ExtendedJwtCreator() { + super(); + } + + /** + * Add a specific Note Before ("nbf") claim to the Payload. + * + * @param nbf the nbf value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withNbf(Date nbf) { + jwt.withNotBefore(nbf); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static ExtendedJwtCreator build() { + return new ExtendedJwtCreator(); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/creators/FbJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/FbJwtCreator.java new file mode 100644 index 00000000..43956de6 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/FbJwtCreator.java @@ -0,0 +1,218 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.jwts.JWT; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * The FbJwtCreator class holds the sign method to generate a complete FB JWT (with Signature) from a given Header and Payload content. + */ +public class FbJwtCreator { + + protected JWTCreator.Builder jwt; + protected HashMap addedClaims; + protected Set publicClaims; + + public FbJwtCreator() { + jwt = JWT.create(); + addedClaims = new HashMap() {{ + put("UserId", false); + put("AppId", false); + put("Iat", false); + }}; + publicClaims = new HashSet() {{ + add(PublicClaims.ISSUED_AT); + add(PublicClaims.EXPIRES_AT); + }}; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. + * + * @param iat the Issued At value. + * @return this same Builder instance. + */ + public FbJwtCreator withIat(Date iat) { + jwt.withIssuedAt(iat); + addedClaims.put("Iat", true); + return this; + } + + /** + * Add a specific Expires At ("exp") claim to the Payload. + * + * @param exp the Expires At value. + * @return this same Builder instance. + */ + public FbJwtCreator withExp(Date exp) { + jwt.withExpiresAt(exp); + return this; + } + + /** + * Require a specific userId ("userId") claim. + * + * @param userId the required userId value + * @return this same Verification instance. + */ + public FbJwtCreator withUserId(String userId) { + jwt.withNonStandardClaim("userId", userId); + addedClaims.put("UserId", true); + return this; + } + + /** + * Require a specific appId ("appId") claim. + * + * @param appId the required appId value + * @return this same Verification instance. + */ + public FbJwtCreator withAppId(String appId) { + jwt.withNonStandardClaim("appId", appId); + addedClaims.put("AppId", true); + return this; + } + + /** + * Require a specific Claim value. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public FbJwtCreator withNonStandardClaim(String name, String value) { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 FbJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 FbJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 FbJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 FbJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 FbJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Require a specific Array Claim to contain at least the given items. + * + * @param name the Claim's name. + * @param items the items the Claim must contain. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public FbJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException { + jwt.withArrayClaim(name, items); + if(publicClaims.contains(name)) + addedClaims.put(name, true); + return this; + } + + /** + * Developer explicitly specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public FbJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static FbJwtCreator build() { + return new FbJwtCreator(); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/creators/GoogleJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/GoogleJwtCreator.java new file mode 100644 index 00000000..8eb69b55 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/GoogleJwtCreator.java @@ -0,0 +1,277 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.jwts.JWT; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * The GoogleJwtCreator class holds the sign method to generate a complete Google JWT (with Signature) from a given Header and Payload content. + */ +public class GoogleJwtCreator { + + protected JWTCreator.Builder jwt; + protected HashMap addedClaims; + protected Set publicClaims; + + public GoogleJwtCreator() { + jwt = JWT.create(); + addedClaims = new HashMap() {{ + put("Name", false); + put("Email", false); + put("Picture", false); + put("Issuer", false); + put("Subject", false); + put("Iat", false); + }}; + publicClaims = new HashSet() {{ + add(PublicClaims.ISSUER); + add(PublicClaims.SUBJECT); + add(PublicClaims.EXPIRES_AT); + add(PublicClaims.NOT_BEFORE); + add(PublicClaims.ISSUED_AT); + add(PublicClaims.JWT_ID); + add(PublicClaims.AUDIENCE); + }}; + } + + + /** + * Add a specific Name ("name") claim to the Payload. + * + * @param name the Name value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withName(String name) { + jwt.withNonStandardClaim("name", name); + addedClaims.put("Name", true); + return this; + } + + /** + * Add a specific Email ("email") claim to the Payload. + * + * @param email the Email value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withEmail(String email) { + jwt.withNonStandardClaim("email", email); + addedClaims.put("Email", true); + return this; + } + + /** + * Add a specific Picture ("picture") claim to the Payload. + * + * @param picture the Picture value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withPicture(String picture) { + jwt.withNonStandardClaim("picture", picture); + addedClaims.put("Picture", true); + return this; + } + + /** + * Add a specific Issuer ("issuer") claim to the Payload. + * Allows for multiple issuers + * + * @param issuer the Issuer value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withIssuer(String... issuer) { + jwt.withIssuer(issuer); + addedClaims.put("Issuer", true); + return this; + } + + /** + * Add a specific Subject ("subject") claim to the Payload. + * Allows for multiple subjects + * + * @param subject the Subject value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withSubject(String... subject) { + jwt.withSubject(subject); + addedClaims.put("Subject", true); + return this; + } + + /** + * Add a specific Audience ("audience") claim to the Payload. + * Allows for multiple audience + * + * @param audience the Audience value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withAudience(String... audience) { + jwt.withAudience(audience); + return this; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. + * + * @param iat the Issued At value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withIat(Date iat) { + jwt.withIssuedAt(iat); + addedClaims.put("Iat", true); + return this; + } + + /** + * Add a specific Expires At ("exp") claim to the Payload. + * + * @param exp the Expires At value. + * @return this same Builder instance. + */ + public GoogleJwtCreator withExp(Date exp) { + jwt.withExpiresAt(exp); + return this; + } + + /** + * Require a specific Claim value. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public GoogleJwtCreator withNonStandardClaim(String name, String value) { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 GoogleJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 GoogleJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 GoogleJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 GoogleJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 GoogleJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Require a specific Array Claim to contain at least the given items. + * + * @param name the Claim's name. + * @param items the items the Claim must contain. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public GoogleJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException { + jwt.withArrayClaim(name, items); + if(publicClaims.contains(name)) + addedClaims.put(name, true); + return this; + } + + /** + * Developer explicitly specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public GoogleJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static GoogleJwtCreator build() { + return new GoogleJwtCreator(); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/creators/ImplicitJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/ImplicitJwtCreator.java new file mode 100644 index 00000000..9169fd37 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/ImplicitJwtCreator.java @@ -0,0 +1,223 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.jwts.JWT; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * The ImplicitJwtCreator class holds the sign method to generate a complete Implicit JWT (with Signature) from a given Header and Payload content. + */ +public class ImplicitJwtCreator { + + protected JWTCreator.Builder jwt; + protected HashMap addedClaims; + protected Set publicClaims; + + public ImplicitJwtCreator() { + jwt = JWT.create(); + addedClaims = new HashMap() {{ + put("Issuer", false); + put("Subject", false); + put("Iat", false); + }}; + publicClaims = new HashSet() {{ + add(PublicClaims.ISSUER); + add(PublicClaims.SUBJECT); + add(PublicClaims.ISSUED_AT); + add(PublicClaims.AUDIENCE); + }}; + } + + /** + * Add a specific Issuer ("issuer") claim to the Payload. + * Allows for multiple issuers + * + * @param issuer the Issuer value. + * @return this same Builder instance. + */ + public ImplicitJwtCreator withIssuer(String... issuer) { + jwt.withIssuer(issuer); + addedClaims.put("Issuer", true); + return this; + } + + /** + * Add a specific Subject ("subject") claim to the Payload. + * Allows for multiple subjects + * + * @param subject the Subject value. + * @return this same Builder instance. + */ + public ImplicitJwtCreator withSubject(String... subject) { + jwt.withSubject(subject); + addedClaims.put("Subject", true); + return this; + } + + /** + * Add a specific Audience ("audience") claim to the Payload. + * Allows for multiple audience + * + * @param audience the Audience value. + * @return this same Builder instance. + */ + public ImplicitJwtCreator withAudience(String... audience) { + jwt.withAudience(audience); + return this; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. + * + * @param iat the Issued At value. + * @return this same Builder instance. + */ + public ImplicitJwtCreator withIat(Date iat) { + jwt.withIssuedAt(iat); + addedClaims.put("Iat", true); + return this; + } + + /** + * Require a specific Claim value. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public ImplicitJwtCreator withNonStandardClaim(String name, String value) { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ImplicitJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ImplicitJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ImplicitJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ImplicitJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ImplicitJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Require a specific Array Claim to contain at least the given items. + * + * @param name the Claim's name. + * @param items the items the Claim must contain. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public ImplicitJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException { + jwt.withArrayClaim(name, items); + if(publicClaims.contains(name)) + addedClaims.put(name, true); + return this; + } + + /** + * Developer explicitly specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public ImplicitJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static ImplicitJwtCreator build() { + return new ImplicitJwtCreator(); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/JWTCreator.java b/lib/src/main/java/com/auth0/jwt/creators/JWTCreator.java similarity index 87% rename from lib/src/main/java/com/auth0/jwt/JWTCreator.java rename to lib/src/main/java/com/auth0/jwt/creators/JWTCreator.java index a0889876..2183f675 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTCreator.java +++ b/lib/src/main/java/com/auth0/jwt/creators/JWTCreator.java @@ -1,4 +1,4 @@ -package com.auth0.jwt; +package com.auth0.jwt.creators; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTCreationException; @@ -48,7 +48,7 @@ private JWTCreator(Algorithm algorithm, Map headerClaims, Map payloadClaims; private Map headerClaims; + private boolean isNoneAlgorithmAllowed; Builder() { this.payloadClaims = new HashMap<>(); this.headerClaims = new HashMap<>(); + this.isNoneAlgorithmAllowed = false; } /** @@ -89,28 +91,31 @@ public Builder withKeyId(String keyId) { /** * Add a specific Issuer ("iss") claim to the Payload. + * Allows for multiple issuers * * @param issuer the Issuer value. * @return this same Builder instance. */ - public Builder withIssuer(String issuer) { + public Builder withIssuer(String... issuer) { addClaim(PublicClaims.ISSUER, issuer); return this; } /** * Add a specific Subject ("sub") claim to the Payload. + * Allows for multiple subjects * * @param subject the Subject value. * @return this same Builder instance. */ - public Builder withSubject(String subject) { + public Builder withSubject(String... subject) { addClaim(PublicClaims.SUBJECT, subject); return this; } /** * Add a specific Audience ("aud") claim to the Payload. + * Allows for multiple audience * * @param audience the Audience value. * @return this same Builder instance. @@ -164,6 +169,22 @@ public Builder withJWTId(String jwtId) { return this; } + /** + * Developer specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public Builder setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + this.isNoneAlgorithmAllowed = isNoneAlgorithmAllowed; + return this; + } + + public boolean getIsNoneAlgorithmAllowed() { + return this.isNoneAlgorithmAllowed; + } + /** * Add a custom Claim value. * @@ -172,7 +193,7 @@ public Builder withJWTId(String jwtId) { * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, Boolean value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -186,7 +207,7 @@ public Builder withClaim(String name, Boolean value) throws IllegalArgumentExcep * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, Integer value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -200,7 +221,7 @@ public Builder withClaim(String name, Integer value) throws IllegalArgumentExcep * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, Long value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, Long value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -214,7 +235,7 @@ public Builder withClaim(String name, Long value) throws IllegalArgumentExceptio * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, Double value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, Double value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -228,7 +249,7 @@ public Builder withClaim(String name, Double value) throws IllegalArgumentExcept * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, String value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, String value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -242,7 +263,7 @@ public Builder withClaim(String name, String value) throws IllegalArgumentExcept * @return this same Builder instance. * @throws IllegalArgumentException if the name is null. */ - public Builder withClaim(String name, Date value) throws IllegalArgumentException { + public Builder withNonStandardClaim(String name, Date value) throws IllegalArgumentException { assertNonNull(name); addClaim(name, value); return this; @@ -298,7 +319,7 @@ public Builder withArrayClaim(String name, Long[] items) throws IllegalArgumentE * @throws IllegalArgumentException if the provided algorithm is null. * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. */ - public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException { + public String sign(Algorithm algorithm) throws Exception { if (algorithm == null) { throw new IllegalArgumentException("The Algorithm cannot be null."); } @@ -311,7 +332,7 @@ public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCrea return new JWTCreator(algorithm, headerClaims, payloadClaims).sign(); } - private void assertNonNull(String name) { + protected void assertNonNull(String name) { if (name == null) { throw new IllegalArgumentException("The Custom Claim's name can't be null."); } diff --git a/lib/src/main/java/com/auth0/jwt/creators/ScopedJwtCreator.java b/lib/src/main/java/com/auth0/jwt/creators/ScopedJwtCreator.java new file mode 100644 index 00000000..6b2d6b05 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/creators/ScopedJwtCreator.java @@ -0,0 +1,251 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.jwts.JWT; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * The ScopedJwtCreator class holds the sign method to generate a complete Scoped JWT (with Signature) from a given Header and Payload content. + */ +public class ScopedJwtCreator{ + + protected JWTCreator.Builder jwt; + protected HashMap addedClaims; + protected Set publicClaims; + + public ScopedJwtCreator() { + jwt = JWT.create(); + addedClaims = new HashMap() {{ + put("Scope", false); + put("Issuer", false); + put("Subject", false); + put("Iat", false); + }}; + publicClaims = new HashSet() {{ + add(PublicClaims.ISSUER); + add(PublicClaims.SUBJECT); + add(PublicClaims.EXPIRES_AT); + add(PublicClaims.NOT_BEFORE); + add(PublicClaims.ISSUED_AT); + add(PublicClaims.JWT_ID); + add(PublicClaims.AUDIENCE); + }}; + } + + /** + * Add a specific Scope ("scope") claim to the Payload. + * Allows for multiple issuers + * + * @param scope the Scope value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withScope(String scope) { + jwt.withNonStandardClaim("scope", scope); + addedClaims.put("Scope", true); + return this; + } + + /** + * Add a specific Issuer ("issuer") claim to the Payload. + * Allows for multiple issuers + * + * @param issuer the Issuer value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withIssuer(String... issuer) { + jwt.withIssuer(issuer); + addedClaims.put("Issuer", true); + return this; + } + + /** + * Add a specific Subject ("subject") claim to the Payload. + * Allows for multiple subjects + * + * @param subject the Subject value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withSubject(String... subject) { + jwt.withSubject(subject); + addedClaims.put("Subject", true); + return this; + } + + /** + * Add a specific Audience ("audience") claim to the Payload. + * Allows for multiple audience + * + * @param audience the Audience value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withAudience(String... audience) { + jwt.withAudience(audience); + return this; + } + + /** + * Add a specific Issued At ("iat") claim to the Payload. + * + * @param iat the Issued At value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withIat(Date iat) { + jwt.withIssuedAt(iat); + addedClaims.put("Iat", true); + return this; + } + + /** + * Add a specific Expires At ("exp") claim to the Payload. + * + * @param exp the Expires At value. + * @return this same Builder instance. + */ + public ScopedJwtCreator withExp(Date exp) { + jwt.withExpiresAt(exp); + return this; + } + + /** + * Require a specific Claim value. + * + * @param name the Claim's name. + * @param value the Claim's value. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public ScopedJwtCreator withNonStandardClaim(String name, String value) { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ScopedJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ScopedJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ScopedJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ScopedJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Add a custom Claim value. + * + * @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 ScopedJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + jwt.withNonStandardClaim(name, value); + return this; + } + + /** + * Require a specific Array Claim to contain at least the given items. + * + * @param name the Claim's name. + * @param items the items the Claim must contain. + * @return this same Verification instance. + * @throws IllegalArgumentException if the name is null. + */ + public ScopedJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException { + jwt.withArrayClaim(name, items); + if(publicClaims.contains(name)) + addedClaims.put(name, true); + return this; + } + + /** + * Developer explicitly specifies whether they want to accept + * NONE algorithms or not. + * + * @param isNoneAlgorithmAllowed + * @return + */ + public ScopedJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) { + jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed); + return this; + } + + /** + * Creates a new JWT and signs it with the given algorithm. + * + * @param algorithm used to sign the JWT + * @return a new JWT token + * @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in + * @throws IllegalArgumentException if the provided algorithm is null. + * @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key. + */ + public String sign(Algorithm algorithm) throws Exception { + if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) { + throw new IllegalAccessException("None algorithm isn't allowed"); + } + String JWS = jwt.sign(algorithm); + verifyClaims(); + return JWS; + } + + /** + * Verifies that all the standard claims were provided + * @throws Exception if all the standard claims weren't provided + */ + private void verifyClaims() throws Exception { + for(String claim : addedClaims.keySet()) + if(!addedClaims.get(claim)) + throw new Exception("Standard claim: " + claim + " has not been set"); + } + + public static ScopedJwtCreator build() { + return new ScopedJwtCreator(); + } +} 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 38068872..63dcfce4 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java +++ b/lib/src/main/java/com/auth0/jwt/impl/PayloadDeserializer.java @@ -31,8 +31,8 @@ public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOE throw new JWTDecodeException("Parsing the Payload's JSON resulted on a Null map"); } - String issuer = getString(tree, PublicClaims.ISSUER); - String subject = getString(tree, PublicClaims.SUBJECT); + List issuer = getStringOrArray(tree, PublicClaims.ISSUER); + List subject = getStringOrArray(tree, PublicClaims.SUBJECT); List audience = getStringOrArray(tree, PublicClaims.AUDIENCE); Date expiresAt = getDateFromSeconds(tree, PublicClaims.EXPIRES_AT); Date notBefore = getDateFromSeconds(tree, PublicClaims.NOT_BEFORE); 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 dced3062..653ca06d 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java +++ b/lib/src/main/java/com/auth0/jwt/impl/PayloadImpl.java @@ -12,8 +12,8 @@ * The PayloadImpl class implements the Payload interface. */ class PayloadImpl implements Payload { - private final String issuer; - private final String subject; + private final List issuer; + private final List subject; private final List audience; private final Date expiresAt; private final Date notBefore; @@ -21,7 +21,7 @@ class PayloadImpl implements Payload { private final String jwtId; private final Map tree; - PayloadImpl(String issuer, String subject, List audience, Date expiresAt, Date notBefore, Date issuedAt, String jwtId, Map tree) { + PayloadImpl(List issuer, List subject, List audience, Date expiresAt, Date notBefore, Date issuedAt, String jwtId, Map tree) { this.issuer = issuer; this.subject = subject; this.audience = audience; @@ -37,12 +37,12 @@ Map getTree() { } @Override - public String getIssuer() { + public List getIssuer() { return issuer; } @Override - public String getSubject() { + public List getSubject() { return subject; } diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/ExtendedVerification.java b/lib/src/main/java/com/auth0/jwt/interfaces/ExtendedVerification.java new file mode 100644 index 00000000..b991be59 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/interfaces/ExtendedVerification.java @@ -0,0 +1,4 @@ +package com.auth0.jwt.interfaces; + +public interface ExtendedVerification { +} diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/GoogleVerification.java b/lib/src/main/java/com/auth0/jwt/interfaces/GoogleVerification.java new file mode 100644 index 00000000..dbd1eafc --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/interfaces/GoogleVerification.java @@ -0,0 +1,20 @@ +package com.auth0.jwt.interfaces; + +import java.util.Date; +import java.util.List; + +public interface GoogleVerification extends Verification{ + + Verification createVerifierForGoogle(String picture, String email, List issuer, + List audience, String name, long expLeeway, long iatLeeway); + + Verification withPicture(String picture); + + Verification withEmail(String email); + + GoogleVerification withName(String name); + + Verification createVerifierForExtended(String picture, String email, List issuer, + List audience, String name, long nbf, long expLeeway, long iatLeeway); + +} 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 0f639ab9..fffe3c73 100644 --- a/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java +++ b/lib/src/main/java/com/auth0/jwt/interfaces/Payload.java @@ -10,21 +10,21 @@ public interface Payload { /** - * Get the value of the "iss" claim, or null if it's not available. + * Get the value(s) of the "iss" claim, or null if it's not available. * * @return the Issuer value or null. */ - String getIssuer(); + List getIssuer(); /** - * Get the value of the "sub" claim, or null if it's not available. + * Get the value(s) of the "sub" claim, or null if it's not available. * * @return the Subject value or null. */ - String getSubject(); + List getSubject(); /** - * Get the value of the "aud" claim, or null if it's not available. + * Get the value(s) of the "aud" claim, or null if it's not available. * * @return the Audience value or null. */ diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java b/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java index 465ebe5d..a734d6c7 100644 --- a/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java +++ b/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java @@ -1,13 +1,14 @@ package com.auth0.jwt.interfaces; -import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.jwts.JWT; import java.util.Date; +import java.util.List; public interface Verification { - Verification withIssuer(String issuer); + Verification withIssuer(String... issuer); - Verification withSubject(String subject); + Verification withSubject(String... subject); Verification withAudience(String... audience); @@ -21,21 +22,38 @@ public interface Verification { Verification withJWTId(String jwtId); - Verification withClaim(String name, Boolean value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException; - Verification withClaim(String name, Integer value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, Integer value) throws IllegalArgumentException; - Verification withClaim(String name, Long value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, Long value) throws IllegalArgumentException; - Verification withClaim(String name, Double value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, Double value) throws IllegalArgumentException; - Verification withClaim(String name, String value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, String value) throws IllegalArgumentException; - Verification withClaim(String name, Date value) throws IllegalArgumentException; + Verification withNonStandardClaim(String name, Date value) throws IllegalArgumentException; Verification withArrayClaim(String name, String... items) throws IllegalArgumentException; Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException; - JWTVerifier build(); + Verification withNbf(long nbf); + + Verification createVerifierForScoped(String scope, List issuer, + List audience, long expLeeway, long iatLeeway); + + Verification createVerifierForImplicit(List issuer, + List audience, long iatLeeway); + + Verification createVerifierForFb(String userId, String appId); + + Verification withUserId(String userId); + + Verification withAppId(String appId); + + Verification createVerifierForAccess(List issuer, + List audience, long expLeeway, long iatLeeway); + + JWT build(); } diff --git a/lib/src/main/java/com/auth0/jwt/jwts/AccessJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/AccessJWT.java new file mode 100644 index 00000000..b35c2b64 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/AccessJWT.java @@ -0,0 +1,73 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.Verification; + +import java.util.List; + +public class AccessJWT extends JWT.BaseVerification implements Verification { + + AccessJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + /** + * Create Verification object for verification purposes + * @param issuer + * @param audience + * @param expLeeway + * @param iatLeeway + * @return + */ + public Verification createVerifierForAccess(List issuer, + List audience, long expLeeway, long iatLeeway) { + return withIssuer(issuer.toArray(new String[issuer.size()])).withAudience(audience.toArray(new String[audience.size()])) + .acceptExpiresAt(expLeeway).acceptIssuedAt(iatLeeway); + } + + /** + * Returns a {Verification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return Verification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static Verification require(Algorithm algorithm) { + return AccessJWT.init(algorithm); + } + + /** + * Initialize a Verification instance using the given Algorithm. + * + * @param algorithm the Algorithm to use on the JWT verification. + * @return a AccessJWT instance to configure. + * @throws IllegalArgumentException if the provided algorithm is null. + */ + static Verification init(Algorithm algorithm) throws IllegalArgumentException { + return new AccessJWT(algorithm); + } + + /** + * Creates a new and reusable instance of the JWT with the configuration already provided. + * + * @return a new JWT instance. + */ + @Override + public JWT build() { + return this.build(new ClockImpl()); + } + + /** + * Creates a new and reusable instance of the JWT the configuration already provided. + * ONLY FOR TEST PURPOSES. + * + * @param clock the instance that will handle the current time. + * @return a new JWT instance with a custom Clock. + */ + public JWT build(Clock clock) { + addLeewayToDateClaims(); + return new JWT(algorithm, claims, clock); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/jwts/ExtendedJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/ExtendedJWT.java new file mode 100644 index 00000000..d142ec9e --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/ExtendedJWT.java @@ -0,0 +1,42 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.GoogleVerification; +import com.auth0.jwt.interfaces.Verification; + +import java.util.List; + +public class ExtendedJWT extends GoogleJWT implements GoogleVerification{ + + ExtendedJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + + public Verification createVerifierForExtended(String picture, String email, List issuer, + List audience, String name, long nbf, long expLeeway, long iatLeeway) { + Verification verification = createVerifierForGoogle(picture, email, issuer, audience, name, expLeeway, iatLeeway); + return verification.withNbf(nbf); + } + + public static GoogleVerification require(Algorithm algorithm) { + return ExtendedJWT.init(algorithm); + } + + static GoogleVerification init(Algorithm algorithm) throws IllegalArgumentException { + return new ExtendedJWT(algorithm); + } + + /** + * Require a specific Not Before ("nbf") claim. + * + * @param nbf the required Not Before value + * @return this same Verification instance. + */ + @Override + public Verification withNbf(long nbf) { + requireClaim("nbf", nbf); + return this; + } + +} diff --git a/lib/src/main/java/com/auth0/jwt/jwts/FbJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/FbJWT.java new file mode 100644 index 00000000..337d1811 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/FbJWT.java @@ -0,0 +1,89 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.Verification; + +public class FbJWT extends JWT.BaseVerification implements Verification{ + + FbJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + /** + * Create Verification object for verification purposes + * @param userId + * @param appId + * @return + */ + public Verification createVerifierForFb(String userId, String appId) { + return withUserId(userId).withAppId(appId); + } + + /** + * Require a specific userId ("userId") claim. + * + * @param userId the required userId value + * @return this same Verification instance. + */ + public Verification withUserId(String userId) { + requireClaim("userId", userId); + return this; + } + + /** + * Require a specific appId ("appId") claim. + * + * @param appId the required appId value + * @return this same Verification instance. + */ + public Verification withAppId(String appId) { + requireClaim("appId", appId); + return this; + } + + /** + * Returns a {Verification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return Verification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static Verification require(Algorithm algorithm) { + return FbJWT.init(algorithm); + } + + /** + * Initialize a Verification instance using the given Algorithm. + * + * @param algorithm the Algorithm to use on the JWT verification. + * @return a FbJWT instance to configure. + * @throws IllegalArgumentException if the provided algorithm is null. + */ + static Verification init(Algorithm algorithm) throws IllegalArgumentException { + return new FbJWT(algorithm); + } + + /** + * Creates a new and reusable instance of the JWT with the configuration already provided. + * + * @return a new JWT instance. + */ + @Override + public JWT build() { + return this.build(new ClockImpl()); + } + + /** + * Creates a new and reusable instance of the JWT the configuration already provided. + * ONLY FOR TEST PURPOSES. + * + * @param clock the instance that will handle the current time. + * @return a new JWT instance with a custom Clock. + */ + public JWT build(Clock clock) { + addLeewayToDateClaims(); + return new JWT(algorithm, claims, clock); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/jwts/GoogleJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/GoogleJWT.java new file mode 100644 index 00000000..1bc2c3c3 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/GoogleJWT.java @@ -0,0 +1,116 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.GoogleVerification; +import com.auth0.jwt.interfaces.Verification; + +import java.util.List; + +public class GoogleJWT extends JWT.BaseVerification implements GoogleVerification{ + + GoogleJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + /** + * Create Verification object for verification purposes + * @param picture + * @param email + * @param issuer + * @param audience + * @param name + * @return + */ + public Verification createVerifierForGoogle(String picture, String email, List issuer, + List audience, String name, long expLeeway, long iatLeeway) { + return withPicture(picture).withName(name).withEmail(email).withIssuer(issuer.toArray(new String[issuer.size()])).withAudience(audience.toArray(new String[audience.size()])) + .acceptExpiresAt(expLeeway).acceptIssuedAt(iatLeeway); + } + + /** + * Require a specific Picture ("picture") claim. + * + * @param picture the required Picture value + * @return this same Verification instance. + */ + @Override + public GoogleVerification withPicture(String picture) { + requireClaim("picture", picture); + return this; + } + + /** + * Require a specific Email ("email") claim. + * + * @param email the required Email value + * @return this same Verification instance. + */ + @Override + public GoogleVerification withEmail(String email) { + requireClaim("email", email); + return this; + } + + /** + * Require a specific Name ("name") claim. + * + * @param name the required Name value + * @return this same Verification instance. + */ + @Override + public GoogleVerification withName(String name) { + requireClaim("name", name); + return this; + } + + @Override + public Verification createVerifierForExtended(String picture, String email, List issuer, List audience, String name, long nbf, long expLeeway, long iatLeeway) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + /** + * Returns a {GoogleVerification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return GoogleVerification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static GoogleVerification require(Algorithm algorithm) { + return GoogleJWT.init(algorithm); + } + + /** + * Initialize a GoogleVerification instance using the given Algorithm. + * + * @param algorithm the Algorithm to use on the JWT verification. + * @return a GoogleJWT instance to configure. + * @throws IllegalArgumentException if the provided algorithm is null. + */ + static GoogleVerification init(Algorithm algorithm) throws IllegalArgumentException { + return new GoogleJWT(algorithm); + } + + /** + * Creates a new and reusable instance of the JWT with the configuration already provided. + * + * @return a new JWT instance. + */ + @Override + public JWT build() { + return this.build(new ClockImpl()); + } + + /** + * Creates a new and reusable instance of the JWT the configuration already provided. + * ONLY FOR TEST PURPOSES. + * + * @param clock the instance that will handle the current time. + * @return a new JWT instance with a custom Clock. + */ + public JWT build(Clock clock) { + addLeewayToDateClaims(); + return new JWT(algorithm, claims, clock); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java new file mode 100644 index 00000000..afd21571 --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java @@ -0,0 +1,72 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.Verification; + +import java.util.List; + +public class ImplicitJWT extends JWT.BaseVerification implements Verification{ + + ImplicitJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + /** + * Create Verification object for verification purposes + * @issuer scope + * @param issuer + * @param audience + * @return + */ + public Verification createVerifierForImplicit(List issuer, + List audience, long iatLeeway) { + return withIssuer(issuer.toArray(new String[issuer.size()])).withAudience(audience.toArray(new String[audience.size()])) + .acceptIssuedAt(iatLeeway); + } + + /** + * Returns a {Verification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return Verification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static Verification require(Algorithm algorithm) { + return ImplicitJWT.init(algorithm); + } + + /** + * Initialize a Verification instance using the given Algorithm. + * + * @param algorithm the Algorithm to use on the JWT verification. + * @return a ImplicitJWT instance to configure. + * @throws IllegalArgumentException if the provided algorithm is null. + */ + static Verification init(Algorithm algorithm) throws IllegalArgumentException { + return new ImplicitJWT(algorithm); + } + + /** + * Creates a new and reusable instance of the JWT with the configuration already provided. + * + * @return a new JWT instance. + */ + @Override + public JWT build() { + return this.build(new ClockImpl()); + } + + /** + * Creates a new and reusable instance of the JWT the configuration already provided. + * ONLY FOR TEST PURPOSES. + * + * @param clock the instance that will handle the current time. + * @return a new JWT instance with a custom Clock. + */ + public JWT build(Clock clock) { + addLeewayToDateClaims(); + return new JWT(algorithm, claims, clock); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java b/lib/src/main/java/com/auth0/jwt/jwts/JWT.java similarity index 56% rename from lib/src/main/java/com/auth0/jwt/JWTVerifier.java rename to lib/src/main/java/com/auth0/jwt/jwts/JWT.java index 6f513c7e..b8fcb060 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java +++ b/lib/src/main/java/com/auth0/jwt/jwts/JWT.java @@ -1,47 +1,90 @@ -package com.auth0.jwt; +package com.auth0.jwt.jwts; +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.creators.JWTCreator; +import com.auth0.jwt.JWTDecoder; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.*; import com.auth0.jwt.impl.PublicClaims; -import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.Clock; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.verification.VerificationAndAssertion; 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 it's signature matches. - */ @SuppressWarnings("WeakerAccess") -public final class JWTVerifier { +public class JWT { + private final Algorithm algorithm; final Map claims; private final Clock clock; - JWTVerifier(Algorithm algorithm, Map claims, Clock clock) { + JWT(Algorithm algorithm, Map claims, Clock clock) { this.algorithm = algorithm; this.claims = Collections.unmodifiableMap(claims); this.clock = clock; } /** - * Initialize a JWTVerifier instance using the given Algorithm. + * Convert the given token to a DecodedJWT + *

+ * Note that this method doesn't verify the token's signature! Use it only if you trust the token or you already verified it. + * + * @param token with jwt format as string. + * @return a decoded JWT. + * @throws AlgorithmMismatchException if the algorithm stated in the token's header it's not equal to the one defined in the {@link JWT}. + * @throws SignatureVerificationException if the signature is invalid. + * @throws TokenExpiredException if the token has expired. + * @throws InvalidClaimException if a claim contained a different value than the expected one. + */ + public DecodedJWT decode(String token) throws JWTDecodeException { + DecodedJWT jwt = new JWTDecoder(token); + VerificationAndAssertion.verifyAlgorithm(jwt, algorithm); + algorithm.verify(jwt); + VerificationAndAssertion.verifyClaims(clock, jwt, claims); + return jwt; + } + + /** + * Returns a {Verification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return Verification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static Verification require(Algorithm algorithm) { + return JWT.init(algorithm); + } + + /** + * Returns a Json Web Token builder used to create and sign tokens + * + * @return a token builder. + */ + public static JWTCreator.Builder create() { + return JWTCreator.init(); + } + + //----------------this is from JWTVerifier-------- + + /** + * Initialize a Verification instance using the given Algorithm. * * @param algorithm the Algorithm to use on the JWT verification. - * @return a JWTVerifier.Verification instance to configure. + * @return a JWT.BaseVerification instance to configure. * @throws IllegalArgumentException if the provided algorithm is null. */ static Verification init(Algorithm algorithm) throws IllegalArgumentException { - return new BaseVerification(algorithm); + return new JWT.BaseVerification(algorithm); } /** * The Verification class holds the Claims required by a JWT to be valid. */ public static class BaseVerification implements Verification { - private final Algorithm algorithm; - private final Map claims; + protected final Algorithm algorithm; + protected final Map claims; private long defaultLeeway; BaseVerification(Algorithm algorithm) throws IllegalArgumentException { @@ -54,32 +97,70 @@ public static class BaseVerification implements Verification { this.defaultLeeway = 0; } + @Override + public Verification withNbf(long nbf) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification createVerifierForScoped(String scope, List issuer, List audience, long expLeeway, long iatLeeway) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification createVerifierForImplicit(List issuer, List audience, long iatLeeway) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification createVerifierForFb(String userId, String appId) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification withUserId(String userId) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification withAppId(String appId) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + + @Override + public Verification createVerifierForAccess(List issuer, List audience, long expLeeway, long iatLeeway) { + throw new UnsupportedOperationException("you shouldn't be calling this method"); + } + /** * Require a specific Issuer ("iss") claim. + * Allows for multiple issuers * * @param issuer the required Issuer value * @return this same Verification instance. */ @Override - public Verification withIssuer(String issuer) { - requireClaim(PublicClaims.ISSUER, issuer); + public Verification withIssuer(String... issuer) { + requireClaim(PublicClaims.ISSUER, Arrays.asList(issuer)); return this; } /** * Require a specific Subject ("sub") claim. + * Allows for multiple subjects * * @param subject the required Subject value * @return this same Verification instance. */ @Override - public Verification withSubject(String subject) { - requireClaim(PublicClaims.SUBJECT, subject); + public Verification withSubject(String... subject) { + requireClaim(PublicClaims.SUBJECT, Arrays.asList(subject)); return this; } /** * Require a specific Audience ("aud") claim. + * Allows for multiple audience * * @param audience the required Audience value * @return this same Verification instance. @@ -100,7 +181,7 @@ public Verification withAudience(String... audience) { */ @Override public Verification acceptLeeway(long leeway) throws IllegalArgumentException { - assertPositive(leeway); + VerificationAndAssertion.assertPositive(leeway); this.defaultLeeway = leeway; return this; } @@ -115,7 +196,7 @@ public Verification acceptLeeway(long leeway) throws IllegalArgumentException { */ @Override public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException { - assertPositive(leeway); + VerificationAndAssertion.assertPositive(leeway); requireClaim(PublicClaims.EXPIRES_AT, leeway); return this; } @@ -130,7 +211,7 @@ public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException */ @Override public Verification acceptNotBefore(long leeway) throws IllegalArgumentException { - assertPositive(leeway); + VerificationAndAssertion.assertPositive(leeway); requireClaim(PublicClaims.NOT_BEFORE, leeway); return this; } @@ -145,7 +226,7 @@ public Verification acceptNotBefore(long leeway) throws IllegalArgumentException */ @Override public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException { - assertPositive(leeway); + VerificationAndAssertion.assertPositive(leeway); requireClaim(PublicClaims.ISSUED_AT, leeway); return this; } @@ -171,8 +252,8 @@ public Verification withJWTId(String jwtId) { * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, Boolean value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -186,8 +267,8 @@ public Verification withClaim(String name, Boolean value) throws IllegalArgument * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, Integer value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, Integer value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -201,8 +282,8 @@ public Verification withClaim(String name, Integer value) throws IllegalArgument * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, Long value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, Long value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -216,8 +297,8 @@ public Verification withClaim(String name, Long value) throws IllegalArgumentExc * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, Double value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, Double value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -231,8 +312,8 @@ public Verification withClaim(String name, Double value) throws IllegalArgumentE * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, String value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, String value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -246,8 +327,8 @@ public Verification withClaim(String name, String value) throws IllegalArgumentE * @throws IllegalArgumentException if the name is null. */ @Override - public Verification withClaim(String name, Date value) throws IllegalArgumentException { - assertNonNull(name); + public Verification withNonStandardClaim(String name, Date value) throws IllegalArgumentException { + VerificationAndAssertion.assertNonNull(name); requireClaim(name, value); return this; } @@ -262,7 +343,7 @@ public Verification withClaim(String name, Date value) throws IllegalArgumentExc */ @Override public Verification withArrayClaim(String name, String... items) throws IllegalArgumentException { - assertNonNull(name); + VerificationAndAssertion.assertNonNull(name); requireClaim(name, items); return this; } @@ -277,46 +358,34 @@ public Verification withArrayClaim(String name, String... items) throws IllegalA */ @Override public Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException { - assertNonNull(name); + VerificationAndAssertion.assertNonNull(name); requireClaim(name, items); return this; } /** - * Creates a new and reusable instance of the JWTVerifier with the configuration already provided. + * Creates a new and reusable instance of the JWT with the configuration already provided. * - * @return a new JWTVerifier instance. + * @return a new JWT instance. */ @Override - public JWTVerifier build() { + public JWT build() { return this.build(new ClockImpl()); } /** - * Creates a new and reusable instance of the JWTVerifier with the configuration already provided. + * Creates a new and reusable instance of the JWT the configuration already provided. * ONLY FOR TEST PURPOSES. * * @param clock the instance that will handle the current time. - * @return a new JWTVerifier instance with a custom Clock. + * @return a new JWT instance with a custom Clock. */ - public JWTVerifier build(Clock clock) { + public JWT build(Clock clock) { addLeewayToDateClaims(); - return new JWTVerifier(algorithm, claims, clock); + return new JWT(algorithm, claims, clock); } - private void assertPositive(long leeway) { - if (leeway < 0) { - throw new IllegalArgumentException("Leeway value can't be negative."); - } - } - - private void assertNonNull(String name) { - if (name == null) { - throw new IllegalArgumentException("The Custom Claim's name can't be null."); - } - } - - private void addLeewayToDateClaims() { + protected void addLeewayToDateClaims() { if (!claims.containsKey(PublicClaims.EXPIRES_AT)) { claims.put(PublicClaims.EXPIRES_AT, defaultLeeway); } @@ -328,7 +397,7 @@ private void addLeewayToDateClaims() { } } - private void requireClaim(String name, Object value) { + protected void requireClaim(String name, Object value) { if (value == null) { claims.remove(name); return; @@ -336,122 +405,4 @@ private void requireClaim(String name, Object value) { claims.put(name, value); } } - - - /** - * Perform the verification against the given Token, using any previous configured options. - * - * @param token to verify. - * @return a verified and decoded JWT. - * @throws AlgorithmMismatchException if the algorithm stated in the token's header it's not equal to the one defined in the {@link JWTVerifier}. - * @throws SignatureVerificationException if the signature is invalid. - * @throws TokenExpiredException if the token has expired. - * @throws InvalidClaimException if a claim contained a different value than the expected one. - */ - public DecodedJWT verify(String token) throws JWTVerificationException { - DecodedJWT jwt = JWT.decode(token); - verifyAlgorithm(jwt, algorithm); - algorithm.verify(jwt); - verifyClaims(jwt, claims); - return jwt; - } - - private void verifyAlgorithm(DecodedJWT jwt, Algorithm expectedAlgorithm) throws AlgorithmMismatchException { - if (!expectedAlgorithm.getName().equals(jwt.getAlgorithm())) { - throw new AlgorithmMismatchException("The provided Algorithm doesn't match the one defined in the JWT's Header."); - } - } - - private void verifyClaims(DecodedJWT jwt, Map claims) throws TokenExpiredException, InvalidClaimException { - for (Map.Entry entry : claims.entrySet()) { - switch (entry.getKey()) { - case PublicClaims.AUDIENCE: - //noinspection unchecked - assertValidAudienceClaim(jwt.getAudience(), (List) entry.getValue()); - break; - case PublicClaims.EXPIRES_AT: - assertValidDateClaim(jwt.getExpiresAt(), (Long) entry.getValue(), true); - break; - case PublicClaims.ISSUED_AT: - assertValidDateClaim(jwt.getIssuedAt(), (Long) entry.getValue(), false); - break; - case PublicClaims.NOT_BEFORE: - assertValidDateClaim(jwt.getNotBefore(), (Long) entry.getValue(), false); - break; - case PublicClaims.ISSUER: - assertValidStringClaim(entry.getKey(), jwt.getIssuer(), (String) entry.getValue()); - break; - case PublicClaims.JWT_ID: - assertValidStringClaim(entry.getKey(), jwt.getId(), (String) entry.getValue()); - break; - case PublicClaims.SUBJECT: - assertValidStringClaim(entry.getKey(), jwt.getSubject(), (String) entry.getValue()); - break; - default: - assertValidClaim(jwt.getClaim(entry.getKey()), entry.getKey(), entry.getValue()); - break; - } - } - } - - private void assertValidClaim(Claim claim, String claimName, Object value) { - boolean isValid = false; - if (value instanceof String) { - isValid = value.equals(claim.asString()); - } else if (value instanceof Integer) { - isValid = value.equals(claim.asInt()); - } else if (value instanceof Long) { - isValid = value.equals(claim.asLong()); - } else if (value instanceof Boolean) { - isValid = value.equals(claim.asBoolean()); - } else if (value instanceof Double) { - isValid = value.equals(claim.asDouble()); - } else if (value instanceof Date) { - isValid = value.equals(claim.asDate()); - } else if (value instanceof Object[]) { - List claimArr = Arrays.asList(claim.as(Object[].class)); - List valueArr = Arrays.asList((Object[]) value); - isValid = claimArr.containsAll(valueArr); - } - - if (!isValid) { - throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName)); - } - } - - private void assertValidStringClaim(String claimName, String value, String expectedValue) { - if (!expectedValue.equals(value)) { - throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName)); - } - } - - private void assertValidDateClaim(Date date, long leeway, boolean shouldBeFuture) { - Date today = clock.getToday(); - today.setTime((long) Math.floor((today.getTime() / 1000) * 1000)); // truncate millis - if (shouldBeFuture) { - assertDateIsFuture(date, leeway, today); - } else { - assertDateIsPast(date, leeway, today); - } - } - - 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 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 assertValidAudienceClaim(List audience, List value) { - if (audience == null || !audience.containsAll(value)) { - throw new InvalidClaimException("The Claim 'aud' value doesn't contain the required audience."); - } - } } diff --git a/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java new file mode 100644 index 00000000..8bc7f04b --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java @@ -0,0 +1,83 @@ +package com.auth0.jwt.jwts; + +import com.auth0.jwt.ClockImpl; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.Verification; + +import java.util.List; + +public class ScopedJWT extends JWT.BaseVerification implements Verification{ + + ScopedJWT(Algorithm algorithm) throws IllegalArgumentException { + super(algorithm); + } + + /** + * Create Verification object for verification purposes + * @issuer scope + * @param issuer + * @param audience + * @return + */ + public Verification createVerifierForScoped(String scope, List issuer, + List audience, long expLeeway, long iatLeeway) { + return withScope(scope).withIssuer(issuer.toArray(new String[issuer.size()])).withAudience(audience.toArray(new String[audience.size()])) + .acceptExpiresAt(expLeeway).acceptIssuedAt(iatLeeway); + } + + /** + * Require a specific Scope ("scope") claim. + * + * @param scope the required Scope value + * @return this same Verification instance. + */ + public Verification withScope(String scope) { + requireClaim("scope", scope); + return this; + } + + /** + * Returns a {Verification} to be used to validate token signature. + * + * @param algorithm that will be used to verify the token's signature. + * @return Verification + * @throws IllegalArgumentException if the provided algorithm is null. + */ + public static Verification require(Algorithm algorithm) { + return ScopedJWT.init(algorithm); + } + + /** + * Initialize a Verification instance using the given Algorithm. + * + * @param algorithm the Algorithm to use on the JWT verification. + * @return a ScopedJWT instance to configure. + * @throws IllegalArgumentException if the provided algorithm is null. + */ + static Verification init(Algorithm algorithm) throws IllegalArgumentException { + return new ScopedJWT(algorithm); + } + + /** + * Creates a new and reusable instance of the JWT with the configuration already provided. + * + * @return a new JWT instance. + */ + @Override + public JWT build() { + return this.build(new ClockImpl()); + } + + /** + * Creates a new and reusable instance of the JWT the configuration already provided. + * ONLY FOR TEST PURPOSES. + * + * @param clock the instance that will handle the current time. + * @return a new JWT instance with a custom Clock. + */ + public JWT build(Clock clock) { + addLeewayToDateClaims(); + return new JWT(algorithm, claims, clock); + } +} diff --git a/lib/src/main/java/com/auth0/jwt/verification/VerificationAndAssertion.java b/lib/src/main/java/com/auth0/jwt/verification/VerificationAndAssertion.java new file mode 100644 index 00000000..f029fe3f --- /dev/null +++ b/lib/src/main/java/com/auth0/jwt/verification/VerificationAndAssertion.java @@ -0,0 +1,132 @@ +package com.auth0.jwt.verification; + +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.Clock; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class VerificationAndAssertion { + + public static void assertPositive(long leeway) { + if (leeway < 0) { + throw new IllegalArgumentException("Leeway value can't be negative."); + } + } + + public static void assertNonNull(String name) { + if (name == null) { + throw new IllegalArgumentException("The Custom Claim's name can't be null."); + } + } + + public static void verifyAlgorithm(DecodedJWT jwt, Algorithm expectedAlgorithm) throws AlgorithmMismatchException { + if (!expectedAlgorithm.getName().equals(jwt.getAlgorithm())) { + throw new AlgorithmMismatchException("The provided Algorithm doesn't match the one defined in the JWT's Header."); + } + } + + public static void verifyClaims(Clock clock, DecodedJWT jwt, Map claims) throws TokenExpiredException, InvalidClaimException { + for (Map.Entry entry : claims.entrySet()) { + switch (entry.getKey()) { + case PublicClaims.AUDIENCE: + //noinspection unchecked + VerificationAndAssertion.assertValidAudienceClaim(jwt.getAudience(), (List) entry.getValue()); + break; + case PublicClaims.EXPIRES_AT: + assertValidDateClaim(clock, jwt.getExpiresAt(), (Long) entry.getValue(), true); + break; + case PublicClaims.ISSUED_AT: + assertValidDateClaim(clock, jwt.getIssuedAt(), (Long) entry.getValue(), false); + break; + case PublicClaims.NOT_BEFORE: + assertValidDateClaim(clock, jwt.getNotBefore(), (Long) entry.getValue(), false); + break; + case PublicClaims.ISSUER: + VerificationAndAssertion.assertValidIssuerClaim(jwt.getIssuer(), (List) entry.getValue()); + break; + case PublicClaims.JWT_ID: + VerificationAndAssertion.assertValidStringClaim(entry.getKey(), jwt.getId(), (String) entry.getValue()); + break; + default: + VerificationAndAssertion.assertValidClaim(jwt.getClaim(entry.getKey()), entry.getKey(), entry.getValue()); + break; + } + } + } + + private static void assertValidDateClaim(Clock clock, Date date, long leeway, boolean shouldBeFuture) { + Date today = clock.getToday(); + today.setTime((long) Math.floor((today.getTime() / 1000) * 1000)); // truncate millis + if (shouldBeFuture) { + VerificationAndAssertion.assertDateIsFuture(date, leeway, today); + } else { + VerificationAndAssertion.assertDateIsPast(date, leeway, today); + } + } + + private static void assertValidClaim(Claim claim, String claimName, Object value) { + boolean isValid = false; + if (value instanceof String) { + isValid = value.equals(claim.asString()); + } else if (value instanceof Integer) { + isValid = value.equals(claim.asInt()); + } else if (value instanceof Long) { + isValid = value.equals(claim.asLong()); + } else if (value instanceof Boolean) { + isValid = value.equals(claim.asBoolean()); + } else if (value instanceof Double) { + isValid = value.equals(claim.asDouble()); + } else if (value instanceof Date) { + isValid = value.equals(claim.asDate()); + } else if (value instanceof Object[]) { + List claimArr = Arrays.asList(claim.as(Object[].class)); + List valueArr = Arrays.asList((Object[]) value); + isValid = claimArr.containsAll(valueArr); + } + + if (!isValid) { + throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName)); + } + } + + private static void assertValidStringClaim(String claimName, String value, String expectedValue) { + if (!expectedValue.equals(value)) { + throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName)); + } + } + + private static 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 static 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 static void assertValidAudienceClaim(List audience, List value) { + if (audience == null || !audience.containsAll(value) || audience.size() != value.size()) { + throw new InvalidClaimException("The Claim 'aud' value doesn't contain the required audience."); + } + } + + private static void assertValidIssuerClaim(List issuer, List value) { + if (issuer == null || !issuer.containsAll(value) || issuer.size() != value.size()) { + throw new InvalidClaimException("The Claim 'iss' value doesn't match the required one."); + } + } +} diff --git a/lib/src/test/java/com/auth0/jwt/ConcurrentVerifyTest.java b/lib/src/test/java/com/auth0/jwt/ConcurrentVerifyTest.java index 41098c25..5ed88a51 100644 --- a/lib/src/test/java/com/auth0/jwt/ConcurrentVerifyTest.java +++ b/lib/src/test/java/com/auth0/jwt/ConcurrentVerifyTest.java @@ -2,6 +2,7 @@ import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.jwts.JWT; import net.jodah.concurrentunit.Waiter; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -43,9 +44,9 @@ public static void afterAll() throws Exception { } @SuppressWarnings("Convert2Lambda") - private void concurrentVerify(final JWTVerifier verifier, final String token) throws TimeoutException, InterruptedException { + private void concurrentVerify(final JWT jwt, final String token) throws TimeoutException, InterruptedException { final Waiter waiter = new Waiter(); - List tasks = Collections.nCopies(REPEAT_COUNT, new VerifyTask(waiter, verifier, token)); + List tasks = Collections.nCopies(REPEAT_COUNT, new VerifyTask(waiter, jwt, token)); executor.invokeAll(tasks, TIMEOUT, TimeUnit.MILLISECONDS); waiter.await(TIMEOUT, REPEAT_COUNT); } @@ -53,81 +54,81 @@ private void concurrentVerify(final JWTVerifier verifier, final String token) th private static class VerifyTask implements Callable { private final Waiter waiter; - private final JWTVerifier verifier; + private final JWT jwt; private final String token; - VerifyTask(Waiter waiter, final JWTVerifier verifier, final String token) { + VerifyTask(Waiter waiter, final JWT jwt, final String token) { this.waiter = waiter; - this.verifier = verifier; + this.jwt = jwt; this.token = token; } @Override public DecodedJWT call() throws Exception { - DecodedJWT jwt = null; + DecodedJWT decodedJWT = null; try { - jwt = verifier.verify(token); - waiter.assertNotNull(jwt); + decodedJWT = jwt.decode(token); + waiter.assertNotNull(decodedJWT); } catch (Exception e) { waiter.fail(e); } waiter.resume(); - return jwt; + return decodedJWT; } } @Test public void shouldPassHMAC256Verification() throws Exception { Algorithm algorithm = Algorithm.HMAC256("secret"); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test public void shouldPassHMAC384Verification() throws Exception { String token = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; Algorithm algorithm = Algorithm.HMAC384("secret"); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test public void shouldPassHMAC512Verification() throws Exception { String token = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; Algorithm algorithm = Algorithm.HMAC512("secret"); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test public void shouldPassRSA256Verification() throws Exception { String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; Algorithm algorithm = Algorithm.RSA256((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test public void shouldPassRSA384Verification() throws Exception { String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; Algorithm algorithm = Algorithm.RSA384((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test public void shouldPassRSA512Verification() throws Exception { String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; Algorithm algorithm = Algorithm.RSA512((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test @@ -135,9 +136,9 @@ public void shouldPassECDSA256VerificationWithJOSESignature() throws Exception { String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); Algorithm algorithm = Algorithm.ECDSA256(key); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test @@ -145,9 +146,9 @@ public void shouldPassECDSA384VerificationWithJOSESignature() throws Exception { String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); Algorithm algorithm = Algorithm.ECDSA384(key); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } @Test @@ -155,8 +156,9 @@ public void shouldPassECDSA512VerificationWithJOSESignature() throws Exception { String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); Algorithm algorithm = Algorithm.ECDSA512(key); - JWTVerifier verifier = JWTVerifier.init(algorithm).withIssuer("auth0").build(); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); - concurrentVerify(verifier, token); + concurrentVerify(jwt, token); } + } diff --git a/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java b/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java index a482685e..7dd350fe 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTDecoderTest.java @@ -1,13 +1,15 @@ package com.auth0.jwt; +import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.impl.NullClaim; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.hamcrest.collection.IsCollectionWithSize; import org.hamcrest.core.IsCollectionContaining; import org.junit.Assert; +import static org.junit.Assert.assertTrue; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -20,14 +22,17 @@ import static org.hamcrest.Matchers.*; public class JWTDecoderTest { + @Rule public ExpectedException exception = ExpectedException.none(); @Test public void getSubject() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"); - assertThat(jwt.getSubject(), is(notNullValue())); - assertThat(jwt.getSubject(), is("1234567890")); + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).withNonStandardClaim("admin", true).withNonStandardClaim("name", "John Doe").build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT.getSubject(), is(notNullValue())); + assertTrue(decodedJWT.getSubject().contains("1234567890")); } // Exceptions @@ -35,14 +40,16 @@ public void getSubject() throws Exception { public void shouldThrowIfLessThan3Parts() throws Exception { exception.expect(JWTDecodeException.class); exception.expectMessage("The token was expected to have 3 parts, but got 2."); - JWT.decode("two.parts"); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).withNonStandardClaim("admin", true).withNonStandardClaim("name", "John Doe").build(); + DecodedJWT decodedJWT = jwt.decode("two.parts"); } @Test public void shouldThrowIfMoreThan3Parts() throws Exception { exception.expect(JWTDecodeException.class); exception.expectMessage("The token was expected to have 3 parts, but got 4."); - JWT.decode("this.has.four.parts"); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).withNonStandardClaim("admin", true).withNonStandardClaim("name", "John Doe").build(); + DecodedJWT decodedJWT = jwt.decode("this.has.four.parts"); } @Test @@ -67,207 +74,242 @@ public void shouldThrowIfHeaderHasInvalidJSONFormat() throws Exception { @Test public void shouldGetStringToken() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getToken(), is(notNullValue())); - assertThat(jwt.getToken(), is("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); + String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getToken(), is(notNullValue())); + assertThat(decodedJWT.getToken(), is("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); } @Test public void shouldGetHeader() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getHeader(), is("eyJhbGciOiJIUzI1NiJ9")); + String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getHeader(), is("eyJhbGciOiJIUzI1NiJ9")); } @Test public void shouldGetPayload() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getPayload(), is("e30")); + String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getPayload(), is("e30")); } @Test public void shouldGetSignature() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getSignature(), is("XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); + String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getSignature(), is("XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); } // Public PublicClaims @Test public void shouldGetIssuer() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJKb2huIERvZSJ9.SgXosfRR_IwCgHq5lF3tlM-JHtpucWCRSaVuoHTbWbQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuer(), is("John Doe")); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJKb2huIERvZSJ9.SgXosfRR_IwCgHq5lF3tlM-JHtpucWCRSaVuoHTbWbQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertTrue(decodedJWT.getIssuer().contains("John Doe")); } @Test public void shouldGetSubject() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJUb2szbnMifQ.RudAxkslimoOY3BLl2Ghny3BrUKu9I1ZrXzCZGDJtNs"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getSubject(), is("Tok3ns")); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJUb2szbnMifQ.RudAxkslimoOY3BLl2Ghny3BrUKu9I1ZrXzCZGDJtNs"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertTrue(decodedJWT.getSubject().contains("Tok3ns")); } @Test public void shouldGetArrayAudience() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiSG9wZSIsIlRyYXZpcyIsIlNvbG9tb24iXX0.Tm4W8WnfPjlmHSmKFakdij0on2rWPETpoM7Sh0u6-S4"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAudience(), is(IsCollectionWithSize.hasSize(3))); - assertThat(jwt.getAudience(), is(IsCollectionContaining.hasItems("Hope", "Travis", "Solomon"))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiSG9wZSIsIlRyYXZpcyIsIlNvbG9tb24iXX0.Tm4W8WnfPjlmHSmKFakdij0on2rWPETpoM7Sh0u6-S4"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getAudience(), is(IsCollectionWithSize.hasSize(3))); + assertThat(decodedJWT.getAudience(), is(IsCollectionContaining.hasItems("Hope", "Travis", "Solomon"))); } @Test public void shouldGetStringAudience() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJKYWNrIFJleWVzIn0.a4I9BBhPt1OB1GW67g2P1bEHgi6zgOjGUL4LvhE9Dgc"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAudience(), is(IsCollectionWithSize.hasSize(1))); - assertThat(jwt.getAudience(), is(IsCollectionContaining.hasItems("Jack Reyes"))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJKYWNrIFJleWVzIn0.a4I9BBhPt1OB1GW67g2P1bEHgi6zgOjGUL4LvhE9Dgc"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getAudience(), is(IsCollectionWithSize.hasSize(1))); + assertThat(decodedJWT.getAudience(), is(IsCollectionContaining.hasItems("Jack Reyes"))); } @Test public void shouldGetExpirationTime() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NzY3MjcwODZ9.L9dcPHEDQew2u9MkDCORFkfDGcSOsgoPqNY-LUMLEHg"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(instanceOf(Date.class))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NzY3MjcwODZ9.L9dcPHEDQew2u9MkDCORFkfDGcSOsgoPqNY-LUMLEHg"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).acceptExpiresAt(1476727086).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.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(decodedJWT.getExpiresAt(), is(notNullValue())); + assertThat(decodedJWT.getExpiresAt(), is(equalTo(expectedDate))); } @Test public void shouldGetNotBefore() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0NzY3MjcwODZ9.tkpD3iCPQPVqjnjpDVp2bJMBAgpVCG9ZjlBuMitass0"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getNotBefore(), is(instanceOf(Date.class))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0NzY3MjcwODZ9.tkpD3iCPQPVqjnjpDVp2bJMBAgpVCG9ZjlBuMitass0"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).acceptNotBefore(1476727086).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.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(decodedJWT.getNotBefore(), is(notNullValue())); + assertThat(decodedJWT.getNotBefore(), is(equalTo(expectedDate))); } @Test public void shouldGetIssuedAt() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NzY3MjcwODZ9.KPjGoW665E8V5_27Jugab8qSTxLk2cgquhPCBfAP0_w"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(instanceOf(Date.class))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NzY3MjcwODZ9.KPjGoW665E8V5_27Jugab8qSTxLk2cgquhPCBfAP0_w"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).acceptIssuedAt(1476727086).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.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(decodedJWT.getIssuedAt(), is(notNullValue())); + assertThat(decodedJWT.getIssuedAt(), is(equalTo(expectedDate))); } @Test public void shouldGetId() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0NTY3ODkwIn0.m3zgEfVUFOd-CvL3xG5BuOWLzb0zMQZCqiVNQQOPOvA"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getId(), is("1234567890")); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0NTY3ODkwIn0.m3zgEfVUFOd-CvL3xG5BuOWLzb0zMQZCqiVNQQOPOvA"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getId(), is("1234567890")); } @Test public void shouldGetContentType() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiIsImN0eSI6ImF3ZXNvbWUifQ.e30.AIm-pJDOaAyct9qKMlN-lQieqNDqc3d4erqUZc5SHAs"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getContentType(), is("awesome")); + String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6ImF3ZXNvbWUifQ.e30.AIm-pJDOaAyct9qKMlN-lQieqNDqc3d4erqUZc5SHAs"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getContentType(), is("awesome")); } @Test public void shouldGetType() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.e30.WdFmrzx8b9v_a-r6EHC2PTAaWywgm_8LiP8RBRhYwkI"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getType(), is("JWS")); + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.e30.WdFmrzx8b9v_a-r6EHC2PTAaWywgm_8LiP8RBRhYwkI"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getType(), is("JWS")); } @Test public void shouldGetAlgorithm() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAlgorithm(), is("HS256")); + String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getAlgorithm(), is("HS256")); } //Private PublicClaims - @Test - public void shouldGetMissingClaimIfClaimDoesNotExist() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.K17vlwhE8FCMShdl1_65jEYqsQqBOVMPUU9IgG-QlTM"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getClaim("notExisting"), is(notNullValue())); - assertThat(jwt.getClaim("notExisting"), is(instanceOf(NullClaim.class))); - } @Test public void shouldGetValidClaim() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJvYmplY3QiOnsibmFtZSI6ImpvaG4ifX0.lrU1gZlOdlmTTeZwq0VI-pZx2iV46UWYd5-lCjy6-c4"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getClaim("object"), is(notNullValue())); - assertThat(jwt.getClaim("object"), is(instanceOf(Claim.class))); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJvYmplY3QiOnsibmFtZSI6ImpvaG4ifX0.lrU1gZlOdlmTTeZwq0VI-pZx2iV46UWYd5-lCjy6-c4"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getClaim("object"), is(notNullValue())); + assertThat(decodedJWT.getClaim("object"), is(instanceOf(Claim.class))); } + @Test public void shouldNotGetNullClaimIfClaimIsEmptyObject() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJvYmplY3QiOnt9fQ.d3nUeeL_69QsrHL0ZWij612LHEQxD8EZg1rNoY3a4aI"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getClaim("object"), is(notNullValue())); - assertThat(jwt.getClaim("object").isNull(), is(false)); + String token = "eyJhbGciOiJIUzI1NiJ9.eyJvYmplY3QiOnt9fQ.d3nUeeL_69QsrHL0ZWij612LHEQxD8EZg1rNoY3a4aI"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + assertThat(decodedJWT.getClaim("object"), is(notNullValue())); + assertThat(decodedJWT.getClaim("object").isNull(), is(false)); } @Test public void shouldGetCustomClaimOfTypeInteger() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxMjN9.XZAudnA7h3_Al5kJydzLjw6RzZC3Q6OvnLEYlhNW7HA"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asInt(), is(123)); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asInt(), is(123)); } @Test public void shouldGetCustomClaimOfTypeDouble() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoyMy40NX0.7pyX2OmEGaU9q15T8bGFqRm-d3RVTYnqmZNZtxMKSlA"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asDouble(), is(23.45)); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asDouble(), is(23.45)); } @Test public void shouldGetCustomClaimOfTypeBoolean() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjp0cnVlfQ.FwQ8VfsZNRqBa9PXMinSIQplfLU4-rkCLfIlTLg_MV0"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asBoolean(), is(true)); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asBoolean(), is(true)); } @Test public void shouldGetCustomClaimOfTypeDate() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxNDc4ODkxNTIxfQ.mhioumeok8fghQEhTKF3QtQAksSvZ_9wIhJmgZLhJ6c"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); Date date = new Date(1478891521000L); - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asDate().getTime(), is(date.getTime())); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asDate().getTime(), is(date.getTime())); } @Test public void shouldGetCustomArrayClaimOfTypeString() throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbInRleHQiLCIxMjMiLCJ0cnVlIl19.lxM8EcmK1uSZRAPd0HUhXGZJdauRmZmLjoeqz4J9yAA"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asArray(String.class), arrayContaining("text", "123", "true")); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asArray(String.class), arrayContaining("text", "123", "true")); } @Test public void shouldGetCustomArrayClaimOfTypeInteger() throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbMSwyLDNdfQ.UEuMKRQYrzKAiPpPLhIVawWkKWA1zj0_GderrWUIyFE"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Assert.assertThat(jwt.getClaim("name").asArray(Integer.class), arrayContaining(1, 2, 3)); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Assert.assertThat(decodedJWT.getClaim("name").asArray(Integer.class), arrayContaining(1, 2, 3)); } @Test public void shouldGetCustomMapClaim() throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjp7InN0cmluZyI6InZhbHVlIiwibnVtYmVyIjoxLCJib29sZWFuIjp0cnVlfX0.-8aIaXd2-rp1lLuDEQmCeisCBX9X_zbqdPn2llGxNoc"; - DecodedJWT jwt = JWT.decode(token); - Assert.assertThat(jwt, is(notNullValue())); - Map map = jwt.getClaim("name").asMap(); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + Assert.assertThat(decodedJWT, is(notNullValue())); + Map map = decodedJWT.getClaim("name").asMap(); Assert.assertThat(map, hasEntry("string", (Object) "value")); Assert.assertThat(map, hasEntry("number", (Object) 1)); Assert.assertThat(map, hasEntry("boolean", (Object) true)); @@ -275,26 +317,30 @@ public void shouldGetCustomMapClaim() throws Exception { @Test public void shouldGetAvailableClaims() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwiaWF0IjoiMTIzNDU2Nzg5MCIsIm5iZiI6IjEyMzQ1Njc4OTAiLCJqdGkiOiJodHRwczovL2p3dC5pby8iLCJhdWQiOiJodHRwczovL2RvbWFpbi5hdXRoMC5jb20iLCJzdWIiOiJsb2dpbiIsImlzcyI6ImF1dGgwIiwiZXh0cmFDbGFpbSI6IkpvaG4gRG9lIn0.TX9Ct4feGp9YyeGK9Zl91tO0YBOrguJ4As9jeqgHdZQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getClaims(), is(notNullValue())); - assertThat(jwt.getClaims(), is(instanceOf(Map.class))); - assertThat(jwt.getClaims().get("exp"), is(notNullValue())); - assertThat(jwt.getClaims().get("iat"), is(notNullValue())); - assertThat(jwt.getClaims().get("nbf"), is(notNullValue())); - assertThat(jwt.getClaims().get("jti"), is(notNullValue())); - assertThat(jwt.getClaims().get("aud"), is(notNullValue())); - assertThat(jwt.getClaims().get("sub"), is(notNullValue())); - assertThat(jwt.getClaims().get("iss"), is(notNullValue())); - assertThat(jwt.getClaims().get("extraClaim"), is(notNullValue())); + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwiaWF0IjoiMTIzNDU2Nzg5MCIsIm5iZiI6IjEyMzQ1Njc4OTAiLCJqdGkiOiJodHRwczovL2p3dC5pby8iLCJhdWQiOiJodHRwczovL2RvbWFpbi5hdXRoMC5jb20iLCJzdWIiOiJsb2dpbiIsImlzcyI6ImF1dGgwIiwiZXh0cmFDbGFpbSI6IkpvaG4gRG9lIn0.TX9Ct4feGp9YyeGK9Zl91tO0YBOrguJ4As9jeqgHdZQ"; + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(token); + assertThat(decodedJWT, is(notNullValue())); + Map claims = decodedJWT.getClaims(); + assertThat(claims, is(notNullValue())); + assertThat(claims, is(instanceOf(Map.class))); + assertThat(claims.get("exp"), is(notNullValue())); + assertThat(claims.get("iat"), is(notNullValue())); + assertThat(claims.get("nbf"), is(notNullValue())); + assertThat(claims.get("jti"), is(notNullValue())); + assertThat(claims.get("aud"), is(notNullValue())); + assertThat(claims.get("sub"), is(notNullValue())); + assertThat(claims.get("iss"), is(notNullValue())); + assertThat(claims.get("extraClaim"), is(notNullValue())); } //Helper Methods - private DecodedJWT customJWT(String jsonHeader, String jsonPayload, String signature) { + private DecodedJWT customJWT(String jsonHeader, String jsonPayload, String signature) throws Exception{ String header = Base64.encodeBase64URLSafeString(jsonHeader.getBytes(StandardCharsets.UTF_8)); String body = Base64.encodeBase64URLSafeString(jsonPayload.getBytes(StandardCharsets.UTF_8)); - return JWT.decode(String.format("%s.%s.%s", header, body, signature)); + JWT jwt = JWT.require(Algorithm.HMAC256("secret")).build(); + DecodedJWT decodedJWT = jwt.decode(String.format("%s.%s.%s", header, body, signature)); + return decodedJWT; } - } \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/JWTTest.java b/lib/src/test/java/com/auth0/jwt/JWTTest.java index 31df4494..32fe283a 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTTest.java @@ -3,6 +3,7 @@ import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Clock; import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.hamcrest.collection.IsCollectionWithSize; import org.hamcrest.core.IsCollectionContaining; @@ -22,478 +23,122 @@ public class JWTTest { - private static final String PUBLIC_KEY_FILE_RSA = "src/test/resources/rsa-public.pem"; - private static final String PRIVATE_KEY_FILE_RSA = "src/test/resources/rsa-private.pem"; - - private static final String PUBLIC_KEY_FILE_EC_256 = "src/test/resources/ec256-key-public.pem"; - private static final String PUBLIC_KEY_FILE_EC_384 = "src/test/resources/ec384-key-public.pem"; - private static final String PUBLIC_KEY_FILE_EC_512 = "src/test/resources/ec512-key-public.pem"; - private static final String PRIVATE_KEY_FILE_EC_256 = "src/test/resources/ec256-key-private.pem"; - private static final String PRIVATE_KEY_FILE_EC_384 = "src/test/resources/ec384-key-private.pem"; - private static final String PRIVATE_KEY_FILE_EC_512 = "src/test/resources/ec512-key-private.pem"; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - // Decode - - @Test - public void shouldDecodeAStringToken() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - DecodedJWT jwt = JWT.decode(token); - - assertThat(jwt, is(notNullValue())); - } - - // getToken - @Test - public void shouldGetStringToken() throws Exception { - DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"); - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getToken(), is(notNullValue())); - assertThat(jwt.getToken(), is("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); - } - - - // Verify + public ExpectedException thrown = ExpectedException.none(); @Test - public void shouldAcceptNoneAlgorithm() throws Exception { - String token = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9."; - DecodedJWT jwt = JWT.require(Algorithm.none()) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldAcceptHMAC256Algorithm() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldAcceptHMAC384Algorithm() throws Exception { - String token = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC384("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldAcceptHMAC512Algorithm() throws Exception { - String token = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC512("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testWithNbf() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).withNbf(5); } - @Test - public void shouldAcceptRSA256Algorithm() throws Exception { - String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; - RSAKey key = (RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"); - DecodedJWT jwt = JWT.require(Algorithm.RSA256(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testCreateVerifierForScoped() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).createVerifierForScoped(null, null, null, 5, 5); } - @Test - public void shouldAcceptRSA384Algorithm() throws Exception { - String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; - RSAKey key = (RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"); - DecodedJWT jwt = JWT.require(Algorithm.RSA384(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testCreateVerifierForImplicit() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).createVerifierForImplicit(null, null, 5); } @Test - public void shouldAcceptRSA512Algorithm() throws Exception { - String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; - RSAKey key = (RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"); - DecodedJWT jwt = JWT.require(Algorithm.RSA512(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testCreateVerifierForFB() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).createVerifierForFb(null, null); } - @Test - public void shouldAcceptECDSA256Algorithm() throws Exception { - String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - ECKey key = (ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_256, "EC"); - DecodedJWT jwt = JWT.require(Algorithm.ECDSA256(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testCreateVerifierForAccess() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).createVerifierForAccess(null, null, 5, 5); } @Test - public void shouldAcceptECDSA384Algorithm() throws Exception { - String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; - ECKey key = (ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_384, "EC"); - DecodedJWT jwt = JWT.require(Algorithm.ECDSA384(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testWithUserId() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).withUserId(null); } @Test - public void shouldAcceptECDSA512Algorithm() throws Exception { - String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; - ECKey key = (ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_512, "EC"); - DecodedJWT jwt = JWT.require(Algorithm.ECDSA512(key)) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); + public void testWithAppId() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + JWT.require(Algorithm.none()).withAppId(null); } - - // Public Claims - @Test - public void shouldGetAlgorithm() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAlgorithm(), is("HS256")); + public void testWithSubjectId() { + JWT.require(Algorithm.none()).withSubject("subject1", "subject2"); } @Test - public void shouldGetSignature() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getSignature(), is("XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ")); + public void testAcceptLeeway() { + JWT.require(Algorithm.none()).acceptLeeway(5); } @Test - public void shouldGetIssuer() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJKb2huIERvZSJ9.SgXosfRR_IwCgHq5lF3tlM-JHtpucWCRSaVuoHTbWbQ"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuer(), is("John Doe")); + public void testAcceptNotBefore() { + JWT.require(Algorithm.none()).acceptNotBefore(5); } @Test - public void shouldGetSubject() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJUb2szbnMifQ.RudAxkslimoOY3BLl2Ghny3BrUKu9I1ZrXzCZGDJtNs"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getSubject(), is("Tok3ns")); + public void testWithJWTId() { + JWT.require(Algorithm.none()).withJWTId("jwtId"); } @Test - public void shouldGetArrayAudience() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiSG9wZSIsIlRyYXZpcyIsIlNvbG9tb24iXX0.Tm4W8WnfPjlmHSmKFakdij0on2rWPETpoM7Sh0u6-S4"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAudience(), is(IsCollectionWithSize.hasSize(3))); - assertThat(jwt.getAudience(), is(IsCollectionContaining.hasItems("Hope", "Travis", "Solomon"))); + public void testJWTNonStandardClaimBoolean() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", true); } @Test - public void shouldGetStringAudience() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJKYWNrIFJleWVzIn0.a4I9BBhPt1OB1GW67g2P1bEHgi6zgOjGUL4LvhE9Dgc"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getAudience(), is(IsCollectionWithSize.hasSize(1))); - assertThat(jwt.getAudience(), is(IsCollectionContaining.hasItems("Jack Reyes"))); + public void testJWTNonStandardClaimInteger() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", 5); } @Test - public void shouldGetExpirationTime() throws Exception { - Date expectedDate = new Date(1477592 * 1000); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(expectedDate); - - String token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Nzc1OTJ9.x_ZjkPkKYUV5tdvc0l8go6D_z2kez1MQcOxokXrDc3k"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(instanceOf(Date.class))); - assertThat(jwt.getExpiresAt(), is(notNullValue())); - assertThat(jwt.getExpiresAt(), is(equalTo(expectedDate))); + public void testJWTNonStandardClaimLong() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", 5L); } @Test - public void shouldGetNotBefore() throws Exception { - Date expectedDate = new Date(1477592 * 1000); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(expectedDate); - - String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0Nzc1OTJ9.mWYSOPoNXstjKbZkKrqgkwPOQWEx3F3gMm6PMcfuJd8"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getNotBefore(), is(instanceOf(Date.class))); - assertThat(jwt.getNotBefore(), is(notNullValue())); - assertThat(jwt.getNotBefore(), is(equalTo(expectedDate))); + public void testJWTNonStandardClaimDouble() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", 9.99); } @Test - public void shouldGetIssuedAt() throws Exception { - Date expectedDate = new Date(1477592 * 1000); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(expectedDate); - - String token = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0Nzc1OTJ9.5o1CKlLFjKKcddZzoarQ37pq7qZqNPav3sdZ_bsZaD4"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(instanceOf(Date.class))); - assertThat(jwt.getIssuedAt(), is(notNullValue())); - assertThat(jwt.getIssuedAt(), is(equalTo(expectedDate))); + public void testJWTNonStandardClaimString() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue"); } @Test - public void shouldGetId() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0NTY3ODkwIn0.m3zgEfVUFOd-CvL3xG5BuOWLzb0zMQZCqiVNQQOPOvA"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getId(), is("1234567890")); + public void testJWTNonStandardClaimDate() throws Exception { + JWT.require(Algorithm.none()).withNonStandardClaim("nonStandardClaim", new Date()); } @Test - public void shouldGetContentType() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6ImF3ZXNvbWUifQ.e30.AIm-pJDOaAyct9qKMlN-lQieqNDqc3d4erqUZc5SHAs"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getContentType(), is("awesome")); + public void testJWTWithArrayClaimStrings() throws Exception { + JWT.require(Algorithm.none()).withArrayClaim("arrayKey", "arrayValue1", "arrayValue2"); } @Test - public void shouldGetType() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.e30.WdFmrzx8b9v_a-r6EHC2PTAaWywgm_8LiP8RBRhYwkI"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getType(), is("JWS")); + public void testJWTWithArrayClaimIntegers() throws Exception { + JWT.require(Algorithm.none()).withArrayClaim("arrayKey", 1, 2).build(); } @Test - public void shouldGetKeyId() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleSJ9.e30.von1Vt9tq9cn5ZYdX1f4cf2EE7fUvb5BCBlKOTm9YWs"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getKeyId(), is("key")); - } - - @Test - public void shouldGetCustomClaims() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImlzQWRtaW4iOnRydWV9.eyJpc0FkbWluIjoibm9wZSJ9.YDKBAgUDbh0PkhioDcLNzdQ8c2Gdf_yS6zdEtJQS3F0"; - DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - assertThat(jwt.getHeaderClaim("isAdmin"), notNullValue()); - assertThat(jwt.getHeaderClaim("isAdmin").asBoolean(), is(true)); - assertThat(jwt.getClaim("isAdmin"), notNullValue()); - assertThat(jwt.getClaim("isAdmin").asString(), is("nope")); - } - - // Sign - - @Test - public void shouldCreateAnEmptyHMAC256SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.HMAC256("secret")); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "HS256")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.HMAC256("secret")) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyHMAC384SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.HMAC384("secret")); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "HS384")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.HMAC384("secret")) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyHMAC512SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.HMAC512("secret")); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "HS512")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.HMAC512("secret")) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyRSA256SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.RSA256((RSAKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_RSA, "RSA"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "RS256")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.RSA256((RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"))) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyRSA384SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.RSA384((RSAKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_RSA, "RSA"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "RS384")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.RSA384((RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"))) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyRSA512SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.RSA512((RSAKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_RSA, "RSA"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "RS512")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.RSA512((RSAKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_RSA, "RSA"))) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyECDSA256SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.ECDSA256((ECKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_EC_256, "EC"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "ES256")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.ECDSA256((ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_256, "EC"))) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyECDSA384SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.ECDSA384((ECKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_EC_384, "EC"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "ES384")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.ECDSA384((ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_384, "EC"))) - .build(); - assertThat(verified, is(notNullValue())); - } - - @Test - public void shouldCreateAnEmptyECDSA512SignedToken() throws Exception { - String signed = JWT.create().sign(Algorithm.ECDSA512((ECKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_EC_512, "EC"))); - assertThat(signed, is(notNullValue())); - - String[] parts = signed.split("\\."); - String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8); - assertThat(headerJson, JsonMatcher.hasEntry("alg", "ES512")); - assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT")); - assertThat(parts[1], is("e30")); - - JWTVerifier verified = JWT.require(Algorithm.ECDSA512((ECKey) PemUtils.readPublicKeyFromFile(PUBLIC_KEY_FILE_EC_512, "EC"))) - .build(); - assertThat(verified, is(notNullValue())); + public void testJWTNullAlgorithm() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("The Algorithm cannot be null."); + JWT.require(null); } } diff --git a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java deleted file mode 100644 index d5826c24..00000000 --- a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java +++ /dev/null @@ -1,577 +0,0 @@ -package com.auth0.jwt; - -import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.AlgorithmMismatchException; -import com.auth0.jwt.exceptions.InvalidClaimException; -import com.auth0.jwt.exceptions.TokenExpiredException; -import com.auth0.jwt.interfaces.Clock; -import com.auth0.jwt.interfaces.DecodedJWT; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class JWTVerifierTest { - - private static final long DATE_TOKEN_MS_VALUE = 1477592 * 1000; - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void shouldThrowWhenInitializedWithoutAlgorithm() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("The Algorithm cannot be null"); - JWTVerifier.init(null); - } - - @Test - public void shouldThrowWhenAlgorithmDoesntMatchTheTokensAlgorithm() throws Exception { - exception.expect(AlgorithmMismatchException.class); - exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); - JWTVerifier verifier = JWTVerifier.init(Algorithm.HMAC512("secret")).build(); - verifier.verify("eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.s69x7Mmu4JqwmdxiK6sesALO7tcedbFsKEEITUxw9ho"); - } - - @Test - public void shouldValidateIssuer() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withIssuer("auth0") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidIssuer() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'iss' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withIssuer("invalid") - .build() - .verify(token); - } - - @Test - public void shouldValidateSubject() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withSubject("1234567890") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidSubject() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'sub' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withSubject("invalid") - .build() - .verify(token); - } - - @Test - public void shouldValidateAudience() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJNYXJrIn0.xWB6czYI0XObbVhLAxe55TwChWZg7zO08RxONWU2iY4"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withAudience("Mark") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - - String tokenArr = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiTWFyayIsIkRhdmlkIl19.6WfbIt8m61f9WlCYIQn5CThvw4UNyC66qrPaoinfssw"; - DecodedJWT jwtArr = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withAudience("Mark", "David") - .build() - .verify(tokenArr); - - assertThat(jwtArr, is(notNullValue())); - } - - @Test - public void shouldAcceptPartialAudience() throws Exception { - //Token 'aud' = ["Mark", "David", "John"] - String tokenArr = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiTWFyayIsIkRhdmlkIiwiSm9obiJdfQ.DX5xXiCaYvr54x_iL0LZsJhK7O6HhAdHeDYkgDeb0Rw"; - DecodedJWT jwtArr = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withAudience("John") - .build() - .verify(tokenArr); - - assertThat(jwtArr, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidAudience() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'aud' value doesn't contain the required audience."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withAudience("nope") - .build() - .verify(token); - } - - @Test - public void shouldThrowOnNullCustomClaimName() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("The Custom Claim's name can't be null."); - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim(null, "value"); - } - - @Test - public void shouldThrowOnInvalidCustomClaimValueOfTypeString() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", "value") - .build() - .verify(token); - } - - @Test - public void shouldThrowOnInvalidCustomClaimValueOfTypeInteger() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", 123) - .build() - .verify(token); - } - - @Test - public void shouldThrowOnInvalidCustomClaimValueOfTypeDouble() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", 23.45) - .build() - .verify(token); - } - - @Test - public void shouldThrowOnInvalidCustomClaimValueOfTypeBoolean() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", true) - .build() - .verify(token); - } - - - @Test - public void shouldThrowOnInvalidCustomClaimValueOfTypeDate() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", new Date()) - .build() - .verify(token); - } - - @Test - public void shouldThrowOnInvalidCustomClaimValue() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'name' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; - Map map = new HashMap<>(); - map.put("name", new Object()); - JWTVerifier verifier = new JWTVerifier(Algorithm.HMAC256("secret"), map, new ClockImpl()); - verifier.verify(token); - } - - @Test - public void shouldValidateCustomClaimOfTypeString() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidmFsdWUifQ.Jki8pvw6KGbxpMinufrgo6RDL1cu7AtNMJYVh6t-_cE"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", "value") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomClaimOfTypeInteger() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxMjN9.XZAudnA7h3_Al5kJydzLjw6RzZC3Q6OvnLEYlhNW7HA"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", 123) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomClaimOfTypeLong() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjo5MjIzMzcyMDM2ODU0Nzc2MDB9.km-IwQ5IDnTZFmuJzhSgvjTzGkn_Z5X29g4nAuVC56I"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", 922337203685477600L) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomClaimOfTypeDouble() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoyMy40NX0.7pyX2OmEGaU9q15T8bGFqRm-d3RVTYnqmZNZtxMKSlA"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", 23.45) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomClaimOfTypeBoolean() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjp0cnVlfQ.FwQ8VfsZNRqBa9PXMinSIQplfLU4-rkCLfIlTLg_MV0"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", true) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomClaimOfTypeDate() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxNDc4ODkxNTIxfQ.mhioumeok8fghQEhTKF3QtQAksSvZ_9wIhJmgZLhJ6c"; - Date date = new Date(1478891521000L); - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withClaim("name", date) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomArrayClaimOfTypeString() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbInRleHQiLCIxMjMiLCJ0cnVlIl19.lxM8EcmK1uSZRAPd0HUhXGZJdauRmZmLjoeqz4J9yAA"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withArrayClaim("name", "text", "123", "true") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateCustomArrayClaimOfTypeInteger() throws Exception { - String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbMSwyLDNdfQ.UEuMKRQYrzKAiPpPLhIVawWkKWA1zj0_GderrWUIyFE"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withArrayClaim("name", 1, 2, 3) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - // Generic Delta - @SuppressWarnings("RedundantCast") - @Test - public void shouldAddDefaultLeewayToDateClaims() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, hasEntry("iat", (Object) 0L)); - assertThat(verifier.claims, hasEntry("exp", (Object) 0L)); - assertThat(verifier.claims, hasEntry("nbf", (Object) 0L)); - } - - @SuppressWarnings("RedundantCast") - @Test - public void shouldAddCustomLeewayToDateClaims() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .acceptLeeway(1234L) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); - } - - @SuppressWarnings("RedundantCast") - @Test - public void shouldOverrideDefaultIssuedAtLeeway() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .acceptLeeway(1234L) - .acceptIssuedAt(9999L) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, hasEntry("iat", (Object) 9999L)); - assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); - } - - @SuppressWarnings("RedundantCast") - @Test - public void shouldOverrideDefaultExpiresAtLeeway() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .acceptLeeway(1234L) - .acceptExpiresAt(9999L) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("exp", (Object) 9999L)); - assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); - } - - @SuppressWarnings("RedundantCast") - @Test - public void shouldOverrideDefaultNotBeforeLeeway() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .acceptLeeway(1234L) - .acceptNotBefore(9999L) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); - assertThat(verifier.claims, hasEntry("nbf", (Object) 9999L)); - } - - @Test - public void shouldThrowOnNegativeCustomLeeway() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Leeway value can't be negative."); - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier.init(algorithm) - .acceptLeeway(-1); - } - - // Expires At - @Test - public void shouldValidateExpiresAtWithLeeway() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE + 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) - .acceptExpiresAt(2); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldValidateExpiresAtIfPresent() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidExpiresAtIfPresent() throws Exception { - exception.expect(TokenExpiredException.class); - exception.expectMessage(startsWith("The Token has expired on")); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE + 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - verification - .build(clock) - .verify(token); - } - - @Test - public void shouldThrowOnNegativeExpiresAtLeeway() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Leeway value can't be negative."); - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier.init(algorithm) - .acceptExpiresAt(-1); - } - - // Not before - @Test - public void shouldValidateNotBeforeWithLeeway() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0Nzc1OTJ9.wq4ZmnSF2VOxcQBxPLfeh1J2Ozy1Tj5iUaERm3FKaw8"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) - .acceptNotBefore(2); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidNotBeforeIfPresent() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage(startsWith("The Token can't be used before")); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0Nzc1OTJ9.wq4ZmnSF2VOxcQBxPLfeh1J2Ozy1Tj5iUaERm3FKaw8"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - verification - .build(clock) - .verify(token); - } - - @Test - public void shouldValidateNotBeforeIfPresent() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnNegativeNotBeforeLeeway() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Leeway value can't be negative."); - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier.init(algorithm) - .acceptNotBefore(-1); - } - - // Issued At - @Test - public void shouldValidateIssuedAtWithLeeway() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) - .acceptIssuedAt(2); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidIssuedAtIfPresent() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage(startsWith("The Token can't be used before")); - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - verification - .build(clock) - .verify(token); - } - - @Test - public void shouldValidateIssuedAtIfPresent() throws Exception { - Clock clock = mock(Clock.class); - when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); - - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; - JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); - DecodedJWT jwt = verification - .build(clock) - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnNegativeIssuedAtLeeway() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Leeway value can't be negative."); - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier.init(algorithm) - .acceptIssuedAt(-1); - } - - @Test - public void shouldValidateJWTId() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJqd3RfaWRfMTIzIn0.0kegfXUvwOYioP8PDaLMY1IlV8HOAzSVz3EGL7-jWF4"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .withJWTId("jwt_id_123") - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } - - @Test - public void shouldThrowOnInvalidJWTId() throws Exception { - exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'jti' value doesn't match the required one."); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJqd3RfaWRfMTIzIn0.0kegfXUvwOYioP8PDaLMY1IlV8HOAzSVz3EGL7-jWF4"; - JWTVerifier.init(Algorithm.HMAC256("secret")) - .withJWTId("invalid") - .build() - .verify(token); - } - - @Test - public void shouldRemoveClaimWhenPassingNull() throws Exception { - Algorithm algorithm = mock(Algorithm.class); - JWTVerifier verifier = JWTVerifier.init(algorithm) - .withIssuer("iss") - .withIssuer(null) - .build(); - - assertThat(verifier.claims, is(notNullValue())); - assertThat(verifier.claims, not(hasKey("iss"))); - } - - @Test - public void shouldSkipClaimValidationsIfNoClaimsRequired() throws Exception { - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M"; - DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) - .build() - .verify(token); - - assertThat(jwt, is(notNullValue())); - } -} diff --git a/lib/src/test/java/com/auth0/jwt/MainTestSignatures.java b/lib/src/test/java/com/auth0/jwt/MainTestSignatures.java new file mode 100644 index 00000000..3895656b --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/MainTestSignatures.java @@ -0,0 +1,146 @@ +package com.auth0.jwt; + +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.GoogleJwtCreator; +import com.auth0.jwt.creators.GoogleJwtCreatorTest; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.GoogleVerification; +import com.auth0.jwt.jwts.GoogleJWT; +import com.auth0.jwt.jwts.JWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class MainTestSignatures { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Date exp = generateRandomExpDateInFuture(); + private Date iat = generateRandomIatDateInPast(); + + @Test + public void testComplainOnNone() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("The Algorithm cannot be null."); + + String token = JWT.create().withIssuer("accounts.fake.com").withSubject("subject") + .withAudience("audience") + .sign(null); + GoogleVerification verification = GoogleJWT.require(null); + JWT verifier = verification.createVerifierForGoogle(GoogleJwtCreatorTest.PICTURE, GoogleJwtCreatorTest.EMAIL, asList("accounts.fake.com"), asList("audience"), + GoogleJwtCreatorTest.NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testVerifyingWithEmptyKey() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Empty key"); + Algorithm algorithm = Algorithm.HMAC256(""); + String token = GoogleJwtCreator.build() + .withPicture(GoogleJwtCreatorTest.PICTURE) + .withEmail(GoogleJwtCreatorTest.EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(GoogleJwtCreatorTest.NAME) + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(GoogleJwtCreatorTest.PICTURE, GoogleJwtCreatorTest.EMAIL,asList("accounts.fake.com"), asList("audience"), + GoogleJwtCreatorTest.NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testConfigurableToMultipleKeys() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(GoogleJwtCreatorTest.PICTURE) + .withEmail(GoogleJwtCreatorTest.EMAIL) + .withSubject("subject", "subject2") + .withAudience("audience", "audience2") + .withExp(exp) + .withIat(iat) + .withName(GoogleJwtCreatorTest.NAME) + .withIssuer("issuer", "issuer2") + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(GoogleJwtCreatorTest.PICTURE, GoogleJwtCreatorTest.EMAIL, asList("issuer", "issuer2"), asList("audience", "audience2"), + GoogleJwtCreatorTest.NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + assertTrue(claims.get(GoogleJwtCreatorTest.PICTURE).asString().equals(GoogleJwtCreatorTest.PICTURE)); + assertTrue(claims.get(GoogleJwtCreatorTest.EMAIL).asString().equals(GoogleJwtCreatorTest.EMAIL)); + List issuers = claims.get(PublicClaims.ISSUER).asList(String.class); + assertTrue(issuers.get(0).equals("issuer")); + assertTrue(issuers.get(1).equals("issuer2")); + List subjects = claims.get(PublicClaims.SUBJECT).asList(String.class); + assertTrue(subjects.get(0).equals("subject")); + assertTrue(subjects.get(1).equals("subject2")); + List audience = claims.get(PublicClaims.AUDIENCE).asList(String.class); + assertTrue(audience.get(0).equals("audience")); + assertTrue(audience.get(1).equals("audience2")); + assertTrue(claims.get(PublicClaims.EXPIRES_AT).asDate().toString().equals(exp.toString())); + assertTrue(claims.get(GoogleJwtCreatorTest.NAME).asString().equals(GoogleJwtCreatorTest.NAME)); + } + + @Test + public void testConfigurableToIncorrectNumberMultipleKeysForAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String[] arr = {"accounts.fake.com", "subject"}; + String token = GoogleJwtCreator.build() + .withPicture(GoogleJwtCreatorTest.PICTURE) + .withEmail(GoogleJwtCreatorTest.EMAIL) + .withSubject("subject", "subject2") + .withAudience("audience", "audience2") + .withExp(exp) + .withIat(iat) + .withName(GoogleJwtCreatorTest.NAME) + .withIssuer("issuer", "issuer2") + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(GoogleJwtCreatorTest.PICTURE, GoogleJwtCreatorTest.EMAIL, asList("issuer", "issuer2"), asList("audience"), + GoogleJwtCreatorTest.NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testConfigurableToIncorrectValueMultipleKeysForAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String[] arr = {"accounts.fake.com", "subject"}; + String token = GoogleJwtCreator.build() + .withPicture(GoogleJwtCreatorTest.PICTURE) + .withEmail(GoogleJwtCreatorTest.EMAIL) + .withSubject("subject", "subject2") + .withAudience("audience", "audience2") + .withExp(exp) + .withIat(iat) + .withName(GoogleJwtCreatorTest.NAME) + .withIssuer("issuer", "issuer2") + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(GoogleJwtCreatorTest.PICTURE, GoogleJwtCreatorTest.EMAIL, asList("issuer", "issuer2"), asList("audience", "audience3"), + GoogleJwtCreatorTest.NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } +} \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/TimeUtil.java b/lib/src/test/java/com/auth0/jwt/TimeUtil.java new file mode 100644 index 00000000..5070088e --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/TimeUtil.java @@ -0,0 +1,28 @@ +package com.auth0.jwt; + +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Random; + +public class TimeUtil { + + public static Date generateRandomExpDateInFuture() { + Random rnd = new Random(); + return new Date(Math.abs(System.currentTimeMillis() + rnd.nextLong())); + } + + public static Date generateRandomIatDateInPast() { + GregorianCalendar gc = new GregorianCalendar(); + int year = randBetween(1900, 2010); + gc.set(gc.YEAR, year); + int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR)); + gc.set(gc.DAY_OF_YEAR, dayOfYear); + + return new Date(gc.getTimeInMillis()); + } + + public static int randBetween(int start, int end) { + return start + (int)Math.round(Math.random() * (end - start)); + } + +} diff --git a/lib/src/test/java/com/auth0/jwt/algorithms/ECDSAAlgorithmTest.java b/lib/src/test/java/com/auth0/jwt/algorithms/ECDSAAlgorithmTest.java index 86bf3c0b..5663e637 100644 --- a/lib/src/test/java/com/auth0/jwt/algorithms/ECDSAAlgorithmTest.java +++ b/lib/src/test/java/com/auth0/jwt/algorithms/ECDSAAlgorithmTest.java @@ -1,9 +1,11 @@ package com.auth0.jwt.algorithms; -import com.auth0.jwt.JWT; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureGenerationException; import com.auth0.jwt.exceptions.SignatureVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.ECDSAKeyProvider; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.hamcrest.Matchers; import org.hamcrest.collection.IsIn; @@ -33,6 +35,7 @@ @SuppressWarnings("deprecation") public class ECDSAAlgorithmTest { + private static final String PRIVATE_KEY_FILE_256 = "src/test/resources/ec256-key-private.pem"; private static final String PUBLIC_KEY_FILE_256 = "src/test/resources/ec256-key-public.pem"; private static final String INVALID_PUBLIC_KEY_FILE_256 = "src/test/resources/ec256-key-public-invalid.pem"; @@ -57,10 +60,12 @@ public class ECDSAAlgorithmTest { @Test public void shouldPassECDSA256VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); Algorithm algorithm = Algorithm.ECDSA256(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -70,17 +75,21 @@ public void shouldThrowOnECDSA256VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); Algorithm algorithm = Algorithm.ECDSA256(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA256VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -90,9 +99,11 @@ public void shouldThrowOnECDSA256VerificationWithDERSignatureWithBothKeys() thro exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -100,9 +111,11 @@ public void shouldPassECDSA256VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; + String token = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; Algorithm algorithm = Algorithm.ECDSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -113,18 +126,22 @@ public void shouldFailECDSA256VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; + String token = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; Algorithm algorithm = Algorithm.ECDSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA256VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withECDSA"); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -133,9 +150,11 @@ public void shouldFailECDSA256VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -148,9 +167,11 @@ public void shouldFailECDSA256VerificationOnInvalidJOSESignatureLength() throws byte[] bytes = new byte[63]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -161,9 +182,11 @@ public void shouldFailECDSA256VerificationOnInvalidJOSESignature() throws Except byte[] bytes = new byte[64]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -175,17 +198,21 @@ public void shouldFailECDSA256VerificationOnInvalidDERSignature() throws Excepti bytes[0] = 0x30; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA384VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); Algorithm algorithm = Algorithm.ECDSA384(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -195,17 +222,21 @@ public void shouldThrowOnECDSA384VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); Algorithm algorithm = Algorithm.ECDSA384(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA384VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; Algorithm algorithm = Algorithm.ECDSA384((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -215,9 +246,11 @@ public void shouldThrowOnECDSA384VerificationWithDERSignatureWithBothKeys() thro exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; Algorithm algorithm = Algorithm.ECDSA384((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -225,9 +258,11 @@ public void shouldPassECDSA384VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; + String token = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; Algorithm algorithm = Algorithm.ECDSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -238,18 +273,22 @@ public void shouldFailECDSA384VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; + String token = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; Algorithm algorithm = Algorithm.ECDSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -258,59 +297,67 @@ public void shouldFailECDSA384VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidJOSESignatureLength() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); - exception.expectCause(isA(SignatureException.class)); - exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[95]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidJOSESignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[96]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidDERSignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[96]; new SecureRandom().nextBytes(bytes); bytes[0] = 0x30; String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA512VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); Algorithm algorithm = Algorithm.ECDSA512(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -320,17 +367,21 @@ public void shouldThrowOnECDSA512VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); Algorithm algorithm = Algorithm.ECDSA512(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA512VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; Algorithm algorithm = Algorithm.ECDSA512((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -340,9 +391,11 @@ public void shouldThrowECDSA512VerificationWithDERSignatureWithBothKeys() throws exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; Algorithm algorithm = Algorithm.ECDSA512((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -350,9 +403,11 @@ public void shouldPassECDSA512VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; + String token = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; Algorithm algorithm = Algorithm.ECDSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -363,18 +418,22 @@ public void shouldFailECDSA512VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; + String token = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; Algorithm algorithm = Algorithm.ECDSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -383,51 +442,57 @@ public void shouldFailECDSA512VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidJOSESignatureLength() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); - exception.expectCause(isA(SignatureException.class)); - exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[131]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidJOSESignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[132]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidDERSignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[132]; new SecureRandom().nextBytes(bytes); bytes[0] = 0x30; String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -440,20 +505,21 @@ public void shouldFailJOSEToDERConversionOnInvalidJOSESignatureLength() throws E byte[] bytes = new byte[256]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; ECPublicKey publicKey = (ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm("ES256", "SHA256withECDSA", 128, provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(NoSuchAlgorithmException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -463,15 +529,16 @@ public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exce ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(InvalidKeyException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -481,15 +548,16 @@ public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid() throws Exception { ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(SignatureException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -499,8 +567,10 @@ public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared() throws Exception ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } //Sign @@ -517,10 +587,12 @@ public void shouldDoECDSA256Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -530,10 +602,12 @@ public void shouldDoECDSA256SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -548,10 +622,12 @@ public void shouldDoECDSA256SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -586,10 +662,12 @@ public void shouldDoECDSA384Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -599,10 +677,12 @@ public void shouldDoECDSA384SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -617,10 +697,12 @@ public void shouldDoECDSA384SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -655,10 +737,12 @@ public void shouldDoECDSA512Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -668,10 +752,12 @@ public void shouldDoECDSA512SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @@ -687,10 +773,12 @@ public void shouldDoECDSA512SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -854,8 +942,10 @@ public void shouldSignAndVerifyWithECDSA256() throws Exception { byte[] signature = algorithm256.sign(content256.getBytes()); String signature256 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content256 + "." + signature256; - algorithm256.verify(JWT.decode(jwt)); + String token = content256 + "." + signature256; + JWT jwt = JWT.require(algorithm256).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm256.verify(decoded); } } @@ -868,8 +958,10 @@ public void shouldSignAndVerifyWithECDSA384() throws Exception { byte[] signature = algorithm384.sign(content384.getBytes()); String signature384 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content384 + "." + signature384; - algorithm384.verify(JWT.decode(jwt)); + String token = content384 + "." + signature384; + JWT jwt = JWT.require(algorithm384).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm384.verify(decoded); } } @@ -882,8 +974,10 @@ public void shouldSignAndVerifyWithECDSA512() throws Exception { byte[] signature = algorithm512.sign(content512.getBytes()); String signature512 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content512 + "." + signature512; - algorithm512.verify(JWT.decode(jwt)); + String token = content512 + "." + signature512; + JWT jwt = JWT.require(algorithm512).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm512.verify(decoded); } } @@ -1164,4 +1258,5 @@ static void assertValidDERSignature(byte[] derSignature, int numberSize, boolean Assert.assertThat(derSignature.length, is(totalLength)); } + } \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/algorithms/ECDSABouncyCastleProviderTests.java b/lib/src/test/java/com/auth0/jwt/algorithms/ECDSABouncyCastleProviderTests.java index 4af1c4ec..e30547b7 100644 --- a/lib/src/test/java/com/auth0/jwt/algorithms/ECDSABouncyCastleProviderTests.java +++ b/lib/src/test/java/com/auth0/jwt/algorithms/ECDSABouncyCastleProviderTests.java @@ -1,9 +1,11 @@ package com.auth0.jwt.algorithms; -import com.auth0.jwt.JWT; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureGenerationException; import com.auth0.jwt.exceptions.SignatureVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.ECDSAKeyProvider; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.AfterClass; @@ -32,6 +34,7 @@ public class ECDSABouncyCastleProviderTests { + private static final String PRIVATE_KEY_FILE_256 = "src/test/resources/ec256-key-private.pem"; private static final String PUBLIC_KEY_FILE_256 = "src/test/resources/ec256-key-public.pem"; private static final String INVALID_PUBLIC_KEY_FILE_256 = "src/test/resources/ec256-key-public-invalid.pem"; @@ -74,10 +77,12 @@ public void shouldPreferBouncyCastleProvider() throws Exception { @Test public void shouldPassECDSA256VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); Algorithm algorithm = Algorithm.ECDSA256(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -87,17 +92,21 @@ public void shouldThrowOnECDSA256VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); Algorithm algorithm = Algorithm.ECDSA256(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA256VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -107,9 +116,11 @@ public void shouldThrowOnECDSA256VerificationWithDERSignatureWithBothKeys() thro exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.MEYCIQDiJWTf5jS/hFPj/0hpCWn7x1n/h+xPMjKWCs9MMusS9AIhAMcFPJVLe2A9uvb8hl8sRO2IpGoKDRpDmyH14ixNPAHW"; Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -117,9 +128,11 @@ public void shouldPassECDSA256VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; + String token = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; Algorithm algorithm = Algorithm.ECDSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -130,18 +143,22 @@ public void shouldFailECDSA256VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; + String token = "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.D_oU4CB0ZEsxHOjcWnmS3ZJvlTzm6WcGFx-HASxnvcB2Xu2WjI-axqXH9xKq45aPBDs330JpRhJmqBSc2K8MXQ"; Algorithm algorithm = Algorithm.ECDSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA256VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withECDSA"); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -150,9 +167,11 @@ public void shouldFailECDSA256VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.W9qfN1b80B9hnMo49WL8THrOsf1vEjOhapeFemPMGySzxTcgfyudS5esgeBTO908X5SLdAr5jMwPUPBs9b6nNg"; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -165,9 +184,11 @@ public void shouldFailECDSA256VerificationOnInvalidJOSESignatureLength() throws byte[] bytes = new byte[63]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -178,9 +199,11 @@ public void shouldFailECDSA256VerificationOnInvalidJOSESignature() throws Except byte[] bytes = new byte[64]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -192,17 +215,21 @@ public void shouldFailECDSA256VerificationOnInvalidDERSignature() throws Excepti bytes[0] = 0x30; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA256((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_256, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA384VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); Algorithm algorithm = Algorithm.ECDSA384(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -212,17 +239,21 @@ public void shouldThrowOnECDSA384VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); Algorithm algorithm = Algorithm.ECDSA384(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA384VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.50UU5VKNdF1wfykY8jQBKpvuHZoe6IZBJm5NvoB8bR-hnRg6ti-CHbmvoRtlLfnHfwITa_8cJMy6TenMC2g63GQHytc8rYoXqbwtS4R0Ko_AXbLFUmfxnGnMC6v4MS_z"; Algorithm algorithm = Algorithm.ECDSA384((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -232,9 +263,11 @@ public void shouldThrowOnECDSA384VerificationWithDERSignatureWithBothKeys() thro exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9.MGUCMQDnRRTlUo10XXB/KRjyNAEqm+4dmh7ohkEmbk2+gHxtH6GdGDq2L4Idua+hG2Ut+ccCMH8CE2v/HCTMuk3pzAtoOtxkB8rXPK2KF6m8LUuEdCqPwF2yxVJn8ZxpzAur+DEv8w=="; Algorithm algorithm = Algorithm.ECDSA384((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -242,9 +275,11 @@ public void shouldPassECDSA384VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_384, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; + String token = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; Algorithm algorithm = Algorithm.ECDSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -255,18 +290,22 @@ public void shouldFailECDSA384VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; + String token = "eyJhbGciOiJFUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.9kjGuFTPx3ylfpqL0eY9H7TGmPepjQOBKI8UPoEvby6N7dDLF5HxLohosNxxFymNT7LzpeSgOPAB0wJEwG2Nl2ukgdUOpZOf492wog_i5ZcZmAykd3g1QH7onrzd69GU"; Algorithm algorithm = Algorithm.ECDSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -275,59 +314,67 @@ public void shouldFailECDSA384VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; + String token = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJhdXRoMCJ9._k5h1KyO-NE0R2_HAw0-XEc0bGT5atv29SxHhOGC9JDqUHeUdptfCK_ljQ01nLVt2OQWT2SwGs-TuyHDFmhPmPGFZ9wboxvq_ieopmYqhQilNAu-WF-frioiRz9733fU"; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidJOSESignatureLength() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); - exception.expectCause(isA(SignatureException.class)); - exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[95]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidJOSESignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[96]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA384VerificationOnInvalidDERSignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[96]; new SecureRandom().nextBytes(bytes); bytes[0] = 0x30; String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA384((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_384, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA512VerificationWithJOSESignature() throws Exception { - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); Algorithm algorithm = Algorithm.ECDSA512(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -337,17 +384,21 @@ public void shouldThrowOnECDSA512VerificationWithDERSignature() throws Exception exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; ECKey key = (ECKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); Algorithm algorithm = Algorithm.ECDSA512(key); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassECDSA512VerificationWithJOSESignatureWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AeCJPDIsSHhwRSGZCY6rspi8zekOw0K9qYMNridP1Fu9uhrA1QrG-EUxXlE06yvmh2R7Rz0aE7kxBwrnq8L8aOBCAYAsqhzPeUvyp8fXjjgs0Eto5I0mndE2QHlgcMSFASyjHbU8wD2Rq7ZNzGQ5b2MZfpv030WGUajT-aZYWFUJHVg2"; Algorithm algorithm = Algorithm.ECDSA512((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -357,9 +408,11 @@ public void shouldThrowECDSA512VerificationWithDERSignatureWithBothKeys() throws exception.expectCause(isA(SignatureException.class)); exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.MIGIAkIB4Ik8MixIeHBFIZkJjquymLzN6Q7DQr2pgw2uJ0/UW726GsDVCsb4RTFeUTTrK+aHZHtHPRoTuTEHCuerwvxo4EICQgGALKocz3lL8qfH1444LNBLaOSNJp3RNkB5YHDEhQEsox21PMA9kau2TcxkOW9jGX6b9N9FhlGo0/mmWFhVCR1YNg=="; Algorithm algorithm = Algorithm.ECDSA512((ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"), (ECPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -367,9 +420,11 @@ public void shouldPassECDSA512VerificationWithProvidedPublicKey() throws Excepti ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE_512, "EC"); when(provider.getPublicKeyById("my-key-id")).thenReturn((ECPublicKey) publicKey); - String jwt = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; + String token = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; Algorithm algorithm = Algorithm.ECDSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -380,18 +435,22 @@ public void shouldFailECDSA512VerificationWhenProvidedPublicKeyIsNull() throws E exception.expectCause(hasMessage(is("The given Public Key is null."))); ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; + String token = "eyJhbGciOiJFUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.AGxEwbsYa2bQ7Y7DAcTQnVD8PmLSlhJ20jg2OfdyPnqdXI8SgBaG6lGciq3_pofFhs1HEoFoJ33Jcluha24oMHIvAfwu8qbv_Wq3L2eI9Q0L0p6ul8Pd_BS8adRa2PgLc36xXGcRc7ID5YH-CYaQfsTp5YIaF0Po3h0QyCoQ6ZiYQkqm"; Algorithm algorithm = Algorithm.ECDSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -400,51 +459,57 @@ public void shouldFailECDSA512VerificationWhenUsingPrivateKey() throws Exception exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; + String token = "eyJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJhdXRoMCJ9.AZgdopFFsN0amCSs2kOucXdpylD31DEm5ChK1PG0_gq5Mf47MrvVph8zHSVuvcrXzcE1U3VxeCg89mYW1H33Y-8iAF0QFkdfTUQIWKNObH543WNMYYssv3OtOj0znPv8atDbaF8DMYAtcT1qdmaSJRhx-egRE9HGZkinPh9CfLLLt58X"; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidJOSESignatureLength() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); - exception.expectCause(isA(SignatureException.class)); - exception.expectCause(hasMessage(is("Invalid JOSE signature format."))); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[131]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidJOSESignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[132]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailECDSA512VerificationOnInvalidDERSignature() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withECDSA"); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); byte[] bytes = new byte[132]; new SecureRandom().nextBytes(bytes); bytes[0] = 0x30; String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; Algorithm algorithm = Algorithm.ECDSA512((ECKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE_512, "EC")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -457,20 +522,21 @@ public void shouldFailJOSEToDERConversionOnInvalidJOSESignatureLength() throws E byte[] bytes = new byte[256]; new SecureRandom().nextBytes(bytes); String signature = Base64.encodeBase64URLSafeString(bytes); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature; ECPublicKey publicKey = (ECPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE_256, "EC"); ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm("ES256", "SHA256withECDSA", 128, provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(NoSuchAlgorithmException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -480,15 +546,16 @@ public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exce ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(InvalidKeyException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -498,15 +565,16 @@ public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid() throws Exception { ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(SignatureException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -516,8 +584,10 @@ public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared() throws Exception ECPrivateKey privateKey = mock(ECPrivateKey.class); ECDSAKeyProvider provider = ECDSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new ECDSAAlgorithm(crypto, "some-alg", "some-algorithm", 32, provider); - String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } //Sign @@ -534,10 +604,12 @@ public void shouldDoECDSA256Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -547,10 +619,12 @@ public void shouldDoECDSA256SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -565,10 +639,12 @@ public void shouldDoECDSA256SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -603,10 +679,12 @@ public void shouldDoECDSA384Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -616,10 +694,12 @@ public void shouldDoECDSA384SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -634,10 +714,12 @@ public void shouldDoECDSA384SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -672,10 +754,12 @@ public void shouldDoECDSA512Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -685,10 +769,12 @@ public void shouldDoECDSA512SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @@ -704,10 +790,12 @@ public void shouldDoECDSA512SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -871,8 +959,10 @@ public void shouldSignAndVerifyWithECDSA256() throws Exception { byte[] signature = algorithm256.sign(content256.getBytes()); String signature256 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content256 + "." + signature256; - algorithm256.verify(JWT.decode(jwt)); + String token = content256 + "." + signature256; + JWT jwt = JWT.require(algorithm256).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm256.verify(decoded); } } @@ -885,8 +975,10 @@ public void shouldSignAndVerifyWithECDSA384() throws Exception { byte[] signature = algorithm384.sign(content384.getBytes()); String signature384 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content384 + "." + signature384; - algorithm384.verify(JWT.decode(jwt)); + String token = content384 + "." + signature384; + JWT jwt = JWT.require(algorithm384).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm384.verify(decoded); } } @@ -899,8 +991,10 @@ public void shouldSignAndVerifyWithECDSA512() throws Exception { byte[] signature = algorithm512.sign(content512.getBytes()); String signature512 = Base64.encodeBase64URLSafeString((signature)); - String jwt = content512 + "." + signature512; - algorithm512.verify(JWT.decode(jwt)); + String token = content512 + "." + signature512; + JWT jwt = JWT.require(algorithm512).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm512.verify(decoded); } } @@ -1053,5 +1147,4 @@ public void shouldDecodeECDSA512DER() throws Exception { joseSignature = algorithm512.DERToJOSE(derSignature); assertValidJOSESignature(joseSignature, 66, true, true); } - } diff --git a/lib/src/test/java/com/auth0/jwt/algorithms/HMACAlgorithmTest.java b/lib/src/test/java/com/auth0/jwt/algorithms/HMACAlgorithmTest.java index 2d5fd301..15900928 100644 --- a/lib/src/test/java/com/auth0/jwt/algorithms/HMACAlgorithmTest.java +++ b/lib/src/test/java/com/auth0/jwt/algorithms/HMACAlgorithmTest.java @@ -1,9 +1,10 @@ package com.auth0.jwt.algorithms; -import com.auth0.jwt.JWT; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureGenerationException; import com.auth0.jwt.exceptions.SignatureVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.junit.Rule; import org.junit.Test; @@ -38,10 +39,11 @@ public void shouldGetStringBytes() throws Exception { @Test public void shouldPassHMAC256Verification() throws Exception { - String jwt = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; + String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; Algorithm algorithmString = Algorithm.HMAC256("secret"); Algorithm algorithmBytes = Algorithm.HMAC256("secret".getBytes(StandardCharsets.UTF_8)); - DecodedJWT decoded = JWT.decode(jwt); + JWT jwt = JWT.require(algorithmString).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); algorithmString.verify(decoded); algorithmBytes.verify(decoded); } @@ -50,26 +52,31 @@ public void shouldPassHMAC256Verification() throws Exception { public void shouldFailHMAC256VerificationWithInvalidSecretString() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA256"); - String jwt = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; + String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; Algorithm algorithm = Algorithm.HMAC256("not_real_secret"); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailHMAC256VerificationWithInvalidSecretBytes() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA256"); - String jwt = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; + String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; Algorithm algorithm = Algorithm.HMAC256("not_real_secret".getBytes(StandardCharsets.UTF_8)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassHMAC384Verification() throws Exception { - String jwt = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; + String token = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; Algorithm algorithmString = Algorithm.HMAC384("secret"); Algorithm algorithmBytes = Algorithm.HMAC384("secret".getBytes(StandardCharsets.UTF_8)); - DecodedJWT decoded = JWT.decode(jwt); + JWT jwt = JWT.require(algorithmString).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); algorithmString.verify(decoded); algorithmBytes.verify(decoded); } @@ -78,26 +85,31 @@ public void shouldPassHMAC384Verification() throws Exception { public void shouldFailHMAC384VerificationWithInvalidSecretString() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA384"); - String jwt = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; + String token = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; Algorithm algorithm = Algorithm.HMAC384("not_real_secret"); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailHMAC384VerificationWithInvalidSecretBytes() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA384"); - String jwt = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; + String token = "eyJhbGciOiJIUzM4NCIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.uztpK_wUMYJhrRv8SV-1LU4aPnwl-EM1q-wJnqgyb5DHoDteP6lN_gE1xnZJH5vw"; Algorithm algorithm = Algorithm.HMAC384("not_real_secret".getBytes(StandardCharsets.UTF_8)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassHMAC512Verification() throws Exception { - String jwt = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; + String token = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; Algorithm algorithmString = Algorithm.HMAC512("secret"); Algorithm algorithmBytes = Algorithm.HMAC512("secret".getBytes(StandardCharsets.UTF_8)); - DecodedJWT decoded = JWT.decode(jwt); + JWT jwt = JWT.require(algorithmString).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); algorithmString.verify(decoded); algorithmBytes.verify(decoded); } @@ -106,48 +118,39 @@ public void shouldPassHMAC512Verification() throws Exception { public void shouldFailHMAC512VerificationWithInvalidSecretString() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA512"); - String jwt = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; + String token = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; Algorithm algorithm = Algorithm.HMAC512("not_real_secret"); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailHMAC512VerificationWithInvalidSecretBytes() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA512"); - String jwt = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; + String token = "eyJhbGciOiJIUzUxMiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.VUo2Z9SWDV-XcOc_Hr6Lff3vl7L9e5Vb8ThXpmGDFjHxe3Dr1ZBmUChYF-xVA7cAdX1P_D4ZCUcsv3IefpVaJw"; Algorithm algorithm = Algorithm.HMAC512("not_real_secret".getBytes(StandardCharsets.UTF_8)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } - @Test - public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(NoSuchAlgorithmException.class)); - - CryptoHelper crypto = mock(CryptoHelper.class); - when(crypto.verifySignatureFor(anyString(), any(byte[].class), any(byte[].class), any(byte[].class))) - .thenThrow(NoSuchAlgorithmException.class); - - Algorithm algorithm = new HMACAlgorithm(crypto, "some-alg", "some-algorithm", "secret".getBytes(StandardCharsets.UTF_8)); - String jwt = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - algorithm.verify(JWT.decode(jwt)); - } @Test public void shouldThrowOnVerifyWhenTheSecretIsInvalid() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(InvalidKeyException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(byte[].class), any(byte[].class), any(byte[].class))) .thenThrow(InvalidKeyException.class); Algorithm algorithm = new HMACAlgorithm(crypto, "some-alg", "some-algorithm", "secret".getBytes(StandardCharsets.UTF_8)); - String jwt = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } // Sign @@ -165,12 +168,14 @@ public void shouldDoHMAC256SigningWithBytes() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "s69x7Mmu4JqwmdxiK6sesALO7tcedbFsKEEITUxw9ho"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -181,12 +186,14 @@ public void shouldDoHMAC384SigningWithBytes() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "4-y2Gxz_foN0jAOFimmBPF7DWxf4AsjM20zxNkHg8Zah5Q64G42P9GfjmUp4Hldt"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -197,12 +204,14 @@ public void shouldDoHMAC512SigningWithBytes() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "OXWyxmf-VcVo8viOiTFfLaEy6mrQqLEos5R82Xsx8mtFxQadJAQ1aVniIWN8qT2GNE_pMQPcdzk4x7Cqxsp1dw"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -213,12 +222,14 @@ public void shouldDoHMAC256SigningWithString() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "s69x7Mmu4JqwmdxiK6sesALO7tcedbFsKEEITUxw9ho"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -229,12 +240,14 @@ public void shouldDoHMAC384SigningWithString() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "4-y2Gxz_foN0jAOFimmBPF7DWxf4AsjM20zxNkHg8Zah5Q64G42P9GfjmUp4Hldt"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -245,12 +258,14 @@ public void shouldDoHMAC512SigningWithString() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "OXWyxmf-VcVo8viOiTFfLaEy6mrQqLEos5R82Xsx8mtFxQadJAQ1aVniIWN8qT2GNE_pMQPcdzk4x7Cqxsp1dw"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/algorithms/NoneAlgorithmTest.java b/lib/src/test/java/com/auth0/jwt/algorithms/NoneAlgorithmTest.java index f6e72b84..7fb2b15f 100644 --- a/lib/src/test/java/com/auth0/jwt/algorithms/NoneAlgorithmTest.java +++ b/lib/src/test/java/com/auth0/jwt/algorithms/NoneAlgorithmTest.java @@ -1,8 +1,9 @@ package com.auth0.jwt.algorithms; -import com.auth0.jwt.JWT; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.SignatureVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.jwts.JWT; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -19,30 +20,37 @@ public class NoneAlgorithmTest { @Test public void shouldPassNoneVerification() throws Exception { Algorithm algorithm = Algorithm.none(); - String jwt = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9."; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9."; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailNoneVerificationWhenTokenHasTwoParts() throws Exception { exception.expect(JWTDecodeException.class); exception.expectMessage("The token was expected to have 3 parts, but got 2."); - String jwt = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9"; + String token = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9"; Algorithm algorithm = Algorithm.none(); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailNoneVerificationWhenSignatureIsPresent() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: none"); - String jwt = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9.Ox-WRXRaGAuWt2KfPvWiGcCrPqZtbp_4OnQzZXaTfss"; + String token = "eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJpc3MiOiJhdXRoMCJ9.Ox-WRXRaGAuWt2KfPvWiGcCrPqZtbp_4OnQzZXaTfss"; Algorithm algorithm = Algorithm.none(); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldReturnNullSigningKeyId() throws Exception { assertThat(Algorithm.none().getSigningKeyId(), is(nullValue())); } + } \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/algorithms/RSAAlgorithmTest.java b/lib/src/test/java/com/auth0/jwt/algorithms/RSAAlgorithmTest.java index 9025f9e4..89c755c9 100644 --- a/lib/src/test/java/com/auth0/jwt/algorithms/RSAAlgorithmTest.java +++ b/lib/src/test/java/com/auth0/jwt/algorithms/RSAAlgorithmTest.java @@ -1,9 +1,11 @@ package com.auth0.jwt.algorithms; -import com.auth0.jwt.JWT; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureGenerationException; import com.auth0.jwt.exceptions.SignatureVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.RSAKeyProvider; +import com.auth0.jwt.jwts.JWT; import org.apache.commons.codec.binary.Base64; import org.junit.Rule; import org.junit.Test; @@ -39,16 +41,20 @@ public class RSAAlgorithmTest { @Test public void shouldPassRSA256Verification() throws Exception { - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; Algorithm algorithm = Algorithm.RSA256((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassRSA256VerificationWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"), (RSAPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -56,9 +62,11 @@ public void shouldPassRSA256VerificationWithProvidedPublicKey() throws Exception RSAKeyProvider provider = mock(RSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"); when(provider.getPublicKeyById("my-key-id")).thenReturn((RSAPublicKey) publicKey); - String jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.jXrbue3xJmnzWH9kU-uGeCTtgbQEKbch8uHd4Z52t86ncNyepfusl_bsyLJIcxMwK7odRzKiSE9efV9JaRSEDODDBdMeCzODFx82uBM7e46T1NLVSmjYIM7Hcfh81ZeTIk-hITvgtL6hvTdeJWOCZAB0bs18qSVW5SvursRUhY38xnhuNI6HOHCtqp7etxWAu6670L53I3GtXsmi6bXIzv_0v1xZcAFg4HTvXxfhfj3oCqkSs2nC27mHxBmQtmZKWmXk5HzVUyPRwTUWx5wHPT_hCsGer-CMCAyGsmOg466y1KDqf7ogpMYojfVZGWBsyA39LO1oWZ4Ryomkn8t5Vg"; + String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.jXrbue3xJmnzWH9kU-uGeCTtgbQEKbch8uHd4Z52t86ncNyepfusl_bsyLJIcxMwK7odRzKiSE9efV9JaRSEDODDBdMeCzODFx82uBM7e46T1NLVSmjYIM7Hcfh81ZeTIk-hITvgtL6hvTdeJWOCZAB0bs18qSVW5SvursRUhY38xnhuNI6HOHCtqp7etxWAu6670L53I3GtXsmi6bXIzv_0v1xZcAFg4HTvXxfhfj3oCqkSs2nC27mHxBmQtmZKWmXk5HzVUyPRwTUWx5wHPT_hCsGer-CMCAyGsmOg466y1KDqf7ogpMYojfVZGWBsyA39LO1oWZ4Ryomkn8t5Vg"; Algorithm algorithm = Algorithm.RSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -69,18 +77,22 @@ public void shouldFailRSA256VerificationWhenProvidedPublicKeyIsNull() throws Exc exception.expectCause(hasMessage(is("The given Public Key is null."))); RSAKeyProvider provider = mock(RSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.jXrbue3xJmnzWH9kU-uGeCTtgbQEKbch8uHd4Z52t86ncNyepfusl_bsyLJIcxMwK7odRzKiSE9efV9JaRSEDODDBdMeCzODFx82uBM7e46T1NLVSmjYIM7Hcfh81ZeTIk-hITvgtL6hvTdeJWOCZAB0bs18qSVW5SvursRUhY38xnhuNI6HOHCtqp7etxWAu6670L53I3GtXsmi6bXIzv_0v1xZcAFg4HTvXxfhfj3oCqkSs2nC27mHxBmQtmZKWmXk5HzVUyPRwTUWx5wHPT_hCsGer-CMCAyGsmOg466y1KDqf7ogpMYojfVZGWBsyA39LO1oWZ4Ryomkn8t5Vg"; + String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.jXrbue3xJmnzWH9kU-uGeCTtgbQEKbch8uHd4Z52t86ncNyepfusl_bsyLJIcxMwK7odRzKiSE9efV9JaRSEDODDBdMeCzODFx82uBM7e46T1NLVSmjYIM7Hcfh81ZeTIk-hITvgtL6hvTdeJWOCZAB0bs18qSVW5SvursRUhY38xnhuNI6HOHCtqp7etxWAu6670L53I3GtXsmi6bXIzv_0v1xZcAFg4HTvXxfhfj3oCqkSs2nC27mHxBmQtmZKWmXk5HzVUyPRwTUWx5wHPT_hCsGer-CMCAyGsmOg466y1KDqf7ogpMYojfVZGWBsyA39LO1oWZ4Ryomkn8t5Vg"; Algorithm algorithm = Algorithm.RSA256(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailRSA256VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withRSA"); - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; Algorithm algorithm = Algorithm.RSA256((RSAKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -89,23 +101,29 @@ public void shouldFailRSA256VerificationWhenUsingPrivateKey() throws Exception { exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA256withRSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; Algorithm algorithm = Algorithm.RSA256((RSAKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassRSA384Verification() throws Exception { - String jwt = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; + String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; Algorithm algorithm = Algorithm.RSA384((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassRSA384VerificationWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; + String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; Algorithm algorithm = Algorithm.RSA384((RSAPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"), (RSAPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -113,9 +131,11 @@ public void shouldPassRSA384VerificationWithProvidedPublicKey() throws Exception RSAKeyProvider provider = mock(RSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"); when(provider.getPublicKeyById("my-key-id")).thenReturn((RSAPublicKey) publicKey); - String jwt = "eyJhbGciOiJSUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.ITNTVCT7ercumZKHV4-BXGkJwwa7fyF3CnSfEvm09fDFSkaseDxNo_75WLDmK9WM8RMHTPvkpHcTKm4guYEbC_la7RzFIKpU72bppzQojggSmWWXt_6zq50QP2t5HFMebote1zxhp8ccEdSCX5pyY6J2sm9kJ__HKK32KxIVCTjVCz-bFBS60oG35aYEySdKsxuUdWbD5FQ9I16Ony2x0EPvmlL3GPiAPmgjSFp3LtcBIbCDaoonM7iuDRGIQiDN_n2FKKb1Bt4_38uWPtTkwRpNalt6l53Y3JDdzGI5fMrMo3RQnQlAJxUJKD0eL6dRAA645IVIIXucHwuhgGGIVw"; + String token = "eyJhbGciOiJSUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.ITNTVCT7ercumZKHV4-BXGkJwwa7fyF3CnSfEvm09fDFSkaseDxNo_75WLDmK9WM8RMHTPvkpHcTKm4guYEbC_la7RzFIKpU72bppzQojggSmWWXt_6zq50QP2t5HFMebote1zxhp8ccEdSCX5pyY6J2sm9kJ__HKK32KxIVCTjVCz-bFBS60oG35aYEySdKsxuUdWbD5FQ9I16Ony2x0EPvmlL3GPiAPmgjSFp3LtcBIbCDaoonM7iuDRGIQiDN_n2FKKb1Bt4_38uWPtTkwRpNalt6l53Y3JDdzGI5fMrMo3RQnQlAJxUJKD0eL6dRAA645IVIIXucHwuhgGGIVw"; Algorithm algorithm = Algorithm.RSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -126,18 +146,22 @@ public void shouldFailRSA384VerificationWhenProvidedPublicKeyIsNull() throws Exc exception.expectCause(hasMessage(is("The given Public Key is null."))); RSAKeyProvider provider = mock(RSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJSUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.ITNTVCT7ercumZKHV4-BXGkJwwa7fyF3CnSfEvm09fDFSkaseDxNo_75WLDmK9WM8RMHTPvkpHcTKm4guYEbC_la7RzFIKpU72bppzQojggSmWWXt_6zq50QP2t5HFMebote1zxhp8ccEdSCX5pyY6J2sm9kJ__HKK32KxIVCTjVCz-bFBS60oG35aYEySdKsxuUdWbD5FQ9I16Ony2x0EPvmlL3GPiAPmgjSFp3LtcBIbCDaoonM7iuDRGIQiDN_n2FKKb1Bt4_38uWPtTkwRpNalt6l53Y3JDdzGI5fMrMo3RQnQlAJxUJKD0eL6dRAA645IVIIXucHwuhgGGIVw"; + String token = "eyJhbGciOiJSUzM4NCIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.ITNTVCT7ercumZKHV4-BXGkJwwa7fyF3CnSfEvm09fDFSkaseDxNo_75WLDmK9WM8RMHTPvkpHcTKm4guYEbC_la7RzFIKpU72bppzQojggSmWWXt_6zq50QP2t5HFMebote1zxhp8ccEdSCX5pyY6J2sm9kJ__HKK32KxIVCTjVCz-bFBS60oG35aYEySdKsxuUdWbD5FQ9I16Ony2x0EPvmlL3GPiAPmgjSFp3LtcBIbCDaoonM7iuDRGIQiDN_n2FKKb1Bt4_38uWPtTkwRpNalt6l53Y3JDdzGI5fMrMo3RQnQlAJxUJKD0eL6dRAA645IVIIXucHwuhgGGIVw"; Algorithm algorithm = Algorithm.RSA384(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailRSA384VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withRSA"); - String jwt = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; + String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; Algorithm algorithm = Algorithm.RSA384((RSAKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -146,23 +170,29 @@ public void shouldFailRSA384VerificationWhenUsingPrivateKey() throws Exception { exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA384withRSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; + String token = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.TZlWjXObwGSQOiu2oMq8kiKz0_BR7bbBddNL6G8eZ_GoR82BXOZDqNrQr7lb_M-78XGBguWLWNIdYhzgxOUL9EoCJlrqVm9s9vo6G8T1sj1op-4TbjXZ61TwIvrJee9BvPLdKUJ9_fp1Js5kl6yXkst40Th8Auc5as4n49MLkipjpEhKDKaENKHpSubs1ripSz8SCQZSofeTM_EWVwSw7cpiM8Fy8jOPvWG8Xz4-e3ODFowvHVsDcONX_4FTMNbeRqDuHq2ZhCJnEfzcSJdrve_5VD5fM1LperBVslTrOxIgClOJ3RmM7-WnaizJrWP3D6Z9OLxPxLhM6-jx6tcxEw"; Algorithm algorithm = Algorithm.RSA384((RSAKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassRSA512Verification() throws Exception { - String jwt = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; + String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; Algorithm algorithm = Algorithm.RSA512((RSAKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldPassRSA512VerificationWithBothKeys() throws Exception { - String jwt = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; + String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; Algorithm algorithm = Algorithm.RSA512((RSAPublicKey) readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"), (RSAPrivateKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -170,9 +200,11 @@ public void shouldPassRSA512VerificationWithProvidedPublicKey() throws Exception RSAKeyProvider provider = mock(RSAKeyProvider.class); PublicKey publicKey = readPublicKeyFromFile(PUBLIC_KEY_FILE, "RSA"); when(provider.getPublicKeyById("my-key-id")).thenReturn((RSAPublicKey) publicKey); - String jwt = "eyJhbGciOiJSUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.GpHv85Q8tAU_6hNWsmO0GEpO1qz9lmK3NKeAcemysz9MGo4FXWn8xbD8NjCfzZ8EWphm65M0NArKSjpKHO5-gcNsQxLBVfSED1vzcoaZH_Vy5Rp1M76dGH7JghB_66KrpfyMxer_yRJb-KXesNvIroDGilLQF2ENG-IfLF5nBKlDiVHmPaqr3pm1q20fNLhegkSRca4BJ5VdIlT6kOqE_ykVyCBqzD_oXp3LKO_ARnxoeB9SegIW1fy_3tuxSTKYsCZiOfiyVEXXblAuY3pSLZnGvgeBRnfvmWXDWhP0vVUFtYJBF09eULvvUMVqWcrjUG9gDzzzT7veiY_fHd_x8g"; + String token = "eyJhbGciOiJSUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.GpHv85Q8tAU_6hNWsmO0GEpO1qz9lmK3NKeAcemysz9MGo4FXWn8xbD8NjCfzZ8EWphm65M0NArKSjpKHO5-gcNsQxLBVfSED1vzcoaZH_Vy5Rp1M76dGH7JghB_66KrpfyMxer_yRJb-KXesNvIroDGilLQF2ENG-IfLF5nBKlDiVHmPaqr3pm1q20fNLhegkSRca4BJ5VdIlT6kOqE_ykVyCBqzD_oXp3LKO_ARnxoeB9SegIW1fy_3tuxSTKYsCZiOfiyVEXXblAuY3pSLZnGvgeBRnfvmWXDWhP0vVUFtYJBF09eULvvUMVqWcrjUG9gDzzzT7veiY_fHd_x8g"; Algorithm algorithm = Algorithm.RSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -183,18 +215,22 @@ public void shouldFailRSA512VerificationWhenProvidedPublicKeyIsNull() throws Exc exception.expectCause(hasMessage(is("The given Public Key is null."))); RSAKeyProvider provider = mock(RSAKeyProvider.class); when(provider.getPublicKeyById("my-key-id")).thenReturn(null); - String jwt = "eyJhbGciOiJSUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.GpHv85Q8tAU_6hNWsmO0GEpO1qz9lmK3NKeAcemysz9MGo4FXWn8xbD8NjCfzZ8EWphm65M0NArKSjpKHO5-gcNsQxLBVfSED1vzcoaZH_Vy5Rp1M76dGH7JghB_66KrpfyMxer_yRJb-KXesNvIroDGilLQF2ENG-IfLF5nBKlDiVHmPaqr3pm1q20fNLhegkSRca4BJ5VdIlT6kOqE_ykVyCBqzD_oXp3LKO_ARnxoeB9SegIW1fy_3tuxSTKYsCZiOfiyVEXXblAuY3pSLZnGvgeBRnfvmWXDWhP0vVUFtYJBF09eULvvUMVqWcrjUG9gDzzzT7veiY_fHd_x8g"; + String token = "eyJhbGciOiJSUzUxMiIsImtpZCI6Im15LWtleS1pZCJ9.eyJpc3MiOiJhdXRoMCJ9.GpHv85Q8tAU_6hNWsmO0GEpO1qz9lmK3NKeAcemysz9MGo4FXWn8xbD8NjCfzZ8EWphm65M0NArKSjpKHO5-gcNsQxLBVfSED1vzcoaZH_Vy5Rp1M76dGH7JghB_66KrpfyMxer_yRJb-KXesNvIroDGilLQF2ENG-IfLF5nBKlDiVHmPaqr3pm1q20fNLhegkSRca4BJ5VdIlT6kOqE_ykVyCBqzD_oXp3LKO_ARnxoeB9SegIW1fy_3tuxSTKYsCZiOfiyVEXXblAuY3pSLZnGvgeBRnfvmWXDWhP0vVUFtYJBF09eULvvUMVqWcrjUG9gDzzzT7veiY_fHd_x8g"; Algorithm algorithm = Algorithm.RSA512(provider); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldFailRSA512VerificationWithInvalidPublicKey() throws Exception { exception.expect(SignatureVerificationException.class); exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withRSA"); - String jwt = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; + String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; Algorithm algorithm = Algorithm.RSA512((RSAKey) readPublicKeyFromFile(INVALID_PUBLIC_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -203,16 +239,17 @@ public void shouldFailRSA512VerificationWhenUsingPrivateKey() throws Exception { exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: SHA512withRSA"); exception.expectCause(isA(IllegalStateException.class)); exception.expectCause(hasMessage(is("The given Public Key is null."))); - String jwt = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; + String token = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mvL5LoMyIrWYjk5umEXZTmbyIrkbbcVPUkvdGZbu0qFBxGOf0nXP5PZBvPcOu084lvpwVox5n3VaD4iqzW-PsJyvKFgi5TnwmsbKchAp7JexQEsQOnTSGcfRqeUUiBZqRQdYsho71oAB3T4FnalDdFEpM-fztcZY9XqKyayqZLreTeBjqJm4jfOWH7KfGBHgZExQhe96NLq1UA9eUyQwdOA1Z0SgXe4Ja5PxZ6Fm37KnVDtDlNnY4JAAGFo6y74aGNnp_BKgpaVJCGFu1f1S5xCQ1HSvs8ZSdVWs5NgawW3wRd0kRt_GJ_Y3mIwiF4qUyHWGtsSHu_qjVdCTtbFyow"; Algorithm algorithm = Algorithm.RSA512((RSAKey) readPrivateKeyFromFile(PRIVATE_KEY_FILE, "RSA")); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowWhenMacAlgorithmDoesNotExists() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(NoSuchAlgorithmException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -222,15 +259,16 @@ public void shouldThrowWhenMacAlgorithmDoesNotExists() throws Exception { RSAPrivateKey privateKey = mock(RSAPrivateKey.class); RSAKeyProvider provider = RSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new RSAAlgorithm(crypto, "some-alg", "some-algorithm", provider); - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowWhenThePublicKeyIsInvalid() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(InvalidKeyException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -240,15 +278,16 @@ public void shouldThrowWhenThePublicKeyIsInvalid() throws Exception { RSAPrivateKey privateKey = mock(RSAPrivateKey.class); RSAKeyProvider provider = RSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new RSAAlgorithm(crypto, "some-alg", "some-algorithm", provider); - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test public void shouldThrowWhenTheSignatureIsNotPrepared() throws Exception { - exception.expect(SignatureVerificationException.class); - exception.expectMessage("The Token's Signature resulted invalid when verified using the Algorithm: some-alg"); - exception.expectCause(isA(SignatureException.class)); + exception.expect(AlgorithmMismatchException.class); + exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); CryptoHelper crypto = mock(CryptoHelper.class); when(crypto.verifySignatureFor(anyString(), any(PublicKey.class), any(byte[].class), any(byte[].class))) @@ -258,8 +297,10 @@ public void shouldThrowWhenTheSignatureIsNotPrepared() throws Exception { RSAPrivateKey privateKey = mock(RSAPrivateKey.class); RSAKeyProvider provider = RSAAlgorithm.providerForKeys(publicKey, privateKey); Algorithm algorithm = new RSAAlgorithm(crypto, "some-alg", "some-algorithm", provider); - String jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; - algorithm.verify(JWT.decode(jwt)); + String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.dxXF3MdsyW-AuvwJpaQtrZ33fAde9xWxpLIg9cO2tMLH2GSRNuLAe61KsJusZhqZB9Iy7DvflcmRz-9OZndm6cj_ThGeJH2LLc90K83UEvvRPo8l85RrQb8PcanxCgIs2RcZOLygERizB3pr5icGkzR7R2y6zgNCjKJ5_NJ6EiZsGN6_nc2PRK_DbyY-Wn0QDxIxKoA5YgQJ9qafe7IN980pXvQv2Z62c3XR8dYuaXBqhthBj-AbaFHEpZapN-V-TmuLNzR2MCB6Xr7BYMuCaqWf_XU8og4XNe8f_8w9Wv5vvgqMM1KhqVpG5VdMJv4o_L4NoCROHhtUQSLRh2M9cA"; + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @@ -278,12 +319,14 @@ public void shouldDoRSA256Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "ZB-Tr0vLtnf8I9fhSdSjU6HZei5xLYZQ6nZqM5O6Va0W9PgAqgRT7ShI9CjeYulRXPHvVmSl5EQuYuXdBzM0-H_3p_Nsl6tSMy4EyX2kkhEm6T0HhvarTh8CG0PCjn5p6FP5ZxWwhLcmRN70ItP6Z5MMO4CcJh1JrNxR4Fi4xQgt-CK2aVDMFXd-Br5yQiLVx1CX83w28OD9wssW3Rdltl5e66vCef0Ql6Q5I5e5F0nqGYT989a9fkNgLIx2F8k_az5x07BY59FV2SZg59nSiY7TZNjP8ot11Ew7HKRfPXOdh9eKRUVdhcxzqDePhyzKabU8TG5FP0SiWH5qVPfAgw"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -294,12 +337,14 @@ public void shouldDoRSA256SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "ZB-Tr0vLtnf8I9fhSdSjU6HZei5xLYZQ6nZqM5O6Va0W9PgAqgRT7ShI9CjeYulRXPHvVmSl5EQuYuXdBzM0-H_3p_Nsl6tSMy4EyX2kkhEm6T0HhvarTh8CG0PCjn5p6FP5ZxWwhLcmRN70ItP6Z5MMO4CcJh1JrNxR4Fi4xQgt-CK2aVDMFXd-Br5yQiLVx1CX83w28OD9wssW3Rdltl5e66vCef0Ql6Q5I5e5F0nqGYT989a9fkNgLIx2F8k_az5x07BY59FV2SZg59nSiY7TZNjP8ot11Ew7HKRfPXOdh9eKRUVdhcxzqDePhyzKabU8TG5FP0SiWH5qVPfAgw"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -314,10 +359,12 @@ public void shouldDoRSA256SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -353,12 +400,14 @@ public void shouldDoRSA384Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "Jx1PaTBnjd_U56MNjifFcY7w9ImDbseg0y8Ijr2pSiA1_wzQb_wy9undaWfzR5YqdIAXvjS8AGuZUAzIoTG4KMgOgdVyYDz3l2jzj6wI-lgqfR5hTy1w1ruMUQ4_wobpdxAiJ4fEbg8Mi_GljOiCO-P1HilxKnpiOJZidR8MQGwTInsf71tOUkK4x5UsdmUueuZbaU-CL5kPnRfXmJj9CcdxZbD9oMlbo23dwkP5BNMrS2LwGGzc9C_-ypxrBIOVilG3WZxcSmuG86LjcZbnL6LBEfph5NmKBgQav147uipb_7umBEr1m2dYiB_9u606n3bcoo3rnsYYK_Xfi1GAEQ"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -369,12 +418,14 @@ public void shouldDoRSA384SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "Jx1PaTBnjd_U56MNjifFcY7w9ImDbseg0y8Ijr2pSiA1_wzQb_wy9undaWfzR5YqdIAXvjS8AGuZUAzIoTG4KMgOgdVyYDz3l2jzj6wI-lgqfR5hTy1w1ruMUQ4_wobpdxAiJ4fEbg8Mi_GljOiCO-P1HilxKnpiOJZidR8MQGwTInsf71tOUkK4x5UsdmUueuZbaU-CL5kPnRfXmJj9CcdxZbD9oMlbo23dwkP5BNMrS2LwGGzc9C_-ypxrBIOVilG3WZxcSmuG86LjcZbnL6LBEfph5NmKBgQav147uipb_7umBEr1m2dYiB_9u606n3bcoo3rnsYYK_Xfi1GAEQ"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -389,10 +440,12 @@ public void shouldDoRSA384SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -428,12 +481,14 @@ public void shouldDoRSA512Signing() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithmSign.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "THIPVYzNZ1Yo_dm0k1UELqV0txs3SzyMopCyHcLXOOdgYXF4MlGvBqu0CFvgSga72Sp5LpuC1Oesj40v_QDsp2GTGDeWnvvcv_eo-b0LPSpmT2h1Ibrmu-z70u2rKf28pkN-AJiMFqi8sit2kMIp1bwIVOovPvMTQKGFmova4Xwb3G526y_PeLlflW1h69hQTIVcI67ACEkAC-byjDnnYIklA-B4GWcggEoFwQRTdRjAUpifA6HOlvnBbZZlUd6KXwEydxVS-eh1odwPjB2_sfbyy5HnLsvNdaniiZQwX7QbwLNT4F72LctYdHHM1QCrID6bgfgYp9Ij9CRX__XDEA"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithmVerify.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithmVerify).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithmVerify.verify(decoded); } @Test @@ -444,12 +499,14 @@ public void shouldDoRSA512SigningWithBothKeys() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); String expectedSignature = "THIPVYzNZ1Yo_dm0k1UELqV0txs3SzyMopCyHcLXOOdgYXF4MlGvBqu0CFvgSga72Sp5LpuC1Oesj40v_QDsp2GTGDeWnvvcv_eo-b0LPSpmT2h1Ibrmu-z70u2rKf28pkN-AJiMFqi8sit2kMIp1bwIVOovPvMTQKGFmova4Xwb3G526y_PeLlflW1h69hQTIVcI67ACEkAC-byjDnnYIklA-B4GWcggEoFwQRTdRjAUpifA6HOlvnBbZZlUd6KXwEydxVS-eh1odwPjB2_sfbyy5HnLsvNdaniiZQwX7QbwLNT4F72LctYdHHM1QCrID6bgfgYp9Ij9CRX__XDEA"; assertThat(signatureBytes, is(notNullValue())); assertThat(jwtSignature, is(expectedSignature)); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test @@ -464,10 +521,12 @@ public void shouldDoRSA512SigningWithProvidedPrivateKey() throws Exception { byte[] contentBytes = jwtContent.getBytes(StandardCharsets.UTF_8); byte[] signatureBytes = algorithm.sign(contentBytes); String jwtSignature = Base64.encodeBase64URLSafeString(signatureBytes); - String jwt = String.format("%s.%s", jwtContent, jwtSignature); + String token = String.format("%s.%s", jwtContent, jwtSignature); assertThat(signatureBytes, is(notNullValue())); - algorithm.verify(JWT.decode(jwt)); + JWT jwt = JWT.require(algorithm).withIssuer("auth0").build(); + DecodedJWT decoded = jwt.decode(token); + algorithm.verify(decoded); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java new file mode 100644 index 00000000..d5bb32ce --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java @@ -0,0 +1,298 @@ +package com.auth0.jwt.creators; + +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.jwts.JWT; +import com.auth0.jwt.jwts.AccessJWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.text.SimpleDateFormat; +import java.util.*; + +public class AccessJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date exp = generateRandomExpDateInFuture(); + private static final Date iat = generateRandomIatDateInPast(); + + + @Test + public void testAccessJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorInvalidIssuer() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'iss' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("invalid") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testAccessJwtCreatorInvalidAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("invalid") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testAccessJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testAccessJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testAccessJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .setIsNoneAlgorithmAllowed(true) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorArrayClaim() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withArrayClaim("arrayKey", "arrayValue1", "arrayValue2") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimStringValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimIntegerValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 999) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimDoubleValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 9.99) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimLongValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 999L) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimBooleanValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", true) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorNonStandardClaimDateValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", new Date()) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testAccessJwtCreatorExpTimeHasPassed() throws Exception { + thrown.expect(TokenExpiredException.class); + thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + + String myDate = "2014/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date expDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = AccessJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", new Date()) + .withExp(expDate) + .withIat(iat) + .sign(algorithm); + Verification verification = AccessJWT.require(algorithm); + JWT verifier = verification.createVerifierForAccess(asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + private static void verifyClaims(Map claims, Date exp) { + assertTrue(claims.get(PublicClaims.ISSUER).asList(String.class).get(0).equals("accounts.fake.com")); + assertTrue(claims.get(PublicClaims.SUBJECT).asList(String.class).get(0).equals("subject")); + assertTrue(claims.get(PublicClaims.AUDIENCE).asString().equals("audience")); + assertTrue(claims.get(PublicClaims.EXPIRES_AT).asDate().toString().equals(exp.toString())); + } +} \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java new file mode 100644 index 00000000..1b8a3918 --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java @@ -0,0 +1,407 @@ +package com.auth0.jwt.creators; + +import static com.auth0.jwt.creators.GoogleJwtCreatorTest.*; +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.GoogleVerification; +import com.auth0.jwt.jwts.ExtendedJWT; +import com.auth0.jwt.jwts.JWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +public class ExtendedJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date exp = generateRandomExpDateInFuture(); + private static final Date iat = generateRandomIatDateInPast(); + private static final Date nbf = iat; + + @Test + public void testExtendedJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testExtendedJwtCreatorInvalidIssuer() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'iss' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("invalid") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorInvalidPicture() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'picture' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture("invalid") + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorInvalidEmail() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'email' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture(PICTURE) + .withEmail("invalid") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testExtendedJwtCreatorInvalidAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("invalid") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testExtendedJwtCreatorInvalidName() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'name' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) //this must be called first since ExtendedJwtCreator.build() returns an instance of ExtendedJwtCreator + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName("invalid") + .sign(algorithm); + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testExtendedJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .setIsNoneAlgorithmAllowed(true) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimStringValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimIntegerValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 999) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimLongValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 999L) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimDoubleValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 9.99) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimBooleanValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", true) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorNonStandardClaimDateValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testExtendedJwtCreatorExpTimeHasPassed() throws Exception { + thrown.expect(TokenExpiredException.class); + thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + + String myDate = "2014/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date expDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ExtendedJwtCreator.build() + .withNbf(nbf) + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(expDate) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + + GoogleVerification verification = ExtendedJWT.require(algorithm); + JWT verifier = verification.createVerifierForExtended(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } +} diff --git a/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java new file mode 100644 index 00000000..e61ac1aa --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java @@ -0,0 +1,305 @@ +package com.auth0.jwt.creators; + +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.FbJwtCreator; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.jwts.FbJWT; +import com.auth0.jwt.jwts.JWT; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.text.SimpleDateFormat; +import java.util.*; + +public class FbJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date exp = generateRandomExpDateInFuture(); + private static final Date iat = generateRandomIatDateInPast(); + private static final String USER_ID = "userId"; + private static final String APP_ID = "appId"; + + @Test + public void testFbJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorInvalidUserId() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'userId' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId("invalid") + .withAppId(APP_ID) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testFbJwtCreatorInvalidAppId() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'appId' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId("invalid") + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testFbJwtCreatorUserIdNotProvided() throws Exception { + thrown.expect(Exception.class); + thrown.expectMessage("Standard claim: UserId has not been set"); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withAppId(APP_ID) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testFbJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testFbJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testFbJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorArrayClaim() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withArrayClaim("arrayKey", "arrayValue1", "arrayValue2") + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimStringValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimIntegerValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", 999) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimLongValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", 999L) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimDoubleValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", 9.99) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimBooleanValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", true) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testFbJwtCreatorNonStandardClaimDateValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(exp) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + @Test + public void testFbJwtCreatorExpTimeHasPassed() throws Exception { + thrown.expect(TokenExpiredException.class); + thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + + String myDate = "2014/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date expDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = FbJwtCreator.build() + .withExp(expDate) + .withIat(iat) + .withUserId(USER_ID) + .withAppId(APP_ID) + .setIsNoneAlgorithmAllowed(true) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + Verification verification = FbJWT.require(algorithm); + JWT verifier = verification.createVerifierForFb(USER_ID, APP_ID).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + + private static void verifyClaims(Map claims) { + assertTrue(claims.get(USER_ID).asString().equals(USER_ID)); + assertTrue(claims.get(APP_ID).asString().equals(APP_ID)); + assertTrue(claims.get(PublicClaims.EXPIRES_AT).asDate().toString().equals(exp.toString())); + } +} \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java new file mode 100644 index 00000000..8021f9b2 --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java @@ -0,0 +1,494 @@ +package com.auth0.jwt.creators; + +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.GoogleJwtCreator; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.GoogleVerification; +import com.auth0.jwt.jwts.GoogleJWT; +import com.auth0.jwt.jwts.JWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + + +import java.text.SimpleDateFormat; +import java.util.*; + +public class GoogleJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date exp = generateRandomExpDateInFuture(); + private static final Date iat = generateRandomIatDateInPast(); + public static final String PICTURE = "picture"; + public static final String EMAIL = "email"; + public static final String NAME = "name"; + + + @Test + public void testGoogleJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorWhenCertainRequiredClaimIsntProvided() throws Exception { + thrown.expect(Exception.class); + thrown.expectMessage("Standard claim: Picture has not been set"); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .setIsNoneAlgorithmAllowed(true) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorArrayClaim() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .setIsNoneAlgorithmAllowed(true) + .withArrayClaim("arrayKey", "arrayValue1", "arrayValue2") + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorInvalidIssuer() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'iss' value doesn't match the required one."); + + Algorithm algorithm = Algorithm.none(); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("invalid") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .setIsNoneAlgorithmAllowed(true) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorInvalidAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("invalid") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorInvalidPicture() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'picture' value doesn't match the required one."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture("invalid") + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorInvalidEmail() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'email' value doesn't match the required one."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail("invalid") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorInvalidName() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'name' value doesn't match the required one."); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName("invalid") + .sign(algorithm); + + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimString() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimBoolean() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", true) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimInteger() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 999) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimLong() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 999L) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimDouble() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", 9.99) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorNonStandardClaimDate() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .withName(NAME) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testGoogleJwtCreatorExpTimeHasPassed() throws Exception { + thrown.expect(TokenExpiredException.class); + thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + + String myDate = "2014/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date expDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(expDate) + .withIat(iat) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testGoogleJwtCreatorTokenCantBeUsedBefore() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Token can't be used before Mon Oct 29 00:00:00 PDT 2018."); + + String myDate = "2018/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date iatDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = GoogleJwtCreator.build() + .withPicture(PICTURE) + .withEmail(EMAIL) + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iatDate) + .withName(NAME) + .sign(algorithm); + GoogleVerification verification = GoogleJWT.require(algorithm); + JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("accounts.fake.com"), asList("audience"), + NAME, 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testCreateVerifierForExtended() throws Exception{ + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("you shouldn't be calling this method"); + GoogleVerification verification = GoogleJWT.require(Algorithm.HMAC256("secret")); + verification.createVerifierForExtended(null, null, null, null, null, 1L, 1L, 1L); + } + + protected static void verifyClaims(Map claims, Date exp) { + assertTrue(claims.get(PICTURE).asString().equals(PICTURE)); + assertTrue(claims.get(EMAIL).asString().equals(EMAIL)); + assertTrue(claims.get(PublicClaims.ISSUER).asList(String.class).get(0).equals("accounts.fake.com")); + assertTrue(claims.get(PublicClaims.SUBJECT).asList(String.class).get(0).equals("subject")); + assertTrue(claims.get(PublicClaims.AUDIENCE).asString().equals("audience")); + assertTrue(claims.get(PublicClaims.EXPIRES_AT).asDate().toString().equals(exp.toString())); + assertTrue(claims.get(NAME).asString().equals(NAME)); + } +} \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/creators/ImplicitJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/ImplicitJwtCreatorTest.java new file mode 100644 index 00000000..58c6e8d7 --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/ImplicitJwtCreatorTest.java @@ -0,0 +1,275 @@ +package com.auth0.jwt.creators; + +import com.auth0.jwt.TimeUtil; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.ImplicitJwtCreator; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.jwts.ImplicitJWT; +import com.auth0.jwt.jwts.JWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.*; + +public class ImplicitJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date iat = generateRandomIatDateInPast(); + + + @Test + public void testImplicitJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorInvalidIssuer() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'iss' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("invalid") + .withSubject("subject") + .withAudience("audience") + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorInvalidAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("invalid") + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorIssuerNotProvided() throws Exception { + thrown.expect(Exception.class); + thrown.expectMessage("Standard claim: Issuer has not been set"); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withSubject("subject") + .withAudience("audience") + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .setIsNoneAlgorithmAllowed(false) + .withIat(iat) + .sign(algorithm); + + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testImplicitJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testImplicitJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .setIsNoneAlgorithmAllowed(true) + .withIat(iat) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorArrayClaim() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withArrayClaim("arrayKey", "arrayValue1", "arrayValue2") + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimStringValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimIntegerValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", 999) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimLongValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", 999L) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimDoubleValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", 9.99) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimBooleanValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", true) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + @Test + public void testImplicitJwtCreatorNonStandardClaimDateValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .withNonStandardClaim("nonStandardClaim", new Date()) + .sign(algorithm); + Verification verification = ImplicitJWT.require(algorithm); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims); + } + + private static void verifyClaims(Map claims) { + assertTrue(claims.get(PublicClaims.ISSUER).asList(String.class).get(0).equals("accounts.fake.com")); + assertTrue(claims.get(PublicClaims.SUBJECT).asList(String.class).get(0).equals("subject")); + assertTrue(claims.get(PublicClaims.AUDIENCE).asString().equals("audience")); + } +} \ No newline at end of file diff --git a/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/JWTCreatorTest.java similarity index 95% rename from lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java rename to lib/src/test/java/com/auth0/jwt/creators/JWTCreatorTest.java index ab263bad..140e6aea 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/JWTCreatorTest.java @@ -1,6 +1,10 @@ -package com.auth0.jwt; +package com.auth0.jwt.creators; +import com.auth0.jwt.JsonMatcher; +import com.auth0.jwt.PemUtils; +import com.auth0.jwt.TokenUtils; import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.JWTCreator; import com.auth0.jwt.interfaces.ECDSAKeyProvider; import com.auth0.jwt.interfaces.RSAKeyProvider; import org.apache.commons.codec.binary.Base64; @@ -138,7 +142,7 @@ public void shouldAddIssuer() throws Exception { .sign(Algorithm.HMAC256("secret")); assertThat(signed, is(notNullValue())); - assertThat(TokenUtils.splitToken(signed)[1], is("eyJpc3MiOiJhdXRoMCJ9")); + assertThat(TokenUtils.splitToken(signed)[1], is("eyJpc3MiOlsiYXV0aDAiXX0")); } @Test @@ -148,7 +152,7 @@ public void shouldAddSubject() throws Exception { .sign(Algorithm.HMAC256("secret")); assertThat(signed, is(notNullValue())); - assertThat(TokenUtils.splitToken(signed)[1], is("eyJzdWIiOiIxMjM0NTY3ODkwIn0")); + assertThat(TokenUtils.splitToken(signed)[1], is("eyJzdWIiOlsiMTIzNDU2Nzg5MCJdfQ")); } @Test @@ -255,13 +259,13 @@ public void shouldThrowOnNullCustomClaimName() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("The Custom Claim's name can't be null."); JWTCreator.init() - .withClaim(null, "value"); + .withNonStandardClaim(null, "value"); } @Test public void shouldAcceptCustomClaimOfTypeString() throws Exception { String jwt = JWTCreator.init() - .withClaim("name", "value") + .withNonStandardClaim("name", "value") .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); @@ -272,7 +276,7 @@ public void shouldAcceptCustomClaimOfTypeString() throws Exception { @Test public void shouldAcceptCustomClaimOfTypeInteger() throws Exception { String jwt = JWTCreator.init() - .withClaim("name", 123) + .withNonStandardClaim("name", 123) .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); @@ -283,7 +287,7 @@ public void shouldAcceptCustomClaimOfTypeInteger() throws Exception { @Test public void shouldAcceptCustomClaimOfTypeLong() throws Exception { String jwt = JWTCreator.init() - .withClaim("name", Long.MAX_VALUE) + .withNonStandardClaim("name", Long.MAX_VALUE) .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); @@ -294,7 +298,7 @@ public void shouldAcceptCustomClaimOfTypeLong() throws Exception { @Test public void shouldAcceptCustomClaimOfTypeDouble() throws Exception { String jwt = JWTCreator.init() - .withClaim("name", 23.45) + .withNonStandardClaim("name", 23.45) .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); @@ -305,7 +309,7 @@ public void shouldAcceptCustomClaimOfTypeDouble() throws Exception { @Test public void shouldAcceptCustomClaimOfTypeBoolean() throws Exception { String jwt = JWTCreator.init() - .withClaim("name", true) + .withNonStandardClaim("name", true) .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); @@ -317,7 +321,7 @@ public void shouldAcceptCustomClaimOfTypeBoolean() throws Exception { public void shouldAcceptCustomClaimOfTypeDate() throws Exception { Date date = new Date(1478891521000L); String jwt = JWTCreator.init() - .withClaim("name", date) + .withNonStandardClaim("name", date) .sign(Algorithm.HMAC256("secret")); assertThat(jwt, is(notNullValue())); diff --git a/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java new file mode 100644 index 00000000..e6124d7b --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java @@ -0,0 +1,350 @@ +package com.auth0.jwt.creators; + +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.ScopedJwtCreator; +import com.auth0.jwt.exceptions.InvalidClaimException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.impl.PublicClaims; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.jwts.JWT; +import com.auth0.jwt.jwts.ScopedJWT; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.text.SimpleDateFormat; +import java.util.*; + +public class ScopedJwtCreatorTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Date exp = generateRandomExpDateInFuture(); + private static final Date iat = generateRandomIatDateInPast(); + + + @Test + public void testScopedJwtCreatorAllStandardClaimsMustBeRequired() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorInvalidScope() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'scope' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("invalid") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testScopedJwtCreatorInvalidIssuer() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'iss' value doesn't match the required one."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("invalid") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testScopedJwtCreatorInvalidAudience() throws Exception { + thrown.expect(InvalidClaimException.class); + thrown.expectMessage("The Claim 'aud' value doesn't contain the required audience."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("invalid") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testScopedJwtCreatorScopeNotProvided() throws Exception { + thrown.expect(Exception.class); + thrown.expectMessage("Standard claim: Scope has not been set"); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNoneAlgorithmNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .setIsNoneAlgorithmAllowed(false) + .sign(algorithm); + + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testScopedJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() throws Exception { + thrown.expect(IllegalAccessException.class); + thrown.expectMessage("None algorithm isn't allowed"); + + Algorithm algorithm = Algorithm.none(); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + + @Test + public void testScopedJwtCreatorNoneAlgorithmAllowed() throws Exception { + Algorithm algorithm = Algorithm.none(); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .setIsNoneAlgorithmAllowed(true) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorArrayClaim() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withArrayClaim("arrayKey", "arrayValue1", "arrayValue2") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimStringValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", "nonStandardClaimValue") + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimIntegerValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 999) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimDoubleValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 9.99) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimLongValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", 999L) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimBooleanValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", true) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorNonStandardClaimDateValue() throws Exception { + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", new Date()) + .withExp(exp) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, exp); + } + + @Test + public void testScopedJwtCreatorExpTimeHasPassed() throws Exception { + thrown.expect(TokenExpiredException.class); + thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + + String myDate = "2014/10/29"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); + Date date = sdf.parse(myDate); + long expLong = date.getTime(); + Date expDate = new Date(expLong); + + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ScopedJwtCreator.build() + .withScope("scope") + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withNonStandardClaim("nonStandardClaim", new Date()) + .withExp(expDate) + .withIat(iat) + .sign(algorithm); + Verification verification = ScopedJWT.require(algorithm); + JWT verifier = verification.createVerifierForScoped("scope", asList("accounts.fake.com"), asList("audience"), 1, 1).build(); + DecodedJWT jwt = verifier.decode(token); + Map claims = jwt.getClaims(); + verifyClaims(claims, expDate); + } + + private static void verifyClaims(Map claims, Date exp) { + assertTrue(claims.get(PublicClaims.ISSUER).asList(String.class).get(0).equals("accounts.fake.com")); + assertTrue(claims.get(PublicClaims.SUBJECT).asList(String.class).get(0).equals("subject")); + assertTrue(claims.get(PublicClaims.AUDIENCE).asString().equals("audience")); + assertTrue(claims.get(PublicClaims.EXPIRES_AT).asDate().toString().equals(exp.toString())); + } +} \ No newline at end of file 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 014ae838..316d0675 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/PayloadDeserializerTest.java @@ -13,6 +13,7 @@ import org.hamcrest.collection.IsCollectionWithSize; import org.hamcrest.collection.IsEmptyCollection; import org.hamcrest.core.IsCollectionContaining; +import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -90,8 +91,8 @@ public void shouldNotRemoveKnownPublicClaimsFromTree() throws Exception { Payload payload = deserializer.deserialize(jsonParser, mapper.getDeserializationContext()); assertThat(payload, is(notNullValue())); - assertThat(payload.getIssuer(), is("auth0")); - assertThat(payload.getSubject(), is("emails")); + assertTrue(payload.getIssuer().contains("auth0")); + assertTrue(payload.getSubject().contains("emails")); assertThat(payload.getAudience(), is(IsCollectionContaining.hasItem("users"))); assertThat(payload.getIssuedAt().getTime(), is(10101010L * 1000)); assertThat(payload.getExpiresAt().getTime(), is(11111111L * 1000)); 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 ca7562dc..b2bd8ffe 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/PayloadImplTest.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.node.TextNode; import org.hamcrest.collection.IsCollectionWithSize; import org.hamcrest.core.IsCollectionContaining; +import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -36,7 +37,7 @@ public void setUp() throws Exception { 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); + payload = new PayloadImpl(Collections.singletonList("issuer"), Collections.singletonList("subject"), Collections.singletonList("audience"), expiresAt, notBefore, issuedAt, "jwtId", tree); } @SuppressWarnings("Convert2Diamond") @@ -50,7 +51,7 @@ public void shouldHaveUnmodifiableTree() throws Exception { @Test public void shouldGetIssuer() throws Exception { assertThat(payload, is(notNullValue())); - assertThat(payload.getIssuer(), is("issuer")); + assertTrue(payload.getIssuer().contains("issuer")); } @Test @@ -63,7 +64,7 @@ public void shouldGetNullIssuerIfMissing() throws Exception { @Test public void shouldGetSubject() throws Exception { assertThat(payload, is(notNullValue())); - assertThat(payload.getSubject(), is("subject")); + assertTrue(payload.getSubject().contains("subject")); } @Test diff --git a/lib/src/test/java/com/auth0/jwt/verification/VerificationAndAssertionTest.java b/lib/src/test/java/com/auth0/jwt/verification/VerificationAndAssertionTest.java new file mode 100644 index 00000000..c3dc9881 --- /dev/null +++ b/lib/src/test/java/com/auth0/jwt/verification/VerificationAndAssertionTest.java @@ -0,0 +1,54 @@ +package com.auth0.jwt.verification; + +import com.auth0.jwt.TimeUtil; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.creators.ImplicitJwtCreator; +import com.auth0.jwt.exceptions.AlgorithmMismatchException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import com.auth0.jwt.jwts.ImplicitJWT; +import com.auth0.jwt.jwts.JWT; +import com.auth0.jwt.verification.VerificationAndAssertion; +import static java.util.Arrays.asList; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class VerificationAndAssertionTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testAssertPositiveWithNegativeNumber() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Leeway value can't be negative."); + + VerificationAndAssertion.assertPositive(-1); + } + + @Test + public void testAssertNullWithNullString() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("The Custom Claim's name can't be null."); + + VerificationAndAssertion.assertNonNull(null); + } + + @Test + public void testVerifyAlgorithmWithMismatchingAlgorithms() throws Exception { + thrown.expect(AlgorithmMismatchException.class); + thrown.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); + Algorithm algorithm = Algorithm.HMAC256("secret"); + String token = ImplicitJwtCreator.build() + .withIssuer("accounts.fake.com") + .withSubject("subject") + .withAudience("audience") + .withIat(TimeUtil.generateRandomIatDateInPast()) + .sign(algorithm); + Verification verification = ImplicitJWT.require(Algorithm.none()); + JWT verifier = verification.createVerifierForImplicit(asList("accounts.fake.com"), asList("audience"), 1).build(); + DecodedJWT jwt = verifier.decode(token); + } + +}