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