diff --git a/src/main/java/net/oauth/jsontoken/AbstractJsonTokenParser.java b/src/main/java/net/oauth/jsontoken/AbstractJsonTokenParser.java index 987acae..f1a1dc9 100644 --- a/src/main/java/net/oauth/jsontoken/AbstractJsonTokenParser.java +++ b/src/main/java/net/oauth/jsontoken/AbstractJsonTokenParser.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -22,17 +21,17 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import java.security.SignatureException; +import java.time.Instant; import java.util.List; import net.oauth.jsontoken.crypto.AsciiStringVerifier; import net.oauth.jsontoken.crypto.Verifier; import net.oauth.jsontoken.exceptions.ErrorCode; import net.oauth.jsontoken.exceptions.InvalidJsonTokenException; import org.apache.commons.codec.binary.Base64; -import org.joda.time.Instant; /** - * Class that provides common functions - * used by {@link JsonTokenParser} and {@link AsyncJsonTokenParser}. + * Class that provides common functions used by {@link JsonTokenParser} and {@link + * AsyncJsonTokenParser}. */ abstract class AbstractJsonTokenParser { private final Clock clock; @@ -41,8 +40,7 @@ abstract class AbstractJsonTokenParser { /** * Creates a new {@link AbstractJsonTokenParser}. * - * @param clock a clock object that will decide whether a given token is - * currently valid or not. + * @param clock a clock object that will decide whether a given token is currently valid or not. * @param checkers an array of checkers that validates the parameters in the JSON token. */ AbstractJsonTokenParser(Clock clock, Checker... checkers) { @@ -51,8 +49,8 @@ abstract class AbstractJsonTokenParser { } /** - * Decodes the JWT token string into a JsonToken object. Does not perform - * any validation of headers or claims. + * Decodes the JWT token string into a JsonToken object. Does not perform any validation of + * headers or claims. * * @param tokenString The original encoded representation of a JWT * @return Unverified contents of the JWT as a JsonToken @@ -64,25 +62,22 @@ final JsonToken deserializeInternal(String tokenString) { String jwtHeaderSegment = pieces.get(0); String jwtPayloadSegment = pieces.get(1); JsonParser parser = new JsonParser(); - JsonObject header = parser.parse(JsonTokenUtil.fromBase64ToJsonString(jwtHeaderSegment)) - .getAsJsonObject(); - JsonObject payload = parser.parse(JsonTokenUtil.fromBase64ToJsonString(jwtPayloadSegment)) - .getAsJsonObject(); + JsonObject header = + parser.parse(JsonTokenUtil.fromBase64ToJsonString(jwtHeaderSegment)).getAsJsonObject(); + JsonObject payload = + parser.parse(JsonTokenUtil.fromBase64ToJsonString(jwtPayloadSegment)).getAsJsonObject(); - JsonToken jsonToken = new JsonToken(header, payload, clock, tokenString); - return jsonToken; + return new JsonToken(header, payload, clock, tokenString); } /** - * Verifies that the jsonToken has a valid signature and valid standard claims - * (iat, exp). Does not need VerifierProviders because verifiers are passed in - * directly. + * Verifies that the jsonToken has a valid signature and valid standard claims (iat, exp). Does + * not need VerifierProviders because verifiers are passed in directly. * * @param jsonToken the token to verify - * @throws SignatureException when the signature is invalid - * or if any of the checkers fail - * @throws IllegalStateException when exp or iat are invalid - * or if tokenString is not a properly formatted JWT + * @throws SignatureException when the signature is invalid or if any of the checkers fail + * @throws IllegalStateException when exp or iat are invalid or if tokenString is not a properly + * formatted JWT */ final void verifyInternal(JsonToken jsonToken, List verifiers) throws SignatureException { @@ -96,16 +91,19 @@ final void verifyInternal(JsonToken jsonToken, List verifiers) Instant expiration = jsonToken.getExpiration(); if (issuedAt == null && expiration != null) { - issuedAt = new Instant(0); + issuedAt = Instant.EPOCH; } if (issuedAt != null && expiration == null) { - expiration = new Instant(Long.MAX_VALUE); + // TODO(kak): Should this be Instant.MAX instead? + expiration = Instant.ofEpochMilli(Long.MAX_VALUE); } if (issuedAt != null && expiration != null) { - String errorMessage = String.format("Invalid iat and/or exp. iat: %s exp: %s now: %s", - jsonToken.getIssuedAt(), jsonToken.getExpiration(), clock.now()); + String errorMessage = + String.format( + "Invalid iat and/or exp. iat: %s exp: %s now: %s", + jsonToken.getIssuedAt(), jsonToken.getExpiration(), clock.now()); if (issuedAt.isAfter(expiration)) { throw new IllegalStateException( @@ -134,8 +132,7 @@ final void verifyInternal(JsonToken jsonToken, List verifiers) * Verifies that a JSON Web Token's signature is valid. * * @param tokenString the encoded and signed JSON Web Token to verify. - * @param verifiers used to verify the signature. These usually encapsulate - * secret keys. + * @param verifiers used to verify the signature. These usually encapsulate secret keys. * @throws IllegalStateException if tokenString is not a properly formatted JWT */ final boolean signatureIsValidInternal(String tokenString, List verifiers) { @@ -190,11 +187,13 @@ private List splitTokenString(String tokenString) { List pieces = Splitter.on(JsonTokenUtil.DELIMITER).splitToList(tokenString); if (pieces.size() != 3) { throw new IllegalStateException( - "Expected JWT to have 3 segments separated by '" + - JsonTokenUtil.DELIMITER + "', but it has " + pieces.size() + " segments", + "Expected JWT to have 3 segments separated by '" + + JsonTokenUtil.DELIMITER + + "', but it has " + + pieces.size() + + " segments", new InvalidJsonTokenException(ErrorCode.MALFORMED_TOKEN_STRING)); } return pieces; } - } diff --git a/src/main/java/net/oauth/jsontoken/AsyncJsonTokenParser.java b/src/main/java/net/oauth/jsontoken/AsyncJsonTokenParser.java index c3acdd8..c808021 100644 --- a/src/main/java/net/oauth/jsontoken/AsyncJsonTokenParser.java +++ b/src/main/java/net/oauth/jsontoken/AsyncJsonTokenParser.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -36,8 +35,8 @@ import net.oauth.jsontoken.exceptions.InvalidJsonTokenException; /** - * The asynchronous counterpart of {@link JsonTokenParser}. - * Class that parses and verifies JSON Tokens asynchronously. + * The asynchronous counterpart of {@link JsonTokenParser}. Class that parses and verifies JSON + * Tokens asynchronously. */ public final class AsyncJsonTokenParser extends AbstractJsonTokenParser { private final AsyncVerifierProviders asyncVerifierProviders; @@ -47,8 +46,8 @@ public final class AsyncJsonTokenParser extends AbstractJsonTokenParser { * Creates a new {@link AsyncJsonTokenParser}. * * @param clock a clock object that will decide whether a given token is currently valid or not. - * @param asyncVerifierProviders an object that provides signature verifiers asynchronously - * based on a signature algorithm, the signer, and key ids. + * @param asyncVerifierProviders an object that provides signature verifiers asynchronously based + * on a signature algorithm, the signer, and key ids. * @param executor an executor to run the tasks before and after getting the verifiers * @param checkers an array of checkers that validates the parameters in the JSON token. */ @@ -63,29 +62,22 @@ public AsyncJsonTokenParser( } /** - * Verifies that the jsonToken has a valid signature and valid standard claims - * (iat, exp). Uses {@link AsyncVerifierProviders} to obtain the secret key. - * This method is not expected to throw exceptions when returning a future. However, - * when getting the result of the future, an {@link ExecutionException} may be thrown - * in which {@link ExecutionException#getCause()} is an {@link InvalidJsonTokenException} - * with an error code of: + * Verifies that the jsonToken has a valid signature and valid standard claims (iat, exp). Uses + * {@link AsyncVerifierProviders} to obtain the secret key. This method is not expected to throw + * exceptions when returning a future. However, when getting the result of the future, an {@link + * ExecutionException} may be thrown in which {@link ExecutionException#getCause()} is an {@link + * InvalidJsonTokenException} with an error code of: + * *
    - *
  • {@link ErrorCode#BAD_HEADER}: - * if the header does not have all of the required parameters
  • - *
  • {@link ErrorCode#BAD_SIGNATURE}: - * if the signature is invalid
  • - *
  • {@link ErrorCode#BAD_TIME_RANGE}: - * if the IAT is after EXP or the token is in the future
  • - *
  • {@link ErrorCode#EXPIRED_TOKEN}: - * if the token is expired
  • - *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING}: - * if the tokenString is not a properly formatted JWT
  • - *
  • {@link ErrorCode#NO_VERIFIER}: - * if there is no valid verifier for the (issuer, keyId) pair
  • - *
  • {@link ErrorCode#UNKNOWN}: - * if any of the checkers fail
  • - *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM}: - * if the signature algorithm is unsupported
  • + *
  • {@link ErrorCode#BAD_HEADER}: if the header does not have all of the required parameters + *
  • {@link ErrorCode#BAD_SIGNATURE}: if the signature is invalid + *
  • {@link ErrorCode#BAD_TIME_RANGE}: if the IAT is after EXP or the token is in the future + *
  • {@link ErrorCode#EXPIRED_TOKEN}: if the token is expired + *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING}: if the tokenString is not a properly formatted + * JWT + *
  • {@link ErrorCode#NO_VERIFIER}: if there is no valid verifier for the (issuer, keyId) pair + *
  • {@link ErrorCode#UNKNOWN}: if any of the checkers fail + *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM}: if the signature algorithm is unsupported *
* * @param jsonToken @@ -107,34 +99,26 @@ public ListenableFuture verify(JsonToken jsonToken) { } /** - * Parses and verifies a JSON Token. - * This method is not expected to throw exceptions when returning a future. However, - * when getting the result of the future, an {@link ExecutionException} may be thrown - * in which {@link ExecutionException#getCause()} is an {@link InvalidJsonTokenException} - * with an error code of: + * Parses and verifies a JSON Token. This method is not expected to throw exceptions when + * returning a future. However, when getting the result of the future, an {@link + * ExecutionException} may be thrown in which {@link ExecutionException#getCause()} is an {@link + * InvalidJsonTokenException} with an error code of: + * *
    - *
  • {@link ErrorCode#BAD_HEADER} - * if the header does not have all of the required parameters
  • - *
  • {@link ErrorCode#BAD_SIGNATURE} - * if the signature is invalid
  • - *
  • {@link ErrorCode#BAD_TIME_RANGE} - * if the IAT is after EXP or the token is in the future
  • - *
  • {@link ErrorCode#EXPIRED_TOKEN} - * if the token is expired
  • - *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING} - * if the tokenString is not a properly formed JWT
  • - *
  • {@link ErrorCode#NO_VERIFIER} - * if there is no valid verifier for the (issuer, keyId) pair
  • - *
  • {@link ErrorCode#UNKNOWN} - * if any of the checkers fail
  • - *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM} - * if the signature algorithm is unsupported
  • + *
  • {@link ErrorCode#BAD_HEADER} if the header does not have all of the required parameters + *
  • {@link ErrorCode#BAD_SIGNATURE} if the signature is invalid + *
  • {@link ErrorCode#BAD_TIME_RANGE} if the IAT is after EXP or the token is in the future + *
  • {@link ErrorCode#EXPIRED_TOKEN} if the token is expired + *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING} if the tokenString is not a properly formed JWT + *
  • {@link ErrorCode#NO_VERIFIER} if there is no valid verifier for the (issuer, keyId) pair + *
  • {@link ErrorCode#UNKNOWN} if any of the checkers fail + *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM} if the signature algorithm is unsupported *
* * @param tokenString the serialized token that is to parsed and verified. * @return a {@link ListenableFuture} that will return the deserialized {@link JsonObject}, - * suitable for passing to the constructor of {@link JsonToken} - * or equivalent constructor of {@link JsonToken} subclasses. + * suitable for passing to the constructor of {@link JsonToken} or equivalent constructor of + * {@link JsonToken} subclasses. */ @Nonnull public ListenableFuture verifyAndDeserialize(String tokenString) { @@ -151,58 +135,54 @@ public ListenableFuture verifyAndDeserialize(String tokenString) { } /** - * Decodes the JWT token string into a JsonToken object. Does not perform - * any validation of headers or claims. - * Identical to {@link AbstractJsonTokenParser#deserializeInternal(String)}, + * Decodes the JWT token string into a JsonToken object. Does not perform any validation of + * headers or claims. Identical to {@link AbstractJsonTokenParser#deserializeInternal(String)}, * except exceptions are caught and rethrown as {@link InvalidJsonTokenException}. * * @param tokenString The original encoded representation of a JWT * @return Unverified contents of the JWT as a JsonToken - * @throws InvalidJsonTokenException with {@link ErrorCode#MALFORMED_TOKEN_STRING} - * if the tokenString is not a properly formatted JWT. + * @throws InvalidJsonTokenException with {@link ErrorCode#MALFORMED_TOKEN_STRING} if the + * tokenString is not a properly formatted JWT. */ public JsonToken deserialize(String tokenString) throws InvalidJsonTokenException { return mapExceptions(() -> deserializeInternal(tokenString)); } /** - * Verifies that the jsonToken has a valid signature and valid standard claims - * (iat, exp). Does not need VerifierProviders because verifiers are passed in - * directly. - * Identical to {@link AbstractJsonTokenParser#verifyInternal(JsonToken, List)}, - * except exceptions are caught and rethrown as {@link InvalidJsonTokenException}. + * Verifies that the jsonToken has a valid signature and valid standard claims (iat, exp). Does + * not need VerifierProviders because verifiers are passed in directly. Identical to {@link + * AbstractJsonTokenParser#verifyInternal(JsonToken, List)}, except exceptions are caught and + * rethrown as {@link InvalidJsonTokenException}. * * @param jsonToken the token to verify * @throws InvalidJsonTokenException with the error code - *
    - *
  • {@link ErrorCode#BAD_SIGNATURE} - * if the signature is invalid
  • - *
  • {@link ErrorCode#BAD_TIME_RANGE} - * if the IAT is after EXP or the token is in the future
  • - *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING} - * if the tokenString is not a properly formed JWT
  • - *
  • {@link ErrorCode#UNKNOWN} - * if any of the checkers fail
  • - *
+ *
    + *
  • {@link ErrorCode#BAD_SIGNATURE} if the signature is invalid + *
  • {@link ErrorCode#BAD_TIME_RANGE} if the IAT is after EXP or the token is in the + * future + *
  • {@link ErrorCode#MALFORMED_TOKEN_STRING} if the tokenString is not a properly formed + * JWT + *
  • {@link ErrorCode#UNKNOWN} if any of the checkers fail + *
*/ public void verify(JsonToken jsonToken, List verifiers) throws InvalidJsonTokenException { - mapExceptions(() -> { - verifyInternal(jsonToken, verifiers); - return null; - }); + mapExceptions( + () -> { + verifyInternal(jsonToken, verifiers); + return null; + }); } /** - * Verifies that a JSON Web Token's signature is valid. - * Identical to {@link AbstractJsonTokenParser#signatureIsValidInternal(String, List)}, - * except exceptions are caught and rethrown as {@link InvalidJsonTokenException}. + * Verifies that a JSON Web Token's signature is valid. Identical to {@link + * AbstractJsonTokenParser#signatureIsValidInternal(String, List)}, except exceptions are caught + * and rethrown as {@link InvalidJsonTokenException}. * * @param tokenString the encoded and signed JSON Web Token to verify. - * @param verifiers used to verify the signature. These usually encapsulate - * secret keys. - * @throws InvalidJsonTokenException with {@link ErrorCode#MALFORMED_TOKEN_STRING} - * if the tokenString is not a properly formatted JWT. + * @param verifiers used to verify the signature. These usually encapsulate secret keys. + * @throws InvalidJsonTokenException with {@link ErrorCode#MALFORMED_TOKEN_STRING} if the + * tokenString is not a properly formatted JWT. */ public boolean signatureIsValid(String tokenString, List verifiers) throws InvalidJsonTokenException { @@ -210,19 +190,15 @@ public boolean signatureIsValid(String tokenString, List verifiers) } /** - * Use {@link AsyncVerifierProviders} to get future that will return a list of verifiers - * for this token. - * This method is not expected to throw exceptions when returning a future. However, - * when getting the result of the future, an {@link ExecutionException} may be thrown - * in which {@link ExecutionException#getCause()} is an {@link InvalidJsonTokenException} - * with an error code of: + * Use {@link AsyncVerifierProviders} to get future that will return a list of verifiers for this + * token. This method is not expected to throw exceptions when returning a future. However, when + * getting the result of the future, an {@link ExecutionException} may be thrown in which {@link + * ExecutionException#getCause()} is an {@link InvalidJsonTokenException} with an error code of: + * *
    - *
  • {@link ErrorCode#BAD_HEADER} - * if the header does not have all of the required parameters
  • - *
  • {@link ErrorCode#NO_VERIFIER} - * if there is no valid verifier for the (issuer, keyId) pair
  • - *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM} - * if the signature algorithm is unsupported
  • + *
  • {@link ErrorCode#BAD_HEADER} if the header does not have all of the required parameters + *
  • {@link ErrorCode#NO_VERIFIER} if there is no valid verifier for the (issuer, keyId) pair + *
  • {@link ErrorCode#UNSUPPORTED_ALGORITHM} if the signature algorithm is unsupported *
* * @param jsonToken @@ -262,8 +238,8 @@ private ListenableFuture> provideVerifiers(JsonToken jsonToken) { } /** - * Remaps exceptions, when applicable, to {@link InvalidJsonTokenException} for improved - * exception handling in the asynchronous parser. Otherwise, the original exception is returned. + * Remaps exceptions, when applicable, to {@link InvalidJsonTokenException} for improved exception + * handling in the asynchronous parser. Otherwise, the original exception is returned. */ private Exception mapException(Exception originalException) { Throwable cause = originalException.getCause(); @@ -289,8 +265,8 @@ private Exception mapException(Exception originalException) { } /** - * Rethrows any {@link SignatureException}, any {@link RuntimeException}s, or any - * {@link Exception} where {@link Exception#getCause()} is {@link InvalidJsonTokenException}. + * Rethrows any {@link SignatureException}, any {@link RuntimeException}s, or any {@link + * Exception} where {@link Exception#getCause()} is {@link InvalidJsonTokenException}. */ private T mapExceptions(Callable callable) throws InvalidJsonTokenException { try { @@ -309,14 +285,16 @@ private T mapExceptions(Callable callable) throws InvalidJsonTokenExcepti } /** - * Catches any failed futures and returns a new future with a mapped exception. - * Unlike {@link #mapExceptions(Callable)}, this function supports all exceptions. + * Catches any failed futures and returns a new future with a mapped exception. Unlike {@link + * #mapExceptions(Callable)}, this function supports all exceptions. */ private ListenableFuture mapExceptions(ListenableFuture result) { - return Futures.catchingAsync(result, Exception.class, + return Futures.catchingAsync( + result, + Exception.class, exception -> { throw mapException(exception); - }, executor); + }, + executor); } - } diff --git a/src/main/java/net/oauth/jsontoken/Checker.java b/src/main/java/net/oauth/jsontoken/Checker.java index 01527ce..35dd1e8 100644 --- a/src/main/java/net/oauth/jsontoken/Checker.java +++ b/src/main/java/net/oauth/jsontoken/Checker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,16 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; import com.google.gson.JsonObject; import java.security.SignatureException; -/** - * Token verifiers must implement this interface. - */ +/** Token verifiers must implement this interface. */ public interface Checker { /** @@ -31,5 +28,4 @@ public interface Checker { * @throws SignatureException if the audience doesn't match. */ void check(JsonObject payload) throws SignatureException; - } diff --git a/src/main/java/net/oauth/jsontoken/Clock.java b/src/main/java/net/oauth/jsontoken/Clock.java index daf7de6..1687ccd 100644 --- a/src/main/java/net/oauth/jsontoken/Clock.java +++ b/src/main/java/net/oauth/jsontoken/Clock.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,26 +12,21 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; -import org.joda.time.Instant; +import java.time.Instant; -/** - * Clock interface. - */ +/** Clock interface. */ public interface Clock { - /** - * Returns current time. - */ + /** Returns current time. */ Instant now(); /** - * Determines whether the current time falls within the interval defined by the - * start and intervalLength parameters. Implementations are free to fudge this a - * little bit to take into account possible clock skew. + * Determines whether the current time falls within the interval defined by {@code start} and + * {@code end}. Implementations are free to fudge this a little bit to take into account possible + * clock skew. */ boolean isCurrentTimeInInterval(Instant start, Instant end); } diff --git a/src/main/java/net/oauth/jsontoken/JsonToken.java b/src/main/java/net/oauth/jsontoken/JsonToken.java index 8f27d77..72a8e94 100644 --- a/src/main/java/net/oauth/jsontoken/JsonToken.java +++ b/src/main/java/net/oauth/jsontoken/JsonToken.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,15 +12,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; -import com.google.common.base.Preconditions; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import java.security.SignatureException; +import java.time.Duration; +import java.time.Instant; import javax.annotation.Nullable; import net.oauth.jsontoken.crypto.AsciiStringSigner; import net.oauth.jsontoken.crypto.SignatureAlgorithm; @@ -28,41 +30,38 @@ import net.oauth.jsontoken.exceptions.ErrorCode; import net.oauth.jsontoken.exceptions.InvalidJsonTokenException; import org.apache.commons.codec.binary.Base64; -import org.joda.time.Instant; -/** - * A JSON Token. - */ +/** A JSON Token. */ public class JsonToken { // header names - public final static String ALGORITHM_HEADER = "alg"; - public final static String KEY_ID_HEADER = "kid"; - public final static String TYPE_HEADER = "typ"; - + public static final String ALGORITHM_HEADER = "alg"; + public static final String KEY_ID_HEADER = "kid"; + public static final String TYPE_HEADER = "typ"; + // standard claim names (payload parameters) - public final static String ISSUER = "iss"; - public final static String ISSUED_AT = "iat"; - public final static String EXPIRATION = "exp"; - public final static String AUDIENCE = "aud"; - + public static final String ISSUER = "iss"; + public static final String ISSUED_AT = "iat"; + public static final String EXPIRATION = "exp"; + public static final String AUDIENCE = "aud"; + // default encoding for all Json token - public final static String BASE64URL_ENCODING = "base64url"; - - public final static int DEFAULT_LIFETIME_IN_MINS = 2; + public static final String BASE64URL_ENCODING = "base64url"; + + public static final Duration DEFAULT_LIFETIME = Duration.ofMinutes(2); protected final Clock clock; private final JsonObject header; private final JsonObject payload; private final String tokenString; - + // The following fields are only valid when signing the token. private final Signer signer; private String signature; private String baseString; - - + /** * Public constructor, use empty data type. + * * @param signer the signer that will sign the token. */ public JsonToken(Signer signer) { @@ -71,17 +70,16 @@ public JsonToken(Signer signer) { /** * Public constructor. + * * @param signer the signer that will sign the token - * @param clock a clock whose notion of current time will determine the not-before timestamp - * of the token, if not explicitly set. + * @param clock a clock whose notion of current time will determine the not-before timestamp of + * the token, if not explicitly set. */ public JsonToken(Signer signer, Clock clock) { - Preconditions.checkNotNull(signer); - Preconditions.checkNotNull(clock); + this.signer = checkNotNull(signer); + this.clock = checkNotNull(clock); this.header = createHeader(signer); this.payload = new JsonObject(); - this.signer = signer; - this.clock = clock; this.signature = null; this.baseString = null; this.tokenString = null; @@ -93,17 +91,16 @@ public JsonToken(Signer signer, Clock clock) { } /** - * Public constructor used when parsing a JsonToken {@link JsonToken} - * (as opposed to create a token). This constructor takes Json payload - * and clock as parameters, set all other signing related parameters to null. + * Public constructor used when parsing a JsonToken {@link JsonToken} (as opposed to create a + * token). This constructor takes Json payload and clock as parameters, set all other signing + * related parameters to null. * * @param payload A payload JSON object. - * @param clock a clock whose notion of current time will determine the not-before timestamp - * of the token, if not explicitly set. + * @param clock a clock whose notion of current time will determine the not-before timestamp of + * the token, if not explicitly set. * @param tokenString The original token string we parsed to get this payload. */ - public JsonToken(JsonObject header, JsonObject payload, Clock clock, - String tokenString) { + public JsonToken(JsonObject header, JsonObject payload, Clock clock, String tokenString) { this.header = header; this.payload = payload; this.clock = clock; @@ -112,11 +109,11 @@ public JsonToken(JsonObject header, JsonObject payload, Clock clock, this.signer = null; this.tokenString = tokenString; } - + /** - * Public constructor used when parsing a JsonToken {@link JsonToken} - * (as opposed to create a token). This constructor takes Json payload - * as parameter, set all other signing related parameters to null. + * Public constructor used when parsing a JsonToken {@link JsonToken} (as opposed to create a + * token). This constructor takes Json payload as parameter, set all other signing related + * parameters to null. * * @param payload A payload JSON object. */ @@ -131,13 +128,13 @@ public JsonToken(JsonObject payload) { } /** - * Public constructor used when parsing a JsonToken {@link JsonToken} - * (as opposed to create a token). This constructor takes Json payload - * and clock as parameters, set all other signing related parameters to null. + * Public constructor used when parsing a JsonToken {@link JsonToken} (as opposed to create a + * token). This constructor takes Json payload and clock as parameters, set all other signing + * related parameters to null. * * @param payload A payload JSON object. - * @param clock a clock whose notion of current time will determine the not-before timestamp - * of the token, if not explicitly set. + * @param clock a clock whose notion of current time will determine the not-before timestamp of + * the token, if not explicitly set. */ public JsonToken(JsonObject payload, Clock clock) { this.header = null; @@ -153,8 +150,8 @@ public JsonToken(JsonObject payload, Clock clock) { * Returns the serialized representation of this token, i.e., * keyId.sig.base64(payload).base64(data_type).base64(encoding).base64(alg) * - * This is what a client (token issuer) would send to a token verifier over the - * wire. + *

This is what a client (token issuer) would send to a token verifier over the wire. + * * @throws SignatureException if the token can't be signed. */ public String serializeAndSign() throws SignatureException { @@ -163,9 +160,7 @@ public String serializeAndSign() throws SignatureException { return JsonTokenUtil.toDotFormat(baseString, sig); } - /** - * Returns a human-readable version of the token. - */ + /** Returns a human-readable version of the token. */ @Override public String toString() { return JsonTokenUtil.toJson(payload); @@ -178,30 +173,30 @@ public String getIssuer() { @Nullable public Instant getIssuedAt() { - Long issuedAt = getParamAsLong(ISSUED_AT); - if (issuedAt == null) { - return null; - } - // JWT represents time in seconds, Instants expect milliseconds - return new Instant(issuedAt * 1000); + return getParamAsInstant(ISSUED_AT); } + /** + * Sets the {@code iat} (issued at) timestamp parameter. + * + *

Note: sub-second precision is truncated. + */ public void setIssuedAt(Instant instant) { - setParam(ISSUED_AT, instant.getMillis() / 1000); + setParam(ISSUED_AT, instant.getEpochSecond()); } @Nullable public Instant getExpiration() { - Long expiration = getParamAsLong(EXPIRATION); - if (expiration == null) { - return null; - } - // JWT represents time in seconds, Instants expect milliseconds - return new Instant(expiration * 1000); + return getParamAsInstant(EXPIRATION); } + /** + * Sets the {@code exp} (expiration) timestamp parameter. + * + *

Note: sub-second precision is truncated. + */ public void setExpiration(Instant instant) { - setParam(EXPIRATION, instant.getMillis() / 1000); + setParam(EXPIRATION, instant.getEpochSecond()); } @Nullable @@ -265,8 +260,7 @@ public SignatureAlgorithm getSignatureAlgorithm() { return SignatureAlgorithm.getFromJsonName(algorithmName.getAsString()); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( - e.getMessage(), - new InvalidJsonTokenException(ErrorCode.UNSUPPORTED_ALGORITHM)); + e.getMessage(), new InvalidJsonTokenException(ErrorCode.UNSUPPORTED_ALGORITHM)); } } @@ -274,9 +268,7 @@ public String getTokenString() { return tokenString; } - /** - * @throws IllegalStateException if the header does not exist - */ + /** @throws IllegalStateException if the header does not exist */ public JsonObject getHeader() { if (header == null) { throw new IllegalStateException("JWT has no header"); @@ -291,11 +283,12 @@ private String getParamAsString(String param) { } @Nullable - private Long getParamAsLong(String param) { + private Instant getParamAsInstant(String param) { JsonPrimitive primitive = getParamAsPrimitive(param); if (primitive != null && (primitive.isNumber() || primitive.isString())) { try { - return primitive.getAsLong(); + // JWT represents time in seconds + return Instant.ofEpochSecond(primitive.getAsLong()); } catch (NumberFormatException e) { return null; } @@ -303,17 +296,14 @@ private Long getParamAsLong(String param) { return null; } - /** - * @throws IllegalStateException if the header does not exist - */ + /** @throws IllegalStateException if the header does not exist */ protected String computeSignatureBaseString() { if (baseString != null && !baseString.isEmpty()) { return baseString; } - baseString = JsonTokenUtil.toDotFormat( - JsonTokenUtil.toBase64(getHeader()), - JsonTokenUtil.toBase64(payload) - ); + baseString = + JsonTokenUtil.toDotFormat( + JsonTokenUtil.toBase64(getHeader()), JsonTokenUtil.toBase64(payload)); return baseString; } @@ -330,9 +320,7 @@ private static JsonObject createHeader(Signer signer) { return newHeader; } - /** - * @throws SignatureException if the signer does not exist - */ + /** @throws SignatureException if the signer does not exist */ private String getSignature() throws SignatureException { if (signature != null && !signature.isEmpty()) { return signature; @@ -344,12 +332,8 @@ private String getSignature() throws SignatureException { new InvalidJsonTokenException(ErrorCode.ILLEGAL_STATE)); } - String signature; // now, generate the signature AsciiStringSigner asciiSigner = new AsciiStringSigner(signer); - signature = Base64.encodeBase64URLSafeString(asciiSigner.sign(baseString)); - - return signature; + return Base64.encodeBase64URLSafeString(asciiSigner.sign(baseString)); } - } diff --git a/src/main/java/net/oauth/jsontoken/JsonTokenParser.java b/src/main/java/net/oauth/jsontoken/JsonTokenParser.java index f885ce0..4b6b0ea 100644 --- a/src/main/java/net/oauth/jsontoken/JsonTokenParser.java +++ b/src/main/java/net/oauth/jsontoken/JsonTokenParser.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -28,18 +27,16 @@ import net.oauth.jsontoken.exceptions.ErrorCode; import net.oauth.jsontoken.exceptions.InvalidJsonTokenException; -/** - * Class that parses and verifies JSON Tokens. - */ +/** Class that parses and verifies JSON Tokens. */ public class JsonTokenParser extends AbstractJsonTokenParser { private final VerifierProviders verifierProviders; /** - * Creates a new {@link JsonTokenParser} with a default system clock. The default - * system clock tolerates a clock skew of up to {@link SystemClock#DEFAULT_ACCEPTABLE_CLOCK_SKEW}. + * Creates a new {@link JsonTokenParser} with a default system clock. The default system clock + * tolerates a clock skew of up to {@link SystemClock#DEFAULT_ACCEPTABLE_CLOCK_SKEW}. * - * @param verifierProviders an object that provides signature verifiers - * based on a signature algorithm, the signer, and key ids. + * @param verifierProviders an object that provides signature verifiers based on a signature + * algorithm, the signer, and key ids. * @param checker an audience checker that validates the audience in the JSON token. */ public JsonTokenParser(VerifierProviders verifierProviders, Checker checker) { @@ -49,10 +46,9 @@ public JsonTokenParser(VerifierProviders verifierProviders, Checker checker) { /** * Creates a new {@link JsonTokenParser}. * - * @param clock a clock object that will decide whether a given token is - * currently valid or not. - * @param verifierProviders an object that provides signature verifiers - * based on a signature algorithm, the signer, and key ids. + * @param clock a clock object that will decide whether a given token is currently valid or not. + * @param verifierProviders an object that provides signature verifiers based on a signature + * algorithm, the signer, and key ids. * @param checkers an array of checkers that validates the parameters in the JSON token. */ public JsonTokenParser(Clock clock, VerifierProviders verifierProviders, Checker... checkers) { @@ -61,16 +57,14 @@ public JsonTokenParser(Clock clock, VerifierProviders verifierProviders, Checker } /** - * Verifies that the jsonToken has a valid signature and valid standard claims - * (iat, exp). Uses VerifierProviders to obtain the secret key. - * + * Verifies that the jsonToken has a valid signature and valid standard claims (iat, exp). Uses + * VerifierProviders to obtain the secret key. + * * @param jsonToken - * @throws SignatureException when the signature is invalid - * or if any of the checkers fail + * @throws SignatureException when the signature is invalid or if any of the checkers fail * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer - * or if the header does not exist + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer or if the header does not exist */ public void verify(JsonToken jsonToken) throws SignatureException { List verifiers = provideVerifiers(jsonToken); @@ -79,16 +73,15 @@ public void verify(JsonToken jsonToken) throws SignatureException { /** * Parses, and verifies, a JSON Token. - * + * * @param tokenString the serialized token that is to parsed and verified. - * @return the deserialized {@link JsonObject}, suitable for passing to the constructor - * of {@link JsonToken} or equivalent constructor of {@link JsonToken} subclasses. - * @throws SignatureException when the signature is invalid - * or if any of the checkers fail + * @return the deserialized {@link JsonObject}, suitable for passing to the constructor of {@link + * JsonToken} or equivalent constructor of {@link JsonToken} subclasses. + * @throws SignatureException when the signature is invalid or if any of the checkers fail * @throws JsonParseException if the header or payload portion of tokenString is corrupted * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer */ public JsonToken verifyAndDeserialize(String tokenString) throws SignatureException { JsonToken jsonToken = deserialize(tokenString); @@ -97,9 +90,8 @@ public JsonToken verifyAndDeserialize(String tokenString) throws SignatureExcept } /** - * Decodes the JWT token string into a JsonToken object. Does not perform - * any validation of headers or claims. - * Identical to {@link AbstractJsonTokenParser#deserializeInternal(String)}. + * Decodes the JWT token string into a JsonToken object. Does not perform any validation of + * headers or claims. Identical to {@link AbstractJsonTokenParser#deserializeInternal(String)}. * * @param tokenString The original encoded representation of a JWT * @return Unverified contents of the JWT as a JsonToken @@ -111,28 +103,25 @@ public JsonToken deserialize(String tokenString) { } /** - * Verifies that the jsonToken has a valid signature and valid standard claims - * (iat, exp). Does not need VerifierProviders because verifiers are passed in - * directly. - * Identical to {@link AbstractJsonTokenParser#verifyInternal(JsonToken, List)} + * Verifies that the jsonToken has a valid signature and valid standard claims (iat, exp). Does + * not need VerifierProviders because verifiers are passed in directly. Identical to {@link + * AbstractJsonTokenParser#verifyInternal(JsonToken, List)} * * @param jsonToken the token to verify - * @throws SignatureException when the signature is invalid - * or if any of the checkers fail - * @throws IllegalStateException when exp or iat are invalid - * or if tokenString is not a properly formatted JWT + * @throws SignatureException when the signature is invalid or if any of the checkers fail + * @throws IllegalStateException when exp or iat are invalid or if tokenString is not a properly + * formatted JWT */ public void verify(JsonToken jsonToken, List verifiers) throws SignatureException { verifyInternal(jsonToken, verifiers); } /** - * Verifies that a JSON Web Token's signature is valid. - * Identical to {@link AbstractJsonTokenParser#signatureIsValidInternal(String, List)}. + * Verifies that a JSON Web Token's signature is valid. Identical to {@link + * AbstractJsonTokenParser#signatureIsValidInternal(String, List)}. * * @param tokenString the encoded and signed JSON Web Token to verify. - * @param verifiers used to verify the signature. These usually encapsulate - * secret keys. + * @param verifiers used to verify the signature. These usually encapsulate secret keys. * @throws IllegalStateException if tokenString is not a properly formatted JWT */ public boolean signatureIsValid(String tokenString, List verifiers) { @@ -145,16 +134,16 @@ public boolean signatureIsValid(String tokenString, List verifiers) { * @param jsonToken * @return list of verifiers * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if there is no valid verifier for the issuer - * or if the header does not exist + * @throws IllegalStateException if there is no valid verifier for the issuer or if the header + * does not exist */ private List provideVerifiers(JsonToken jsonToken) { Preconditions.checkNotNull(verifierProviders); SignatureAlgorithm signatureAlgorithm = jsonToken.getSignatureAlgorithm(); VerifierProvider provider = verifierProviders.getVerifierProvider(signatureAlgorithm); if (provider == null) { - throw new IllegalArgumentException("Signature algorithm not supported: " - + signatureAlgorithm); + throw new IllegalArgumentException( + "Signature algorithm not supported: " + signatureAlgorithm); } List verifiers = provider.findVerifier(jsonToken.getIssuer(), jsonToken.getKeyId()); @@ -166,5 +155,4 @@ private List provideVerifiers(JsonToken jsonToken) { return verifiers; } - } diff --git a/src/main/java/net/oauth/jsontoken/JsonTokenUtil.java b/src/main/java/net/oauth/jsontoken/JsonTokenUtil.java index 6acc19c..da65a02 100644 --- a/src/main/java/net/oauth/jsontoken/JsonTokenUtil.java +++ b/src/main/java/net/oauth/jsontoken/JsonTokenUtil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,24 +12,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.StringUtils; - import com.google.common.base.Joiner; import com.google.gson.Gson; import com.google.gson.JsonObject; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.StringUtils; +/** Some utility functions for {@link JsonToken}s. */ +final class JsonTokenUtil { -/** - * Some utility functions for {@link JsonToken}s. - */ -class JsonTokenUtil { - - static public final String DELIMITER = "."; + public static final String DELIMITER = "."; public static String toBase64(JsonObject json) { return convertToBase64(toJson(json)); @@ -42,18 +37,18 @@ public static String toJson(JsonObject json) { public static String convertToBase64(String source) { return Base64.encodeBase64URLSafeString(StringUtils.getBytesUtf8(source)); } - + public static String decodeFromBase64String(String encoded) { return new String(Base64.decodeBase64(encoded)); } - + public static String fromBase64ToJsonString(String source) { return StringUtils.newStringUtf8(Base64.decodeBase64(source)); } - + public static String toDotFormat(String... parts) { - return Joiner.on('.').useForNull("").join(parts); + return Joiner.on(DELIMITER).useForNull("").join(parts); } - - private JsonTokenUtil() { } + + private JsonTokenUtil() {} } diff --git a/src/main/java/net/oauth/jsontoken/SystemClock.java b/src/main/java/net/oauth/jsontoken/SystemClock.java index 3defbf0..587aa72 100644 --- a/src/main/java/net/oauth/jsontoken/SystemClock.java +++ b/src/main/java/net/oauth/jsontoken/SystemClock.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,13 +12,14 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; -import org.joda.time.Duration; -import org.joda.time.Instant; -import org.joda.time.Interval; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.Range; +import java.time.Duration; +import java.time.Instant; /** * Default implementation of {@link Clock}, which accepts clock skews (when comparing time @@ -26,25 +27,24 @@ */ public class SystemClock implements Clock { - public static final Duration DEFAULT_ACCEPTABLE_CLOCK_SKEW = Duration.standardMinutes(2); + public static final Duration DEFAULT_ACCEPTABLE_CLOCK_SKEW = Duration.ofMinutes(2); private final Duration acceptableClockSkew; - /** - * Public constructor. - */ + /** Public constructor. */ public SystemClock() { this(DEFAULT_ACCEPTABLE_CLOCK_SKEW); } /** * Public constructor. - * @param acceptableClockSkew the current time will be considered inside the - * interval at {@link #isCurrentTimeInInterval(Instant, Duration)} even if the current time - * is up to acceptableClockSkew off the ends of the interval. + * + * @param acceptableClockSkew the current time will be considered inside the interval at {@link + * #isCurrentTimeInInterval(Instant, Instant)} even if the current time is up to + * acceptableClockSkew off the ends of the interval. */ public SystemClock(Duration acceptableClockSkew) { - this.acceptableClockSkew = acceptableClockSkew; + this.acceptableClockSkew = checkNotNull(acceptableClockSkew); } /* @@ -53,19 +53,19 @@ public SystemClock(Duration acceptableClockSkew) { */ @Override public Instant now() { - return new Instant(); + return Instant.now(); } /** - * Determines whether the current time (plus minus the acceptableClockSkew) falls within the - * interval defined by the start and intervalLength parameters. + * Determines whether the current time (plus minus the {@code acceptableClockSkew}) falls within + * the interval defined by {@code start} and {@code end}. */ @Override public boolean isCurrentTimeInInterval(Instant start, Instant end) { - Interval interval = new Interval(start, end); + Range interval = Range.closed(start, end); Instant now = now(); - Interval currentTimeWithSkew = - new Interval(now.minus(acceptableClockSkew), now.plus(acceptableClockSkew)); - return interval.overlaps(currentTimeWithSkew); + Range currentTimeWithSkew = + Range.closed(now.minus(acceptableClockSkew), now.plus(acceptableClockSkew)); + return interval.isConnected(currentTimeWithSkew); } } diff --git a/src/main/java/net/oauth/jsontoken/crypto/AbstractSigner.java b/src/main/java/net/oauth/jsontoken/crypto/AbstractSigner.java index 343c40a..62932a2 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/AbstractSigner.java +++ b/src/main/java/net/oauth/jsontoken/crypto/AbstractSigner.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,13 +12,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; -/** - * Superclass for {@link Signer}s. - */ +/** Superclass for {@link Signer}s. */ public abstract class AbstractSigner implements Signer { private final String issuer; @@ -28,7 +25,7 @@ public abstract class AbstractSigner implements Signer { * Caller can suggest which key should be used for signing by passing 'suggestedKeyId' to signer. * It's up to signer whether to use the suggestedKeyId or not. The final signing key id can be * retrieved by calling getKeyId(). - * + * * @param issuer * @param suggestedKeyId */ @@ -36,7 +33,7 @@ protected AbstractSigner(String issuer, String suggestedKeyId) { this.issuer = issuer; this.keyId = suggestedKeyId; } - + protected void setSigningKeyId(String keyId) { this.keyId = keyId; } diff --git a/src/main/java/net/oauth/jsontoken/crypto/AsciiStringSigner.java b/src/main/java/net/oauth/jsontoken/crypto/AsciiStringSigner.java index 45f7cbc..2b002b5 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/AsciiStringSigner.java +++ b/src/main/java/net/oauth/jsontoken/crypto/AsciiStringSigner.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; @@ -20,8 +19,8 @@ import org.apache.commons.codec.binary.StringUtils; /** - * A Signer that can sign Strings (as opposed to byte arrays), assuming - * that the String contains characters in the US-ASCII charset. + * A Signer that can sign Strings (as opposed to byte arrays), assuming that the String contains + * characters in the US-ASCII charset. */ public class AsciiStringSigner { @@ -29,6 +28,7 @@ public class AsciiStringSigner { /** * Public constructor. + * * @param signer {@link Signer} that can sign byte arrays. */ public AsciiStringSigner(Signer signer) { @@ -37,6 +37,7 @@ public AsciiStringSigner(Signer signer) { /** * Signs the given ASCII string. + * * @throws SignatureException when the signature cannot be generated. */ public byte[] sign(String source) throws SignatureException { diff --git a/src/main/java/net/oauth/jsontoken/crypto/AsciiStringVerifier.java b/src/main/java/net/oauth/jsontoken/crypto/AsciiStringVerifier.java index d2db9d5..1fb8c24 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/AsciiStringVerifier.java +++ b/src/main/java/net/oauth/jsontoken/crypto/AsciiStringVerifier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,17 +12,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; -import org.apache.commons.codec.binary.StringUtils; - import java.security.SignatureException; +import org.apache.commons.codec.binary.StringUtils; /** - * A Verifier that can verify Strings (as opposed to byte arrays), assuming - * that the String contains characters in the US-ASCII charset. + * A Verifier that can verify Strings (as opposed to byte arrays), assuming that the String contains + * characters in the US-ASCII charset. */ public class AsciiStringVerifier { @@ -39,6 +37,7 @@ public AsciiStringVerifier(Verifier verifier) { /** * Verifies a signature on an ASCII string. + * * @param source the source that was signed. * @param signature the signature on the source. * @throws SignatureException if the signature doesn't verify. diff --git a/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Signer.java b/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Signer.java index b81c404..336353c 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Signer.java +++ b/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Signer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,20 +12,16 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; - import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; -/** - * A signer that can sign byte arrays using HMAC-SHA256. - */ +/** A signer that can sign byte arrays using HMAC-SHA256. */ public class HmacSHA256Signer extends AbstractSigner { private static final String HMAC_SHA256_ALG = "HmacSHA256"; @@ -35,9 +31,10 @@ public class HmacSHA256Signer extends AbstractSigner { /** * Public constructor. + * * @param issuer the id of this signer, to be included in the envelope of the JSON token. * @param keyId the id of the key that will be included in the envelope. If null, will be omitted - * from the envelope. + * from the envelope. * @param keyBytes the actual key. * @throws InvalidKeyException if the key cannot be used as an HMAC key. */ @@ -48,10 +45,12 @@ public HmacSHA256Signer(String issuer, String keyId, byte[] keyBytes) throws Inv try { this.hmac = Mac.getInstance(HMAC_SHA256_ALG); } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("cannot use Hmac256Signer on system without HmacSHA256 alg", e); + throw new IllegalStateException( + "cannot use Hmac256Signer on system without HmacSHA256 alg", e); } - // just to make sure we catch invalid keys early, let's initialize the hmac and throw if something goes wrong + // just to make sure we catch invalid keys early, let's initialize the hmac and throw if + // something goes wrong hmac.init(signingKey); } @@ -65,7 +64,8 @@ public byte[] sign(byte[] source) { hmac.init(signingKey); } catch (InvalidKeyException e) { // this should not happen - we tested this in the constructor - throw new IllegalStateException("key somehow became invalid since calling the constructor", e); + throw new IllegalStateException( + "key somehow became invalid since calling the constructor", e); } return hmac.doFinal(source); } diff --git a/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Verifier.java b/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Verifier.java index 4209c03..4bcbe17 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Verifier.java +++ b/src/main/java/net/oauth/jsontoken/crypto/HmacSHA256Verifier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,23 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; import java.security.InvalidKeyException; import java.security.SignatureException; -import java.util.Arrays; -/** - * A {@link Verifier} that uses HMAC-SHA256 to verify symmetric-key signatures on byte arrays. - */ +/** A {@link Verifier} that uses HMAC-SHA256 to verify symmetric-key signatures on byte arrays. */ public class HmacSHA256Verifier implements Verifier { private final HmacSHA256Signer signer; /** * Public constructor. + * * @param verificationKey the HMAC verification key to be used for signature verification. * @throws InvalidKeyException if the verificationKey cannot be used as an HMAC key. */ @@ -49,14 +46,14 @@ public void verifySignature(byte[] source, byte[] signature) throws SignatureExc } /** - * Performs a byte-by-byte comparison of {@code first} and {@code second} parameters. This - * method will "NOT" short-circuit the comparison once it has detected a byte difference in - * order to defend against a "timing attack". + * Performs a byte-by-byte comparison of {@code first} and {@code second} parameters. This method + * will "NOT" short-circuit the comparison once it has detected a byte difference in order to + * defend against a "timing attack". * * @param first the first byte array used in the comparison * @param second the second byte array used in the comparison - * @return {@code true} if the {@code first} and {@code second} byte arrays are equal - * otherwise {@code false} + * @return {@code true} if the {@code first} and {@code second} byte arrays are equal otherwise + * {@code false} */ private boolean compareBytes(byte[] first, byte[] second) { if (first == null || second == null) { diff --git a/src/main/java/net/oauth/jsontoken/crypto/MagicRsaPublicKey.java b/src/main/java/net/oauth/jsontoken/crypto/MagicRsaPublicKey.java index 32ab0a3..968eacd 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/MagicRsaPublicKey.java +++ b/src/main/java/net/oauth/jsontoken/crypto/MagicRsaPublicKey.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,12 +12,9 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; -import org.apache.commons.codec.binary.Base64; - import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; @@ -25,6 +22,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.regex.Pattern; +import org.apache.commons.codec.binary.Base64; /** * Class that can parse "magic key" RSA public key representations, which are of the form @@ -36,15 +34,14 @@ public class MagicRsaPublicKey { /** * Public constructor. + * * @param magicKey the serialized key (of the form RSA.modulus.exponent). */ public MagicRsaPublicKey(String magicKey) { this.publicKey = parseKey(magicKey); } - /** - * Returns the public key represented by the "magic" serialized key. - */ + /** Returns the public key represented by the "magic" serialized key. */ public PublicKey getKey() { return publicKey; } diff --git a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA1Verifier.java b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA1Verifier.java index 274f32d..5f9d379 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA1Verifier.java +++ b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA1Verifier.java @@ -13,6 +13,7 @@ public class RsaSHA1Verifier implements Verifier { /** * Public Constructor. + * * @param verificationKey the key used to verify the signature. */ public RsaSHA1Verifier(PublicKey verificationKey) { diff --git a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Signer.java b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Signer.java index 5ae8f08..57c021b 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Signer.java +++ b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Signer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; @@ -23,9 +22,7 @@ import java.security.SignatureException; import java.security.interfaces.RSAPrivateKey; -/** - * Signer that can sign byte arrays using RSA and SHA-256. - */ +/** Signer that can sign byte arrays using RSA and SHA-256. */ public class RsaSHA256Signer extends AbstractSigner { private final Signature signature; @@ -33,12 +30,15 @@ public class RsaSHA256Signer extends AbstractSigner { /** * Public constructor. + * * @param issuer The id of this signer, to be included in the JSON Token's envelope. - * @param keyId The id of the key used by this signer, to be included in the JSON Token's envelope. + * @param keyId The id of the key used by this signer, to be included in the JSON Token's + * envelope. * @param key the private key to be used for signing. * @throws InvalidKeyException if the key is unsuitable for RSA signing. */ - public RsaSHA256Signer(String issuer, String keyId, RSAPrivateKey key) throws InvalidKeyException { + public RsaSHA256Signer(String issuer, String keyId, RSAPrivateKey key) + throws InvalidKeyException { super(issuer, keyId); this.signingKey = key; @@ -47,7 +47,8 @@ public RsaSHA256Signer(String issuer, String keyId, RSAPrivateKey key) throws In this.signature = Signature.getInstance("SHA256withRSA"); this.signature.initSign(signingKey); } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("platform is missing RSAwithSHA256 signature alg, or key is invalid", e); + throw new IllegalStateException( + "platform is missing RSAwithSHA256 signature alg, or key is invalid", e); } } diff --git a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Verifier.java b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Verifier.java index 96c37cf..0acd566 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Verifier.java +++ b/src/main/java/net/oauth/jsontoken/crypto/RsaSHA256Verifier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; @@ -22,9 +21,7 @@ import java.security.Signature; import java.security.SignatureException; -/** - * A verifier that can verify signatures on byte arrays using RSA and SHA-256. - */ +/** A verifier that can verify signatures on byte arrays using RSA and SHA-256. */ public class RsaSHA256Verifier implements Verifier { private final PublicKey verificationKey; @@ -32,6 +29,7 @@ public class RsaSHA256Verifier implements Verifier { /** * Public Constructor. + * * @param verificationKey the key used to verify the signature. */ public RsaSHA256Verifier(PublicKey verificationKey) { diff --git a/src/main/java/net/oauth/jsontoken/crypto/SignatureAlgorithm.java b/src/main/java/net/oauth/jsontoken/crypto/SignatureAlgorithm.java index 1a24e1e..4cc77be 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/SignatureAlgorithm.java +++ b/src/main/java/net/oauth/jsontoken/crypto/SignatureAlgorithm.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,13 +12,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; -/** - * Enum of the signature algorithms supported by this package. - */ +/** Enum of the signature algorithms supported by this package. */ public enum SignatureAlgorithm { HS256("SHA256"), HS1("SHA1"), @@ -31,26 +28,22 @@ private SignatureAlgorithm(String hashAlg) { this.hashAlg = hashAlg; } - /** - * What the signature algorithm is named in the "alg" parameter in a JSON Token's envelope. - */ + /** What the signature algorithm is named in the "alg" parameter in a JSON Token's envelope. */ public String getNameForJson() { return name(); } /** - * Returns the hash algorithm that should be used when hashing data. When large pieces - * of data are to be included in a JSON Token's payload, it sometimes might make sense - * to include the hash of the data instead. If an issuer wants to do that, they should - * use this hash algorithm to hash the data. + * Returns the hash algorithm that should be used when hashing data. When large pieces of data are + * to be included in a JSON Token's payload, it sometimes might make sense to include the hash of + * the data instead. If an issuer wants to do that, they should use this hash algorithm to hash + * the data. */ public String getHashAlgorithm() { return hashAlg; } - /** - * Given the name of the algorithm in the envelope, returns the corresponding enum instance. - */ + /** Given the name of the algorithm in the envelope, returns the corresponding enum instance. */ public static SignatureAlgorithm getFromJsonName(String name) { return SignatureAlgorithm.valueOf(name); } diff --git a/src/main/java/net/oauth/jsontoken/crypto/Signer.java b/src/main/java/net/oauth/jsontoken/crypto/Signer.java index 94c5bb6..0e9f3c0 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/Signer.java +++ b/src/main/java/net/oauth/jsontoken/crypto/Signer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,45 +12,41 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; import java.security.SignatureException; /** - * Interface that a token signer has to implement. A Signer represents a specific - * signing key, and knows the id of this key. (The key id is an identifier by - * which a verifier can find this particular key. It does not need to be - * globally unique, but must be unique for per token issuer.) A Signer also - * belongs to a certain issuer: An issuer is the entity that issues tokens, and - * uses signers to sign them. + * Interface that a token signer has to implement. A Signer represents a specific signing key, and + * knows the id of this key. (The key id is an identifier by which a verifier can find this + * particular key. It does not need to be globally unique, but must be unique for per token issuer.) + * A Signer also belongs to a certain issuer: An issuer is the entity that issues tokens, and uses + * signers to sign them. */ public interface Signer { /** - * Returns the id of this signing key. If not null, this will be included in - * the JSON Token's envelope as the key_id parameter. + * Returns the id of this signing key. If not null, this will be included in the JSON Token's + * envelope as the key_id parameter. */ - public String getKeyId(); + String getKeyId(); /** - * The issuer of the JSON Token. Each signer belongs to an issuer, and an issuer - * may have one or more signers, each with a distinct key id. + * The issuer of the JSON Token. Each signer belongs to an issuer, and an issuer may have one or + * more signers, each with a distinct key id. */ - public String getIssuer(); + String getIssuer(); - /** - * Returns the signature algorithm used by this signer. - */ - public SignatureAlgorithm getSignatureAlgorithm(); + /** Returns the signature algorithm used by this signer. */ + SignatureAlgorithm getSignatureAlgorithm(); /** * Signs an array of bytes. + * * @param source The bytes that should be signed. * @return The signature on the bytes. * @throws SignatureException if the signer could not create the signature. */ - public byte[] sign(byte[] source) throws SignatureException; - + byte[] sign(byte[] source) throws SignatureException; } diff --git a/src/main/java/net/oauth/jsontoken/crypto/Verifier.java b/src/main/java/net/oauth/jsontoken/crypto/Verifier.java index ff1dbd7..259fbcc 100644 --- a/src/main/java/net/oauth/jsontoken/crypto/Verifier.java +++ b/src/main/java/net/oauth/jsontoken/crypto/Verifier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,23 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; import java.security.SignatureException; -/** - * Interface that a JSON Token verifier has to implement. - */ +/** Interface that a JSON Token verifier has to implement. */ public interface Verifier { /** * Verifies a signature on an array of bytes. + * * @param source The bytes that were signed. * @param signature The signature on the bytes. * @throws SignatureException If the signature doesn't match, or if some other error occurred. */ - public void verifySignature(byte[] source, byte[] signature) throws SignatureException; - + void verifySignature(byte[] source, byte[] signature) throws SignatureException; } diff --git a/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProvider.java b/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProvider.java index 12eb5df..a3ade30 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProvider.java +++ b/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProvider.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; @@ -23,29 +22,29 @@ import net.oauth.jsontoken.crypto.Verifier; /** - * The asynchronous counterpart of {@link VerifierProvider}. - * An interface that must be implemented by JSON Token verifiers. The {@link AsyncJsonTokenParser} - * uses {@link AsyncVerifierProvider} implementations to find verification keys asynchronously with - * which to verify the parsed JSON Token. There are different implementations of this interface for - * different types of verification keys. + * The asynchronous counterpart of {@link VerifierProvider}. An interface that must be implemented + * by JSON Token verifiers. The {@link AsyncJsonTokenParser} uses {@link AsyncVerifierProvider} + * implementations to find verification keys asynchronously with which to verify the parsed JSON + * Token. There are different implementations of this interface for different types of verification + * keys. * - * For symmetric signing keys, an implementation of {@link AsyncVerifierProvider} presumably will - * always look up the key in a local database. For public signing keys, the - * {@link AsyncVerifierProvider} implementation may fetch the public verification keys when needed - * from the public internet. + *

For symmetric signing keys, an implementation of {@link AsyncVerifierProvider} presumably will + * always look up the key in a local database. For public signing keys, the {@link + * AsyncVerifierProvider} implementation may fetch the public verification keys when needed from the + * public internet. */ public interface AsyncVerifierProvider { /** - * Returns a {@link ListenableFuture}, which asynchronously returns a {@code List} - * that represents a certain verification key, given the key's id and its issuer. + * Returns a {@link ListenableFuture}, which asynchronously returns a {@code List} that + * represents a certain verification key, given the key's id and its issuer. + * * @param issuer the id of the issuer that's using the key. - * @param keyId the id of the key, if keyId mismatches, return a list of - * possible verification keys. + * @param keyId the id of the key, if keyId mismatches, return a list of possible verification + * keys. * @return a {@link ListenableFuture} object that asynchronously returns a {@code List} - * that represents the verification key. + * that represents the verification key. */ @Nonnull ListenableFuture> findVerifier(String issuer, String keyId); - } diff --git a/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProviders.java b/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProviders.java index 310535f..4d2c5eb 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProviders.java +++ b/src/main/java/net/oauth/jsontoken/discovery/AsyncVerifierProviders.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; @@ -21,19 +20,19 @@ import net.oauth.jsontoken.crypto.SignatureAlgorithm; /** - * The asynchronous counterpart of {@link VerifierProviders}. - * An interface that must be implemented by JSON Token verifiers. The {@link AsyncJsonTokenParser} - * uses the {@link AsyncVerifierProviders} implementation to locate verification keys. In - * particular, it will first look up the {@link AsyncVerifierProvider} for the signature algorithm - * used in the JSON Token and the ask the {@link AsyncVerifierProvider} to provide a future that - * will return a {@code List} to check the validity of the JSON Token. + * The asynchronous counterpart of {@link VerifierProviders}. An interface that must be implemented + * by JSON Token verifiers. The {@link AsyncJsonTokenParser} uses the {@link AsyncVerifierProviders} + * implementation to locate verification keys. In particular, it will first look up the {@link + * AsyncVerifierProvider} for the signature algorithm used in the JSON Token and the ask the {@link + * AsyncVerifierProvider} to provide a future that will return a {@code List} to check the + * validity of the JSON Token. */ public interface AsyncVerifierProviders { /** * @param alg the signature algorithm of the JSON Token. - * @return a {@link AsyncVerifierProvider} corresponding to a given signature algorithm - * that allows for asynchronous retrieval of a verification key. + * @return a {@link AsyncVerifierProvider} corresponding to a given signature algorithm that + * allows for asynchronous retrieval of a verification key. */ @Nullable AsyncVerifierProvider getVerifierProvider(SignatureAlgorithm alg); diff --git a/src/main/java/net/oauth/jsontoken/discovery/DefaultPublicKeyLocator.java b/src/main/java/net/oauth/jsontoken/discovery/DefaultPublicKeyLocator.java index 44e4dcc..4db99b8 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/DefaultPublicKeyLocator.java +++ b/src/main/java/net/oauth/jsontoken/discovery/DefaultPublicKeyLocator.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,27 +12,23 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import com.google.common.collect.Lists; - -import net.oauth.jsontoken.crypto.RsaSHA256Verifier; -import net.oauth.jsontoken.crypto.Verifier; - import java.net.URI; import java.util.List; +import net.oauth.jsontoken.crypto.RsaSHA256Verifier; +import net.oauth.jsontoken.crypto.Verifier; /** - * Default strategy for locating public verification keys. Unlike secret (symmetric) - * verification keys, public verification keys can be published by token issuers - * at URLs called "server descriptors". + * Default strategy for locating public verification keys. Unlike secret (symmetric) verification + * keys, public verification keys can be published by token issuers at URLs called "server + * descriptors". * - * The default strategy to find a public verification key consists of first mapping - * an issuer id to a server descriptor, and then fetching the ServerInfo document from - * the server descriptor URL. Finally, the key is looked up int the ServerInfo document - * by key id. + *

The default strategy to find a public verification key consists of first mapping an issuer id + * to a server descriptor, and then fetching the ServerInfo document from the server descriptor URL. + * Finally, the key is looked up int the ServerInfo document by key id. */ public class DefaultPublicKeyLocator implements VerifierProvider { @@ -42,13 +38,13 @@ public class DefaultPublicKeyLocator implements VerifierProvider { /** * Public constructor. * - * @param descriptorProvider A {@link ServerDescriptorProvider} that maps - * issuer ids to server descriptors (URLs). - * @param resolver A {@link ServerInfoResolver}, i.e., an object that can fetch - * and parse a server info document, given a server descriptor. + * @param descriptorProvider A {@link ServerDescriptorProvider} that maps issuer ids to server + * descriptors (URLs). + * @param resolver A {@link ServerInfoResolver}, i.e., an object that can fetch and parse a server + * info document, given a server descriptor. */ - public DefaultPublicKeyLocator(ServerDescriptorProvider descriptorProvider, - ServerInfoResolver resolver) { + public DefaultPublicKeyLocator( + ServerDescriptorProvider descriptorProvider, ServerInfoResolver resolver) { this.descriptorProvider = descriptorProvider; this.descriptorResolver = resolver; } @@ -60,8 +56,9 @@ public DefaultPublicKeyLocator(ServerDescriptorProvider descriptorProvider, @Override public List findVerifier(String issuer, String keyId) { URI serverDescriptor = descriptorProvider.getServerDescriptor(issuer); - Verifier rsaVerifier = - new RsaSHA256Verifier(descriptorResolver.resolve(serverDescriptor).getVerificationKey(keyId)); + Verifier rsaVerifier = + new RsaSHA256Verifier( + descriptorResolver.resolve(serverDescriptor).getVerificationKey(keyId)); return Lists.newArrayList(rsaVerifier); } } diff --git a/src/main/java/net/oauth/jsontoken/discovery/IdentityServerDescriptorProvider.java b/src/main/java/net/oauth/jsontoken/discovery/IdentityServerDescriptorProvider.java index 236b8e6..8f6ef5a 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/IdentityServerDescriptorProvider.java +++ b/src/main/java/net/oauth/jsontoken/discovery/IdentityServerDescriptorProvider.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,21 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import java.net.URI; /** - * A {@link ServerDescriptorProvider} that returns the issuer id as the server - * descriptor. If a JSON Token issuer uses their own server descriptor as their - * issuer id, then the JSON Token verifier would use this implementation of - * {@link ServerDescriptorProvider} with the {@link DefaultPublicKeyLocator}. + * A {@link ServerDescriptorProvider} that returns the issuer id as the server descriptor. If a JSON + * Token issuer uses their own server descriptor as their issuer id, then the JSON Token verifier + * would use this implementation of {@link ServerDescriptorProvider} with the {@link + * DefaultPublicKeyLocator}. * - * For example, some OAuth Servers might use their Client's server descriptors - * as client_ids, and then use this implementation of {@link ServerDescriptorProvider} - * with the {@link DefaultPublicKeyLocator}. + *

For example, some OAuth Servers might use their Client's server descriptors as client_ids, and + * then use this implementation of {@link ServerDescriptorProvider} with the {@link + * DefaultPublicKeyLocator}. */ public class IdentityServerDescriptorProvider implements ServerDescriptorProvider { diff --git a/src/main/java/net/oauth/jsontoken/discovery/JsonServerInfo.java b/src/main/java/net/oauth/jsontoken/discovery/JsonServerInfo.java index 1e5c91c..b94021a 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/JsonServerInfo.java +++ b/src/main/java/net/oauth/jsontoken/discovery/JsonServerInfo.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,24 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; - -import net.oauth.jsontoken.crypto.MagicRsaPublicKey; - import java.security.PublicKey; import java.util.Map; +import net.oauth.jsontoken.crypto.MagicRsaPublicKey; /** - * Implementation of the {@link ServerInfo} interface that assumes the - * server info document is in JSON format. It can parse such a JSON-formatted - * server info document and exposes its contents through the requisite - * methods of the {@link ServerInfo} interface. + * Implementation of the {@link ServerInfo} interface that assumes the server info document is in + * JSON format. It can parse such a JSON-formatted server info document and exposes its contents + * through the requisite methods of the {@link ServerInfo} interface. */ public class JsonServerInfo implements ServerInfo { @@ -37,8 +33,8 @@ public class JsonServerInfo implements ServerInfo { private final Map verificationKeys = Maps.newHashMap(); /** - * Parses a JSON-formatted server info document and returns it as a - * {@link JsonServerInfo} object. + * Parses a JSON-formatted server info document and returns it as a {@link JsonServerInfo} object. + * * @param json the contents of the JSON-formatted server info document. */ public static JsonServerInfo getDocument(String json) { diff --git a/src/main/java/net/oauth/jsontoken/discovery/ServerDescriptorProvider.java b/src/main/java/net/oauth/jsontoken/discovery/ServerDescriptorProvider.java index fc1df60..b596f85 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/ServerDescriptorProvider.java +++ b/src/main/java/net/oauth/jsontoken/discovery/ServerDescriptorProvider.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,25 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import java.net.URI; /** - * Interface that a JSON Token verifier can implement to help - * with locating public verification keys. If a JSON Token verifier - * wants to take advantage of the {@link DefaultPublicKeyLocator} implementation, - * it needs to provide an implementation of this interface to map issuer ids - * to server descriptors. Server descriptors are URLs that resolve to server - * info documents (which, among other things, contain public verification keys). + * Interface that a JSON Token verifier can implement to help with locating public verification + * keys. If a JSON Token verifier wants to take advantage of the {@link DefaultPublicKeyLocator} + * implementation, it needs to provide an implementation of this interface to map issuer ids to + * server descriptors. Server descriptors are URLs that resolve to server info documents (which, + * among other things, contain public verification keys). */ public interface ServerDescriptorProvider { - /** - * Returns the server descriptor, given the issuer id present in a JSON Token. - */ - public URI getServerDescriptor(String issuer); - + /** Returns the server descriptor, given the issuer id present in a JSON Token. */ + URI getServerDescriptor(String issuer); } diff --git a/src/main/java/net/oauth/jsontoken/discovery/ServerInfo.java b/src/main/java/net/oauth/jsontoken/discovery/ServerInfo.java index e007eb8..42442a9 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/ServerInfo.java +++ b/src/main/java/net/oauth/jsontoken/discovery/ServerInfo.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,23 +12,18 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import java.security.PublicKey; /** - * Represents the document located at a server's "server descriptor" URL. - * Such a "server info" document contains, among other things, the public - * verification keys that can be used to verify JSON Tokens issued by this - * server. + * Represents the document located at a server's "server descriptor" URL. Such a "server info" + * document contains, among other things, the public verification keys that can be used to verify + * JSON Tokens issued by this server. */ public interface ServerInfo { - /** - * Returns the verification key with the given key id. - */ - public PublicKey getVerificationKey(String keyId); - + /** Returns the verification key with the given key id. */ + PublicKey getVerificationKey(String keyId); } diff --git a/src/main/java/net/oauth/jsontoken/discovery/ServerInfoResolver.java b/src/main/java/net/oauth/jsontoken/discovery/ServerInfoResolver.java index dbe8a34..52069ec 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/ServerInfoResolver.java +++ b/src/main/java/net/oauth/jsontoken/discovery/ServerInfoResolver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,28 +12,25 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; import java.net.URI; /** - * Interface that a JSON Token verifier can implement to help - * with locating public verification keys. If a JSON Token verifier - * wants to take advantage of the {@link DefaultPublicKeyLocator} implementation, - * it needs to provide an implementation of this interface to fetch and parse - * server info documents. The implementation should if possible recognize - * different encodings of the server info document (e.g., JSON and XML). + * Interface that a JSON Token verifier can implement to help with locating public verification + * keys. If a JSON Token verifier wants to take advantage of the {@link DefaultPublicKeyLocator} + * implementation, it needs to provide an implementation of this interface to fetch and parse server + * info documents. The implementation should if possible recognize different encodings of the server + * info document (e.g., JSON and XML). */ public interface ServerInfoResolver { /** * Fetches and parses a server info document. - * @param serverDescriptor the URL from which the server info document - * should be fetched. + * + * @param serverDescriptor the URL from which the server info document should be fetched. * @return an object representing the server info document. */ - public ServerInfo resolve(URI serverDescriptor); - + ServerInfo resolve(URI serverDescriptor); } diff --git a/src/main/java/net/oauth/jsontoken/discovery/UrlBasedVerifierProvider.java b/src/main/java/net/oauth/jsontoken/discovery/UrlBasedVerifierProvider.java index 825e7b3..7e332a4 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/UrlBasedVerifierProvider.java +++ b/src/main/java/net/oauth/jsontoken/discovery/UrlBasedVerifierProvider.java @@ -4,12 +4,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; - -import net.oauth.jsontoken.crypto.RsaSHA256Verifier; -import net.oauth.jsontoken.crypto.Verifier; - -import org.apache.commons.codec.binary.Base64; - import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -23,10 +17,12 @@ import java.security.cert.X509Certificate; import java.util.List; import java.util.Map; +import net.oauth.jsontoken.crypto.RsaSHA256Verifier; +import net.oauth.jsontoken.crypto.Verifier; +import org.apache.commons.codec.binary.Base64; /** - * Simple certificates finder by fetching from URL. Expects simple json - * format, for example: + * Simple certificates finder by fetching from URL. Expects simple json format, for example: * {"keyid":"x509 certificate in Pem format", "keyid2":"x509 certificate in Pem format"..} */ public class UrlBasedVerifierProvider implements VerifierProvider { @@ -44,7 +40,7 @@ public List findVerifier(String issuer, String keyId) { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { - + InputStreamReader in = new InputStreamReader((InputStream) connection.getContent()); BufferedReader buff = new BufferedReader(in); StringBuffer content = new StringBuffer(); @@ -53,11 +49,11 @@ public List findVerifier(String issuer, String keyId) { line = buff.readLine(); content.append(line + "\n"); } while (line != null); - + JsonParser parser = new JsonParser(); JsonObject jsonObject = parser.parse(content.toString()).getAsJsonObject(); List verifiers = Lists.newArrayList(); - + for (Map.Entry cert : jsonObject.entrySet()) { String x509PemCertString = cert.getValue().getAsString(); // Parse pem format @@ -72,11 +68,11 @@ public List findVerifier(String issuer, String keyId) { // parse x509 byte[] certBytes = Base64.decodeBase64(x509CertString); CertificateFactory factory = CertificateFactory.getInstance("X509"); - X509Certificate x509Cert = - (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes)); + X509Certificate x509Cert = + (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes)); verifiers.add(new RsaSHA256Verifier(x509Cert.getPublicKey())); } - return verifiers; + return verifiers; } else { return null; } @@ -88,4 +84,4 @@ public List findVerifier(String issuer, String keyId) { return null; } } -} \ No newline at end of file +} diff --git a/src/main/java/net/oauth/jsontoken/discovery/VerifierProvider.java b/src/main/java/net/oauth/jsontoken/discovery/VerifierProvider.java index 398c52c..9bfbb09 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/VerifierProvider.java +++ b/src/main/java/net/oauth/jsontoken/discovery/VerifierProvider.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; @@ -21,25 +20,25 @@ import net.oauth.jsontoken.crypto.Verifier; /** - * An interface that must be implemented by JSON Token verifiers. The {@link JsonTokenParser} - * uses {@link VerifierProvider} implementations to find verification keys with which to - * verify the parsed JSON Token. There are different implementations of this interface for - * different types of verification keys. + * An interface that must be implemented by JSON Token verifiers. The {@link JsonTokenParser} uses + * {@link VerifierProvider} implementations to find verification keys with which to verify the + * parsed JSON Token. There are different implementations of this interface for different types of + * verification keys. * - * For symmetric signing keys, an implementation of {@link VerifierProvider} presumably will + *

For symmetric signing keys, an implementation of {@link VerifierProvider} presumably will * always look up the key in a local database. For public signing keys, the {@link VerifierProvider} * implementation may fetch the public verification keys when needed from the public internet. */ public interface VerifierProvider { /** - * Returns the {@code List} that represents a certain verification - * key, given the key's id and its issuer. + * Returns the {@code List} that represents a certain verification key, given the key's + * id and its issuer. + * * @param issuer the id of the issuer that's using the key. - * @param keyId the id of the key, if keyId mismatches, return a list of - * possible verification keys. + * @param keyId the id of the key, if keyId mismatches, return a list of possible verification + * keys. * @return a {@code List} object that represents the verification key. */ List findVerifier(String issuer, String keyId); - } diff --git a/src/main/java/net/oauth/jsontoken/discovery/VerifierProviders.java b/src/main/java/net/oauth/jsontoken/discovery/VerifierProviders.java index c1ee772..ee10765 100644 --- a/src/main/java/net/oauth/jsontoken/discovery/VerifierProviders.java +++ b/src/main/java/net/oauth/jsontoken/discovery/VerifierProviders.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.discovery; @@ -23,29 +22,24 @@ import net.oauth.jsontoken.crypto.SignatureAlgorithm; /** - * A collection of {@link VerifierProvider}s, one for each signature algorithm. - * The {@link JsonTokenParser} uses a {@link VerifierProviders} instance to locate - * verification keys. In particular, it will first look up the {@link VerifierProvider} - * for the signature algorithm used in the JSON Token (different signature methods - * will use different ways to look up verification keys - for example, symmetric keys - * will always be pre-negotiated and looked up in a local database, while public - * verification keys can be looked up on demand), and the ask the {@link VerifierProvider} - * to provide a {@code List} to check the validity of the JSON Token. + * A collection of {@link VerifierProvider}s, one for each signature algorithm. The {@link + * JsonTokenParser} uses a {@link VerifierProviders} instance to locate verification keys. In + * particular, it will first look up the {@link VerifierProvider} for the signature algorithm used + * in the JSON Token (different signature methods will use different ways to look up verification + * keys - for example, symmetric keys will always be pre-negotiated and looked up in a local + * database, while public verification keys can be looked up on demand), and the ask the {@link + * VerifierProvider} to provide a {@code List} to check the validity of the JSON Token. */ public class VerifierProviders { private final Map map = Maps.newHashMap(); - /** - * Sets a new {@link VerifierProvider} for the given {@link SignatureAlgorithm}. - */ + /** Sets a new {@link VerifierProvider} for the given {@link SignatureAlgorithm}. */ public void setVerifierProvider(SignatureAlgorithm alg, VerifierProvider provider) { map.put(alg, provider); } - /** - * Returns the {@link VerifierProvider} for the given {@link SignatureAlgorithm}. - */ + /** Returns the {@link VerifierProvider} for the given {@link SignatureAlgorithm}. */ @Nullable public VerifierProvider getVerifierProvider(SignatureAlgorithm alg) { return map.get(alg); diff --git a/src/main/java/net/oauth/jsontoken/exceptions/ErrorCode.java b/src/main/java/net/oauth/jsontoken/exceptions/ErrorCode.java index 4a0c1e9..ffcb6b5 100644 --- a/src/main/java/net/oauth/jsontoken/exceptions/ErrorCode.java +++ b/src/main/java/net/oauth/jsontoken/exceptions/ErrorCode.java @@ -2,51 +2,33 @@ public enum ErrorCode { - /** - * The header is missing required parameters. - */ - BAD_HEADER, - - /** - * Signature failed verification. - */ - BAD_SIGNATURE, - - /** - * IAT is after EXP or IAT is in the future - */ - BAD_TIME_RANGE, - - /** - * IAT and EXP are both in the past. - */ - EXPIRED_TOKEN, - - /** - * The token is in an illegal state because of incorrect use of the library. - * If this error code appears, immediately rethrow as an {@link IllegalStateException}. - */ - ILLEGAL_STATE, - - /** - * Token string is corrupted and/or does not contain three components. - */ - MALFORMED_TOKEN_STRING, - - /** - * There are no verifiers available for a given issuer and keyId. - */ - NO_VERIFIER, - - /** - * Generic catch-all for exceptions with scenarios that are not pre-defined. - */ - UNKNOWN, - - /** - * The signature algorithm is not supported or is unknown. - */ - UNSUPPORTED_ALGORITHM + /** The header is missing required parameters. */ + BAD_HEADER, -} + /** Signature failed verification. */ + BAD_SIGNATURE, + + /** IAT is after EXP or IAT is in the future */ + BAD_TIME_RANGE, + + /** IAT and EXP are both in the past. */ + EXPIRED_TOKEN, + + /** + * The token is in an illegal state because of incorrect use of the library. If this error code + * appears, immediately rethrow as an {@link IllegalStateException}. + */ + ILLEGAL_STATE, + /** Token string is corrupted and/or does not contain three components. */ + MALFORMED_TOKEN_STRING, + + /** There are no verifiers available for a given issuer and keyId. */ + NO_VERIFIER, + + /** Generic catch-all for exceptions with scenarios that are not pre-defined. */ + UNKNOWN, + + /** The signature algorithm is not supported or is unknown. */ + UNSUPPORTED_ALGORITHM +} diff --git a/src/main/java/net/oauth/jsontoken/exceptions/InvalidJsonTokenException.java b/src/main/java/net/oauth/jsontoken/exceptions/InvalidJsonTokenException.java index 6c960ae..891e715 100644 --- a/src/main/java/net/oauth/jsontoken/exceptions/InvalidJsonTokenException.java +++ b/src/main/java/net/oauth/jsontoken/exceptions/InvalidJsonTokenException.java @@ -20,5 +20,4 @@ public InvalidJsonTokenException(ErrorCode errorCode, Throwable cause) { public ErrorCode getErrorCode() { return errorCode; } - } diff --git a/src/main/java/net/oauth/signatures/NonceChecker.java b/src/main/java/net/oauth/signatures/NonceChecker.java index 8490e7d..df357dc 100644 --- a/src/main/java/net/oauth/signatures/NonceChecker.java +++ b/src/main/java/net/oauth/signatures/NonceChecker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,23 +12,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; -import net.oauth.jsontoken.JsonToken; - import java.security.SignatureException; +import net.oauth.jsontoken.JsonToken; -/** - * Receivers of Json Tokens may implement this interface. - */ +/** Receivers of Json Tokens may implement this interface. */ public interface NonceChecker { /** - * Throws if the nonce in the {@link JsonToken} has previously been - * used by the same token issuer. + * Throws if the nonce in the {@link JsonToken} has previously been used by the same token issuer. */ - public void checkNonce(String nonce) throws SignatureException; - + void checkNonce(String nonce) throws SignatureException; } diff --git a/src/main/java/net/oauth/signatures/SignedJsonAssertionAudienceChecker.java b/src/main/java/net/oauth/signatures/SignedJsonAssertionAudienceChecker.java index b5beab0..3143d6f 100644 --- a/src/main/java/net/oauth/signatures/SignedJsonAssertionAudienceChecker.java +++ b/src/main/java/net/oauth/signatures/SignedJsonAssertionAudienceChecker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,22 +12,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; import com.google.common.base.Preconditions; import com.google.gson.JsonObject; - import java.net.URI; import java.security.SignatureException; - import net.oauth.jsontoken.Checker; import net.oauth.jsontoken.JsonToken; -/** - * Audience checker for signed Json Assertion. - */ +/** Audience checker for signed Json Assertion. */ public class SignedJsonAssertionAudienceChecker implements Checker { // URI that the client is accessing, as seen by the server @@ -35,24 +30,24 @@ public class SignedJsonAssertionAudienceChecker implements Checker { /** * Public constructor. + * * @param uri the URI against which the signed OAuth token was exercised. */ public SignedJsonAssertionAudienceChecker(String uri) { this.tokenEndpointUri = uri; } - /** - * @see net.oauth.jsontoken.Checker#check(com.google.gson.JsonObject) - */ + /** @see net.oauth.jsontoken.Checker#check(com.google.gson.JsonObject) */ @Override public void check(JsonObject payload) throws SignatureException { - checkUri(tokenEndpointUri, + checkUri( + tokenEndpointUri, Preconditions.checkNotNull( - payload.get(JsonToken.AUDIENCE).getAsString(), - "Audience cannot be null!")); + payload.get(JsonToken.AUDIENCE).getAsString(), "Audience cannot be null!")); } - private static void checkUri(String ourUriString, String tokenUriString) throws SignatureException { + private static void checkUri(String ourUriString, String tokenUriString) + throws SignatureException { URI ourUri = URI.create(ourUriString); URI tokenUri = URI.create(tokenUriString); @@ -61,7 +56,8 @@ private static void checkUri(String ourUriString, String tokenUriString) throws } if (!ourUri.getAuthority().equalsIgnoreCase(tokenUri.getAuthority())) { - throw new SignatureException("authority in token URI (" + tokenUri.getAuthority() + ") is wrong"); + throw new SignatureException( + "authority in token URI (" + tokenUri.getAuthority() + ") is wrong"); } } } diff --git a/src/main/java/net/oauth/signatures/SignedJsonAssertionToken.java b/src/main/java/net/oauth/signatures/SignedJsonAssertionToken.java index 005aa68..b3285f5 100644 --- a/src/main/java/net/oauth/signatures/SignedJsonAssertionToken.java +++ b/src/main/java/net/oauth/signatures/SignedJsonAssertionToken.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,37 +12,30 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; +import com.google.gson.JsonPrimitive; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.SignatureException; - import net.oauth.jsontoken.Clock; import net.oauth.jsontoken.JsonToken; import net.oauth.jsontoken.crypto.Signer; -import org.joda.time.Duration; - -import com.google.common.base.Preconditions; -import com.google.gson.JsonPrimitive; -/** - * A signed Json Assertion - */ +/** A signed Json Assertion */ public class SignedJsonAssertionToken extends JsonToken { - + public static final String JWT = "jwt"; - + public static final String GRANT_TYPE = "grant_type"; public static final String GRANT_TYPE_VALUE = "http://oauth.net/grant_type/jwt/1.0/bearer"; - + // addition JSON token payload fields for signed json assertion public static final String SUBJECT = "subject"; public static final String SCOPE = "scope"; public static final String NONCE = "nonce"; - + public SignedJsonAssertionToken(Signer signer, Clock clock) { super(signer, clock); } @@ -50,7 +43,7 @@ public SignedJsonAssertionToken(Signer signer, Clock clock) { public SignedJsonAssertionToken(Signer signer) { super(signer); } - + public SignedJsonAssertionToken(JsonToken token) { super(token.getPayloadAsJsonObject()); } @@ -63,12 +56,12 @@ public String getSubject() { public void setSubject(String m) { setParam(SUBJECT, m); } - + public String getScope() { JsonPrimitive scopeJson = getParamAsPrimitive(SCOPE); return scopeJson == null ? null : scopeJson.getAsString(); } - + public void setScope(String scope) { setParam(SCOPE, scope); } @@ -81,7 +74,7 @@ public String getNonce() { public void setNonce(String n) { setParam(NONCE, n); } - + public String getJsonAssertionPostBody() throws SignatureException { StringBuffer buffer = new StringBuffer(); buffer.append(GRANT_TYPE).append("=").append(GRANT_TYPE_VALUE); @@ -98,14 +91,14 @@ public String getJsonAssertionPostBody() throws SignatureException { public String serializeAndSign() throws SignatureException { return super.serializeAndSign(); } - + @Override protected String computeSignatureBaseString() { if (getIssuedAt() == null) { setIssuedAt(clock.now()); } if (getExpiration() == null) { - setExpiration(getIssuedAt().plus(Duration.standardMinutes(DEFAULT_LIFETIME_IN_MINS))); + setExpiration(getIssuedAt().plus(DEFAULT_LIFETIME)); } return super.computeSignatureBaseString(); } diff --git a/src/main/java/net/oauth/signatures/SignedJsonAssertionTokenParser.java b/src/main/java/net/oauth/signatures/SignedJsonAssertionTokenParser.java index 7999b02..7357ee4 100644 --- a/src/main/java/net/oauth/signatures/SignedJsonAssertionTokenParser.java +++ b/src/main/java/net/oauth/signatures/SignedJsonAssertionTokenParser.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,25 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; +import com.google.gson.JsonParseException; import java.security.SignatureException; - import javax.servlet.http.HttpServletRequest; - -import com.google.gson.JsonParseException; import net.oauth.jsontoken.Clock; import net.oauth.jsontoken.JsonTokenParser; import net.oauth.jsontoken.SystemClock; import net.oauth.jsontoken.discovery.VerifierProviders; -/** - * Parses signed json assertion. - */ -public class SignedJsonAssertionTokenParser { - +/** Parses signed json assertion. */ +public class SignedJsonAssertionTokenParser { + public static String EXPECTED_CONTENT_TYPE = "application/x-www-form-urlencoded"; private final VerifierProviders locators; @@ -40,10 +35,10 @@ public class SignedJsonAssertionTokenParser { /** * Public constructor. * - * @param locators an object that provides signature verifiers, based signature algorithm, - * as well as on the signer and key ids. - * @param nonceChecker An optional nonce checker. If not null, then the parser will - * call the nonce checker to make sure that the nonce has not been re-used. + * @param locators an object that provides signature verifiers, based signature algorithm, as well + * as on the signer and key ids. + * @param nonceChecker An optional nonce checker. If not null, then the parser will call the nonce + * checker to make sure that the nonce has not been re-used. */ public SignedJsonAssertionTokenParser(VerifierProviders locators, NonceChecker nonceChecker) { this(locators, nonceChecker, new SystemClock()); @@ -52,48 +47,50 @@ public SignedJsonAssertionTokenParser(VerifierProviders locators, NonceChecker n /** * Public constructor. * - * @param locators an object that provides signature verifiers, based signature algorithm, - * as well as on the signer and key ids. - * @param nonceChecker An optional nonce checker. If not null, then the parser will - * call the nonce checker to make sure that the nonce has not been re-used.JsonTokenParser - * @param clock a clock that has implemented the - * {@link Clock#isCurrentTimeInInterval(org.joda.time.Instant, org.joda.time.Duration)} method - * with a suitable slack to account for clock skew when checking token validity. + * @param locators an object that provides signature verifiers, based signature algorithm, as well + * as on the signer and key ids. + * @param nonceChecker An optional nonce checker. If not null, then the parser will call the nonce + * checker to make sure that the nonce has not been re-used.JsonTokenParser + * @param clock a clock that has implemented the {@link + * Clock#isCurrentTimeInInterval(java.time.Instant, java.time.Instant)} method with a suitable + * slack to account for clock skew when checking token validity. */ - public SignedJsonAssertionTokenParser(VerifierProviders locators, NonceChecker nonceChecker, - Clock clock) { + public SignedJsonAssertionTokenParser( + VerifierProviders locators, NonceChecker nonceChecker, Clock clock) { this.locators = locators; this.nonceChecker = nonceChecker; this.clock = clock; } - + /** * Extracts the Json assertion from the Http post body and then verifies it. + * * @param request the {@link HttpServletRequest} that contains the signed Json assertion in the - * post body. + * post body. * @return the Json assertion object. - * @throws SignatureException if the signature doesn't check out, or if authentication fails - * for other reason + * @throws SignatureException if the signature doesn't check out, or if authentication fails for + * other reason * @throws JsonParseException if the header or payload of tokenString is corrupted * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer */ public SignedJsonAssertionToken parseToken(HttpServletRequest request) throws SignatureException { if (!request.getContentType().startsWith(EXPECTED_CONTENT_TYPE)) { throw new SignatureException("bad content type: " + request.getContentType()); } - + String grantType = request.getParameter(SignedJsonAssertionToken.GRANT_TYPE); - if (grantType == null || !grantType.equalsIgnoreCase(SignedJsonAssertionToken.GRANT_TYPE_VALUE)) { + if (grantType == null + || !grantType.equalsIgnoreCase(SignedJsonAssertionToken.GRANT_TYPE_VALUE)) { throw new SignatureException("bad grant_type: " + grantType); } - + String assertion = request.getParameter(SignedJsonAssertionToken.JWT); if (assertion == null) { throw new SignatureException("empty json assertion"); } - + StringBuffer uri = request.getRequestURL(); if (request.getQueryString() != null) { uri.append("?"); @@ -104,21 +101,25 @@ public SignedJsonAssertionToken parseToken(HttpServletRequest request) throws Si } /** - * Parses the provided signed Json assertion, and then verifies it against the provided HTTP method - * and audience URI (in addition to checking the signature, and validity period). + * Parses the provided signed Json assertion, and then verifies it against the provided HTTP + * method and audience URI (in addition to checking the signature, and validity period). + * * @param jsonAssertion the signed Json assertion (in serialized form). * @param uri the URI against which the token was exercised. * @return the signed Json assertion token (deserialized) * @throws SignatureException if the signature (or anything else) doesn't check out * @throws JsonParseException if the header or payload of tokenString is corrupted * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer */ - public SignedJsonAssertionToken parseToken(String jsonAssertion, String uri) throws SignatureException { - JsonTokenParser parser = new JsonTokenParser(clock, locators, new SignedJsonAssertionAudienceChecker(uri)); + public SignedJsonAssertionToken parseToken(String jsonAssertion, String uri) + throws SignatureException { + JsonTokenParser parser = + new JsonTokenParser(clock, locators, new SignedJsonAssertionAudienceChecker(uri)); - SignedJsonAssertionToken token = new SignedJsonAssertionToken(parser.verifyAndDeserialize(jsonAssertion)); + SignedJsonAssertionToken token = + new SignedJsonAssertionToken(parser.verifyAndDeserialize(jsonAssertion)); if (nonceChecker != null) { nonceChecker.checkNonce(token.getNonce()); @@ -127,4 +128,3 @@ public SignedJsonAssertionToken parseToken(String jsonAssertion, String uri) thr return token; } } - diff --git a/src/main/java/net/oauth/signatures/SignedOAuthToken.java b/src/main/java/net/oauth/signatures/SignedOAuthToken.java index 3a7a971..3e89fb3 100644 --- a/src/main/java/net/oauth/signatures/SignedOAuthToken.java +++ b/src/main/java/net/oauth/signatures/SignedOAuthToken.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,25 +12,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; +import com.google.common.base.Preconditions; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; - -import org.apache.commons.codec.binary.Base64; - import net.oauth.jsontoken.Clock; import net.oauth.jsontoken.JsonToken; import net.oauth.jsontoken.crypto.Signer; +import org.apache.commons.codec.binary.Base64; -import com.google.common.base.Preconditions; - -/** - * A signed OAuth token. - */ +/** A signed OAuth token. */ public class SignedOAuthToken extends JsonToken { public static final String AUTH_METHOD = "Token"; @@ -41,7 +35,7 @@ public class SignedOAuthToken extends JsonToken { public static final String BODY_HASH = "body_hash"; public static final String OAUTH_TOKEN = "token"; public static final String NONCE = "nonce"; - + public SignedOAuthToken(Signer signer, Clock clock) { super(signer, clock); } @@ -49,7 +43,7 @@ public SignedOAuthToken(Signer signer, Clock clock) { public SignedOAuthToken(Signer signer) { super(signer); } - + public SignedOAuthToken(JsonToken token) { super(token.getPayloadAsJsonObject()); } @@ -120,4 +114,3 @@ private String getBodyHash(byte[] requestBody) { return Base64.encodeBase64URLSafeString(hash); } } - diff --git a/src/main/java/net/oauth/signatures/SignedOAuthTokenParser.java b/src/main/java/net/oauth/signatures/SignedOAuthTokenParser.java index fe54024..8b2b570 100644 --- a/src/main/java/net/oauth/signatures/SignedOAuthTokenParser.java +++ b/src/main/java/net/oauth/signatures/SignedOAuthTokenParser.java @@ -1,5 +1,4 @@ - -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,27 +12,21 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; +import com.google.gson.JsonParseException; import java.security.SignatureException; import java.util.Enumeration; - import javax.servlet.http.HttpServletRequest; - -import com.google.gson.JsonParseException; import net.oauth.jsontoken.Clock; import net.oauth.jsontoken.JsonTokenParser; import net.oauth.jsontoken.SystemClock; import net.oauth.jsontoken.discovery.VerifierProviders; - import org.apache.http.NameValuePair; import org.apache.http.message.BasicHeaderValueParser; -/** - * Parses signed OAuth tokens. - */ +/** Parses signed OAuth tokens. */ public class SignedOAuthTokenParser { private final VerifierProviders locators; @@ -43,10 +36,10 @@ public class SignedOAuthTokenParser { /** * Public constructor. * - * @param locators an object that provides signature verifiers, based signature algorithm, - * as well as on the signer and key ids. - * @param nonceChecker An optional nonce checker. If not null, then the parser will - * call the nonce checker to make sure that the nonce has not been re-used. + * @param locators an object that provides signature verifiers, based signature algorithm, as well + * as on the signer and key ids. + * @param nonceChecker An optional nonce checker. If not null, then the parser will call the nonce + * checker to make sure that the nonce has not been re-used. */ public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChecker) { this(locators, nonceChecker, new SystemClock()); @@ -55,15 +48,16 @@ public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChec /** * Public constructor. * - * @param locators an object that provides signature verifiers, based signature algorithm, - * as well as on the signer and key ids. - * @param nonceChecker An optional nonce checker. If not null, then the parser will - * call the nonce checker to make sure that the nonce has not been re-used. - * @param clock a clock that has implemented the - * {@link Clock#isCurrentTimeInInterval(org.joda.time.Instant, org.joda.time.Duration)} method - * with a suitable slack to account for clock skew when checking token validity. + * @param locators an object that provides signature verifiers, based signature algorithm, as well + * as on the signer and key ids. + * @param nonceChecker An optional nonce checker. If not null, then the parser will call the nonce + * checker to make sure that the nonce has not been re-used. + * @param clock a clock that has implemented the {@link + * Clock#isCurrentTimeInInterval(org.joda.time.Instant, org.joda.time.Duration)} method with a + * suitable slack to account for clock skew when checking token validity. */ - public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChecker, Clock clock) { + public SignedOAuthTokenParser( + VerifierProviders locators, NonceChecker nonceChecker, Clock clock) { this.locators = locators; this.nonceChecker = nonceChecker; this.clock = clock; @@ -71,15 +65,16 @@ public SignedOAuthTokenParser(VerifierProviders locators, NonceChecker nonceChec /** * Extracts the signed OAuth token from the Authorization header and then verifies it. + * * @param request the {@link HttpServletRequest} that contains the signed OAuth token in the - * Authorization header. + * Authorization header. * @return the signed OAuth token. - * @throws SignatureException if the signature doesn't check out, or if authentication fails - * for other reason (missing Authorization header, etc.). + * @throws SignatureException if the signature doesn't check out, or if authentication fails for + * other reason (missing Authorization header, etc.). * @throws JsonParseException if the header or payload of tokenString is corrupted * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer */ public SignedOAuthToken parseToken(HttpServletRequest request) throws SignatureException { @@ -87,10 +82,11 @@ public SignedOAuthToken parseToken(HttpServletRequest request) throws SignatureE String header = getAuthHeader(request); if (header == null) { - throw new SignatureException("missing Authorization header of type 'Token'"); + throw new SignatureException("missing Authorization header of type 'Token'"); } - String postFix = header.substring(0, SignedOAuthToken.AUTH_METHOD.length()); // read past "Token" + String postFix = + header.substring(0, SignedOAuthToken.AUTH_METHOD.length()); // read past "Token" NameValuePair nvp = BasicHeaderValueParser.parseNameValuePair(postFix.trim(), null); if (nvp == null) { @@ -120,6 +116,7 @@ public SignedOAuthToken parseToken(HttpServletRequest request) throws SignatureE /** * Parses the provided signed OAuth token, and then verifies it against the provided HTTP method * and audience URI (in addition to checking the signature, and validity period). + * * @param tokenString the signed OAuth token (in serialized form). * @param method the HTTP method that was used when the token was exercised. * @param uri the URI against which the token was exercised. @@ -127,11 +124,13 @@ public SignedOAuthToken parseToken(HttpServletRequest request) throws SignatureE * @throws SignatureException if the signature (or anything else) doesn't check out. * @throws JsonParseException if the header or payload of tokenString is corrupted * @throws IllegalArgumentException if the signature algorithm is not supported - * @throws IllegalStateException if tokenString is not a properly formatted JWT - * or if there is no valid verifier for the issuer + * @throws IllegalStateException if tokenString is not a properly formatted JWT or if there is no + * valid verifier for the issuer */ - public SignedOAuthToken parseToken(String tokenString, String method, String uri) throws SignatureException { - JsonTokenParser parser = new JsonTokenParser(clock, locators, new SignedTokenAudienceChecker(uri)); + public SignedOAuthToken parseToken(String tokenString, String method, String uri) + throws SignatureException { + JsonTokenParser parser = + new JsonTokenParser(clock, locators, new SignedTokenAudienceChecker(uri)); SignedOAuthToken token = new SignedOAuthToken(parser.verifyAndDeserialize(tokenString)); diff --git a/src/main/java/net/oauth/signatures/SignedTokenAudienceChecker.java b/src/main/java/net/oauth/signatures/SignedTokenAudienceChecker.java index 0e5be19..6a93e66 100644 --- a/src/main/java/net/oauth/signatures/SignedTokenAudienceChecker.java +++ b/src/main/java/net/oauth/signatures/SignedTokenAudienceChecker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,24 +12,21 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.gson.JsonObject; import java.net.URI; import java.security.SignatureException; - import net.oauth.jsontoken.Checker; import net.oauth.jsontoken.JsonToken; -import com.google.common.base.Objects; -import com.google.common.base.Preconditions; -import com.google.gson.JsonObject; - /** - * Audience checker for signed OAuth tokens. For such tokens, the audience in the token - * is the URL of the accessed resource, and has to match it exactly (save some case-insensitivities - * in the host name). + * Audience checker for signed OAuth tokens. For such tokens, the audience in the token is the URL + * of the accessed resource, and has to match it exactly (save some case-insensitivities in the host + * name). */ public class SignedTokenAudienceChecker implements Checker { @@ -38,24 +35,24 @@ public class SignedTokenAudienceChecker implements Checker { /** * Public constructor. + * * @param uri the URI against which the signed OAuth token was exercised. */ public SignedTokenAudienceChecker(String uri) { this.serverUri = uri; } - /** - * @see net.oauth.jsontoken.Checker#check(com.google.gson.JsonObject) - */ + /** @see net.oauth.jsontoken.Checker#check(com.google.gson.JsonObject) */ @Override public void check(JsonObject payload) throws SignatureException { - checkUri(serverUri, + checkUri( + serverUri, Preconditions.checkNotNull( - payload.get(JsonToken.AUDIENCE).getAsString(), - "Audience cannot be null!")); + payload.get(JsonToken.AUDIENCE).getAsString(), "Audience cannot be null!")); } - private static void checkUri(String ourUriString, String tokenUriString) throws SignatureException { + private static void checkUri(String ourUriString, String tokenUriString) + throws SignatureException { URI ourUri = URI.create(ourUriString); URI tokenUri = URI.create(tokenUriString); @@ -64,7 +61,8 @@ private static void checkUri(String ourUriString, String tokenUriString) throws } if (!ourUri.getAuthority().equalsIgnoreCase(tokenUri.getAuthority())) { - throw new SignatureException("authority in token URI (" + tokenUri.getAuthority() + ") is wrong"); + throw new SignatureException( + "authority in token URI (" + tokenUri.getAuthority() + ") is wrong"); } if (!Objects.equal(ourUri.getPath(), tokenUri.getPath())) { diff --git a/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java b/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java index 36aacd7..cbdfc30 100644 --- a/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java +++ b/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -20,19 +19,23 @@ import com.google.gson.JsonParseException; import java.security.SignatureException; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import net.oauth.jsontoken.crypto.HmacSHA256Signer; import net.oauth.jsontoken.exceptions.ErrorCode; -import org.joda.time.Duration; -import org.joda.time.Instant; public class AbstractJsonTokenParserTest extends JsonTokenTestBase { - private static final String TOKEN_STRING_ISSUER_NULL = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOm51bGwsImJhciI6MTUsImZvbyI6InNvbWUgdmFsdWUiLCJhdWQiOiJodHRwOi8vd3d3Lmdvb2dsZS5jb20iLCJpYXQiOjEyNzY2Njk3MjIsImV4cCI6MTI3NjY2OTcyM30.WPaa6PoLWPzNfnIBisBX9549kWeABSj9tXnwnPE4IJk"; + private static final String TOKEN_STRING_ISSUER_NULL = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOm51bGwsImJhciI6MTUsImZvbyI6InNvbWUgdmFsdWUiLCJhdWQiOiJodHRwOi8vd3d3Lmdvb2dsZS5jb20iLCJpYXQiOjEyNzY2Njk3MjIsImV4cCI6MTI3NjY2OTcyM30.WPaa6PoLWPzNfnIBisBX9549kWeABSj9tXnwnPE4IJk"; private static final String TOKEN_STRING_1PART = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ"; - private static final String TOKEN_STRING_2PARTS = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ"; - private static final String TOKEN_STRING_EMPTY_SIG = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ."; - private static final String TOKEN_STRING_CORRUPT_PAYLOAD = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3&&&&&nb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + private static final String TOKEN_STRING_2PARTS = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ"; + private static final String TOKEN_STRING_EMPTY_SIG = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ."; + private static final String TOKEN_STRING_CORRUPT_PAYLOAD = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3&&&&&nb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; public void testVerify_valid() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); @@ -42,20 +45,19 @@ public void testVerify_valid() throws Exception { public void testVerify_issuedAtAfterExpiration() throws Exception { Instant issuedAt = clock.now(); - Instant expiration = issuedAt.minus(Duration.standardSeconds(1)); + Instant expiration = issuedAt.minus(Duration.ofSeconds(1)); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.BAD_TIME_RANGE, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_issuedAtSkew() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); - Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); + Instant issuedAt = clock.now().plus(SKEW.minus(Duration.ofSeconds(1))); + Instant expiration = issuedAt.plus(Duration.ofSeconds(1)); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); @@ -63,20 +65,19 @@ public void testVerify_issuedAtSkew() throws Exception { } public void testVerify_issuedAtTooMuchSkew() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.plus(Duration.standardSeconds(1))); - Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); + Instant issuedAt = clock.now().plus(SKEW.plus(Duration.ofSeconds(1))); + Instant expiration = issuedAt.plus(Duration.ofSeconds(1)); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.BAD_TIME_RANGE, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_issuedAtNull() throws Exception { - Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); + Instant expiration = clock.now().minus(SKEW.minus(Duration.ofSeconds(1))); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); @@ -84,8 +85,8 @@ public void testVerify_issuedAtNull() throws Exception { } public void testVerify_expirationSkew() throws Exception { - Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); - Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); + Instant expiration = clock.now().minus(SKEW.minus(Duration.ofSeconds(1))); + Instant issuedAt = expiration.minus(Duration.ofSeconds(1)); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); @@ -93,20 +94,19 @@ public void testVerify_expirationSkew() throws Exception { } public void testVerify_expirationTooMuchSkew() throws Exception { - Instant expiration = clock.now().minus(SKEW.plus(Duration.standardSeconds(1))); - Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); + Instant expiration = clock.now().minus(SKEW.plus(Duration.ofSeconds(1))); + Instant issuedAt = expiration.minus(Duration.ofSeconds(1)); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.EXPIRED_TOKEN, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_expirationNull() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); + Instant issuedAt = clock.now().plus(SKEW.minus(Duration.ofSeconds(1))); AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); @@ -126,8 +126,7 @@ public void testVerify_badSignature() throws Exception { assertThrowsWithErrorCode( SignatureException.class, ErrorCode.BAD_SIGNATURE, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_emptySignature() throws Exception { @@ -136,8 +135,7 @@ public void testVerify_emptySignature() throws Exception { assertThrowsWithErrorCode( SignatureException.class, ErrorCode.BAD_SIGNATURE, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_nullSignature() throws Exception { @@ -146,8 +144,7 @@ public void testVerify_nullSignature() throws Exception { assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_unsupportedSignatureAlgorithm() throws Exception { @@ -157,18 +154,14 @@ public void testVerify_unsupportedSignatureAlgorithm() throws Exception { assertThrowsWithErrorCode( SignatureException.class, ErrorCode.BAD_SIGNATURE, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_failChecker() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(new AlwaysPassChecker(), new AlwaysFailChecker()); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertThrows( - SignatureException.class, - () -> parser.verifyInternal(checkToken, getVerifiers()) - ); + assertThrows(SignatureException.class, () -> parser.verifyInternal(checkToken, getVerifiers())); } public void testVerify_emptyVerifiers() throws Exception { @@ -177,8 +170,7 @@ public void testVerify_emptyVerifiers() throws Exception { assertThrowsWithErrorCode( SignatureException.class, ErrorCode.BAD_SIGNATURE, - () -> parser.verifyInternal(checkToken, new ArrayList<>()) - ); + () -> parser.verifyInternal(checkToken, new ArrayList<>())); } public void testDeserialize_valid() throws Exception { @@ -205,8 +197,7 @@ public void testDeserialize_noSignature() throws Exception { assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.deserializeInternal(TOKEN_STRING_2PARTS) - ); + () -> parser.deserializeInternal(TOKEN_STRING_2PARTS)); } public void testDeserialize_emptySignature() throws Exception { @@ -224,24 +215,19 @@ public void testDeserialize_headerOnly() throws Exception { assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.deserializeInternal(TOKEN_STRING_1PART) - ); + () -> parser.deserializeInternal(TOKEN_STRING_1PART)); } public void testDeserialize_corruptHeader() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); assertThrows( - JsonParseException.class, - () -> parser.deserializeInternal(TOKEN_STRING_CORRUPT_HEADER) - ); + JsonParseException.class, () -> parser.deserializeInternal(TOKEN_STRING_CORRUPT_HEADER)); } public void testDeserialize_corruptPayload() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); assertThrows( - JsonParseException.class, - () -> parser.deserializeInternal(TOKEN_STRING_CORRUPT_PAYLOAD) - ); + JsonParseException.class, () -> parser.deserializeInternal(TOKEN_STRING_CORRUPT_PAYLOAD)); } public void testSignatureIsValid_valid() throws Exception { @@ -264,13 +250,12 @@ public void testSignatureIsValid_nullSignature() throws Exception { assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.signatureIsValidInternal(TOKEN_STRING_2PARTS, getVerifiers()) - ); + () -> parser.signatureIsValidInternal(TOKEN_STRING_2PARTS, getVerifiers())); } public void testExpirationIsValid_futureExpiration() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); - Instant expiration = clock.now().plus(Duration.standardSeconds(1)); + Instant expiration = clock.now().plus(Duration.ofSeconds(1)); JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); assertTrue(parser.expirationIsValid(checkToken, clock.now())); @@ -278,7 +263,7 @@ public void testExpirationIsValid_futureExpiration() throws Exception { public void testExpirationIsValid_pastExpiration() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); - Instant expiration = clock.now().minus(Duration.standardSeconds(1)); + Instant expiration = clock.now().minus(Duration.ofSeconds(1)); JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); assertFalse(parser.expirationIsValid(checkToken, clock.now())); @@ -293,7 +278,7 @@ public void testExpirationIsValid_nullExpiration() throws Exception { public void testIssuedAtIsValid_pastIssuedAt() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); - Instant issuedAt = clock.now().minus(Duration.standardSeconds(1)); + Instant issuedAt = clock.now().minus(Duration.ofSeconds(1)); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); @@ -301,7 +286,7 @@ public void testIssuedAtIsValid_pastIssuedAt() throws Exception { public void testIssuedAtIsValid_futureIssuedAt() throws Exception { AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); - Instant issuedAt = clock.now().plus(Duration.standardSeconds(1)); + Instant issuedAt = clock.now().plus(Duration.ofSeconds(1)); JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); assertFalse(parser.issuedAtIsValid(checkToken, clock.now())); @@ -314,8 +299,8 @@ public void testIssuedAtIsValid_nullIssuedAt() throws Exception { assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); } - private JsonToken getJsonTokenWithTimeRange( - Instant issuedAt, Instant expiration) throws Exception { + private JsonToken getJsonTokenWithTimeRange(Instant issuedAt, Instant expiration) + throws Exception { HmacSHA256Signer signer = new HmacSHA256Signer("google.com", "key2", SYMMETRIC_KEY); JsonToken token = new JsonToken(signer, clock); if (issuedAt != null) { @@ -331,11 +316,10 @@ private JsonToken getJsonTokenWithTimeRange( } private AbstractJsonTokenParser getAbstractJsonTokenParser() { - return new AbstractJsonTokenParser(clock, new AlwaysPassChecker()){}; + return new AbstractJsonTokenParser(clock, new AlwaysPassChecker()) {}; } private AbstractJsonTokenParser getAbstractJsonTokenParser(Checker... checkers) { - return new AbstractJsonTokenParser(clock, checkers){}; + return new AbstractJsonTokenParser(clock, checkers) {}; } - } diff --git a/src/test/java/net/oauth/jsontoken/AlwaysFailChecker.java b/src/test/java/net/oauth/jsontoken/AlwaysFailChecker.java index ffde875..843deca 100644 --- a/src/test/java/net/oauth/jsontoken/AlwaysFailChecker.java +++ b/src/test/java/net/oauth/jsontoken/AlwaysFailChecker.java @@ -3,14 +3,11 @@ import com.google.gson.JsonObject; import java.security.SignatureException; -/** - * Fails on any audience (even null). - */ +/** Fails on any audience (even null). */ public final class AlwaysFailChecker implements Checker { @Override public void check(JsonObject payload) throws SignatureException { throw new SignatureException(); } - } diff --git a/src/test/java/net/oauth/jsontoken/AlwaysPassChecker.java b/src/test/java/net/oauth/jsontoken/AlwaysPassChecker.java index 26a5fa7..ab3121b 100644 --- a/src/test/java/net/oauth/jsontoken/AlwaysPassChecker.java +++ b/src/test/java/net/oauth/jsontoken/AlwaysPassChecker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,16 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; import com.google.gson.JsonObject; import java.security.SignatureException; -/** - * Allows any audience (even null). - */ +/** Allows any audience (even null). */ public final class AlwaysPassChecker implements Checker { @Override diff --git a/src/test/java/net/oauth/jsontoken/AsyncJsonTokenParserTest.java b/src/test/java/net/oauth/jsontoken/AsyncJsonTokenParserTest.java index a55083f..9a86585 100644 --- a/src/test/java/net/oauth/jsontoken/AsyncJsonTokenParserTest.java +++ b/src/test/java/net/oauth/jsontoken/AsyncJsonTokenParserTest.java @@ -25,10 +25,14 @@ public class AsyncJsonTokenParserTest extends JsonTokenTestBase { @Override protected void setUp() throws Exception { super.setUp(); - AsyncVerifierProvider hmacLocator = (issuer, keyId) -> Futures.immediateFuture( - locators.getVerifierProvider(SignatureAlgorithm.HS256).findVerifier(issuer, keyId)); - AsyncVerifierProvider rsaLocator = (issuer, keyId) -> Futures.immediateFuture( - locators.getVerifierProvider(SignatureAlgorithm.RS256).findVerifier(issuer, keyId)); + AsyncVerifierProvider hmacLocator = + (issuer, keyId) -> + Futures.immediateFuture( + locators.getVerifierProvider(SignatureAlgorithm.HS256).findVerifier(issuer, keyId)); + AsyncVerifierProvider rsaLocator = + (issuer, keyId) -> + Futures.immediateFuture( + locators.getVerifierProvider(SignatureAlgorithm.RS256).findVerifier(issuer, keyId)); asyncLocators = alg -> { @@ -40,8 +44,12 @@ protected void setUp() throws Exception { return null; }; - AsyncVerifierProvider hmacLocatorFromRuby = (issuer, keyId) -> Futures.immediateFuture( - locatorsFromRuby.getVerifierProvider(SignatureAlgorithm.HS256).findVerifier(issuer, keyId)); + AsyncVerifierProvider hmacLocatorFromRuby = + (issuer, keyId) -> + Futures.immediateFuture( + locatorsFromRuby + .getVerifierProvider(SignatureAlgorithm.HS256) + .findVerifier(issuer, keyId)); asyncLocatorsFromRuby = alg -> { @@ -63,55 +71,41 @@ public void testVerify_valid() throws Exception { public void testVerify_badSignature() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING_BAD_SIG); - assertFailsWithErrorCode( - ErrorCode.BAD_SIGNATURE, - parser.verify(checkToken) - ); + assertFailsWithErrorCode(ErrorCode.BAD_SIGNATURE, parser.verify(checkToken)); } public void testVerify_headerMissingAlg() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING_HEADER_MISSING_ALG); - assertFailsWithErrorCode( - ErrorCode.BAD_HEADER, - parser.verify(checkToken) - ); + assertFailsWithErrorCode(ErrorCode.BAD_HEADER, parser.verify(checkToken)); } public void testVerify_unsupportedSignature() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); - assertFailsWithErrorCode( - ErrorCode.UNSUPPORTED_ALGORITHM, - parser.verify(checkToken) - ); + assertFailsWithErrorCode(ErrorCode.UNSUPPORTED_ALGORITHM, parser.verify(checkToken)); } public void testVerify_noVerifiers() throws Exception { AsyncVerifierProvider noLocator = (signerId, keyId) -> Futures.immediateFuture(null); - AsyncVerifierProviders noLocators = alg -> { - if (alg.equals(SignatureAlgorithm.HS256)) { - return noLocator; - } - return null; - }; + AsyncVerifierProviders noLocators = + alg -> { + if (alg.equals(SignatureAlgorithm.HS256)) { + return noLocator; + } + return null; + }; AsyncJsonTokenParser parser = getAsyncJsonTokenParser(noLocators, new AlwaysPassChecker()); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertFailsWithErrorCode( - ErrorCode.NO_VERIFIER, - parser.verify(checkToken) - ); + assertFailsWithErrorCode(ErrorCode.NO_VERIFIER, parser.verify(checkToken)); } public void testVerify_noProviders() throws Exception { AsyncVerifierProviders noProviders = alg -> null; AsyncJsonTokenParser parser = getAsyncJsonTokenParser(noProviders, new AlwaysPassChecker()); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertFailsWithErrorCode( - ErrorCode.UNSUPPORTED_ALGORITHM, - parser.verify(checkToken) - ); + assertFailsWithErrorCode(ErrorCode.UNSUPPORTED_ALGORITHM, parser.verify(checkToken)); } public void testVerifyAndDeserialize_valid() throws Exception { @@ -124,17 +118,13 @@ public void testVerifyAndDeserialize_valid() throws Exception { public void testVerifyAndDeserialize_deserializeFail() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); assertFailsWithErrorCode( - ErrorCode.MALFORMED_TOKEN_STRING, - parser.verifyAndDeserialize(TOKEN_STRING_2PARTS) - ); + ErrorCode.MALFORMED_TOKEN_STRING, parser.verifyAndDeserialize(TOKEN_STRING_2PARTS)); } public void testVerifyAndDeserialize_verifyFail() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); assertFailsWithErrorCode( - ErrorCode.BAD_SIGNATURE, - parser.verifyAndDeserialize(TOKEN_STRING_BAD_SIG) - ); + ErrorCode.BAD_SIGNATURE, parser.verifyAndDeserialize(TOKEN_STRING_BAD_SIG)); } public void testVerifyAndDeserialize_tokenFromRuby() throws Exception { @@ -149,10 +139,10 @@ public void testVerifyAndDeserialize_tokenFromRuby() throws Exception { public void testDeserialize_corruptHeader() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); - InvalidJsonTokenException e = assertErrorCode( - ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.deserialize(TOKEN_STRING_CORRUPT_HEADER) - ); + InvalidJsonTokenException e = + assertErrorCode( + ErrorCode.MALFORMED_TOKEN_STRING, + () -> parser.deserialize(TOKEN_STRING_CORRUPT_HEADER)); assertTrue(e.getCause() instanceof JsonParseException); } @@ -160,39 +150,29 @@ public void testDeserialize_corruptHeader() throws Exception { public void testVerifyWithVerifiers_unknownCause() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(asyncLocators, new AlwaysFailChecker()); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertErrorCode( - ErrorCode.UNKNOWN, - () -> parser.verify(checkToken, getVerifiers()) - ); + assertErrorCode(ErrorCode.UNKNOWN, () -> parser.verify(checkToken, getVerifiers())); } public void testVerifyWithVerifiers_nullSignature() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING_2PARTS); assertErrorCode( - ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.verify(checkToken, getVerifiers()) - ); + ErrorCode.MALFORMED_TOKEN_STRING, () -> parser.verify(checkToken, getVerifiers())); } public void testSignatureIsValid_nullSignature() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); assertErrorCode( ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.signatureIsValid(TOKEN_STRING_2PARTS, getVerifiers()) - ); + () -> parser.signatureIsValid(TOKEN_STRING_2PARTS, getVerifiers())); } - /** - * Ensure that legitimate runtime exceptions get through rethrowing exceptions. - */ + /** Ensure that legitimate runtime exceptions get through rethrowing exceptions. */ public void testRethrownException_runtimeException() throws Exception { AsyncJsonTokenParser parser = getAsyncJsonTokenParser(); JsonToken checkToken = new JsonToken(new JsonObject()); - ExecutionException e = assertThrows( - ExecutionException.class, - () -> parser.verify(checkToken).get() - ); + ExecutionException e = + assertThrows(ExecutionException.class, () -> parser.verify(checkToken).get()); assertTrue(e.getCause() instanceof IllegalStateException); assertTrue(e.getCause().getMessage().equals("JWT has no algorithm or header")); @@ -216,7 +196,8 @@ private InvalidJsonTokenException assertErrorCode( } private void assertFailsWithErrorCode(ErrorCode errorCode, ListenableFuture future) { - ExecutionException executionException = assertThrows(ExecutionException.class, () -> future.get()); + ExecutionException executionException = + assertThrows(ExecutionException.class, () -> future.get()); Throwable originalException = executionException.getCause(); assertTrue(originalException instanceof InvalidJsonTokenException); diff --git a/src/test/java/net/oauth/jsontoken/FakeClock.java b/src/test/java/net/oauth/jsontoken/FakeClock.java index 4d32010..dbfd44e 100644 --- a/src/test/java/net/oauth/jsontoken/FakeClock.java +++ b/src/test/java/net/oauth/jsontoken/FakeClock.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,16 +12,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; -import org.joda.time.Duration; -import org.joda.time.Instant; +import java.time.Duration; +import java.time.Instant; public class FakeClock extends SystemClock { - private Instant now = new Instant(); + private Instant now = Instant.now(); public FakeClock() { super(Duration.ZERO); diff --git a/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java b/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java index 647dffb..fdbd179 100644 --- a/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java +++ b/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -22,6 +21,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.security.SignatureException; +import java.time.Duration; import java.util.regex.Pattern; import net.oauth.jsontoken.crypto.RsaSHA256Signer; import net.oauth.jsontoken.crypto.SignatureAlgorithm; @@ -45,8 +45,7 @@ public void testVerify_unsupportedSignature() throws Exception { assertThrowsWithErrorCode( IllegalArgumentException.class, ErrorCode.UNSUPPORTED_ALGORITHM, - () -> parser.verify(checkToken) - ); + () -> parser.verify(checkToken)); } public void testVerify_noVerifiers() throws Exception { @@ -58,10 +57,7 @@ public void testVerify_noVerifiers() throws Exception { JsonToken checkToken = naiveDeserialize(TOKEN_STRING); assertThrowsWithErrorCode( - IllegalStateException.class, - ErrorCode.NO_VERIFIER, - () -> parser.verify(checkToken) - ); + IllegalStateException.class, ErrorCode.NO_VERIFIER, () -> parser.verify(checkToken)); } public void testVerify_noProviders() throws Exception { @@ -69,10 +65,7 @@ public void testVerify_noProviders() throws Exception { JsonTokenParser parser = getJsonTokenParser(noProviders, new AlwaysPassChecker()); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertThrows( - IllegalArgumentException.class, - () -> parser.verify(checkToken) - ); + assertThrows(IllegalArgumentException.class, () -> parser.verify(checkToken)); } public void testVerifyAndDeserialize_valid() throws Exception { @@ -87,16 +80,12 @@ public void testVerifyAndDeserialize_deserializeFail() throws Exception { assertThrowsWithErrorCode( IllegalStateException.class, ErrorCode.MALFORMED_TOKEN_STRING, - () -> parser.verifyAndDeserialize(TOKEN_STRING_2PARTS) - ); + () -> parser.verifyAndDeserialize(TOKEN_STRING_2PARTS)); } public void testVerifyAndDeserialize_verifyFail() throws Exception { JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - SignatureException.class, - () -> parser.verifyAndDeserialize(TOKEN_STRING_BAD_SIG) - ); + assertThrows(SignatureException.class, () -> parser.verifyAndDeserialize(TOKEN_STRING_BAD_SIG)); } public void testVerifyAndDeserialize_tokenFromRuby() throws Exception { @@ -114,7 +103,7 @@ public void testPublicKey() throws Exception { JsonToken token = new JsonToken(signer, clock); token.setParam("bar", 15); token.setParam("foo", "some value"); - token.setExpiration(clock.now().withDurationAdded(60, 1)); + token.setExpiration(clock.now().plus(Duration.ofMillis(60))); String tokenString = token.serializeAndSign(); @@ -127,9 +116,12 @@ public void testPublicKey() throws Exception { assertEquals("some value", token.getParamAsPrimitive("foo").getAsString()); // now test what happens if we tamper with the token - JsonObject payload = new JsonParser().parse( - StringUtils.newStringUtf8(Base64.decodeBase64(tokenString.split(Pattern.quote("."))[1]))) - .getAsJsonObject(); + JsonObject payload = + new JsonParser() + .parse( + StringUtils.newStringUtf8( + Base64.decodeBase64(tokenString.split(Pattern.quote("."))[1]))) + .getAsJsonObject(); payload.remove("bar"); payload.addProperty("bar", 14); String payloadString = new Gson().toJson(payload); @@ -139,10 +131,7 @@ public void testPublicKey() throws Exception { String tamperedToken = parts[0] + "." + parts[1] + "." + parts[2]; - assertThrows( - SignatureException.class, - () -> parser.verifyAndDeserialize(tamperedToken) - ); + assertThrows(SignatureException.class, () -> parser.verifyAndDeserialize(tamperedToken)); } private JsonTokenParser getJsonTokenParser() { @@ -152,5 +141,4 @@ private JsonTokenParser getJsonTokenParser() { private JsonTokenParser getJsonTokenParser(VerifierProviders providers, Checker... checkers) { return new JsonTokenParser(clock, providers, checkers); } - } diff --git a/src/test/java/net/oauth/jsontoken/JsonTokenTest.java b/src/test/java/net/oauth/jsontoken/JsonTokenTest.java index e88206c..2959c16 100644 --- a/src/test/java/net/oauth/jsontoken/JsonTokenTest.java +++ b/src/test/java/net/oauth/jsontoken/JsonTokenTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,23 +12,23 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; import static org.junit.Assert.assertThrows; import com.google.gson.JsonObject; +import java.security.SignatureException; +import java.time.Duration; import net.oauth.jsontoken.crypto.HmacSHA256Signer; import net.oauth.jsontoken.crypto.SignatureAlgorithm; -import org.joda.time.Duration; - -import java.security.SignatureException; public class JsonTokenTest extends JsonTokenTestBase { - private static final String TOKEN_STRING_NULL_FIELDS = "eyJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.URnYdSXdAAEukebqZgMq6oFjK4E9cEZlfvO8tBe_WeA"; - private static final String TOKEN_STRING_EMPTY_PAYLOAD = "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; + private static final String TOKEN_STRING_NULL_FIELDS = + "eyJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.URnYdSXdAAEukebqZgMq6oFjK4E9cEZlfvO8tBe_WeA"; + private static final String TOKEN_STRING_EMPTY_PAYLOAD = + "eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ"; public void testSignAndSerialize() throws Exception { HmacSHA256Signer signer = new HmacSHA256Signer("google.com", "key2", SYMMETRIC_KEY); @@ -38,7 +38,7 @@ public void testSignAndSerialize() throws Exception { token.setParam("foo", "some value"); token.setAudience("http://www.google.com"); token.setIssuedAt(clock.now()); - token.setExpiration(clock.now().plus(Duration.standardSeconds(1))); + token.setExpiration(clock.now().plus(Duration.ofSeconds(1))); assertEquals(TOKEN_STRING, token.serializeAndSign()); } @@ -60,10 +60,7 @@ public void testSignAndSerialize_emptyPayload() throws Exception { public void testSignAndSerialize_tokenFromJson() throws Exception { JsonToken token = new JsonToken(getFullHeader(), getFullPayload(), clock, TOKEN_STRING); - assertThrows( - SignatureException.class, - () -> token.serializeAndSign() - ); + assertThrows(SignatureException.class, () -> token.serializeAndSign()); } public void testConstructFromJson() throws Exception { @@ -128,5 +125,4 @@ private JsonObject getFullPayload() { payload.addProperty(JsonToken.EXPIRATION, 1276669723); return payload; } - } diff --git a/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java b/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java index ddfe35c..e7cdbcb 100644 --- a/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java +++ b/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken; @@ -26,6 +25,8 @@ import java.security.interfaces.RSAPrivateKey; import java.security.spec.EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Duration; +import java.time.Instant; import java.util.List; import java.util.regex.Pattern; import junit.framework.TestCase; @@ -40,8 +41,6 @@ import net.oauth.jsontoken.exceptions.ErrorCode; import net.oauth.jsontoken.exceptions.InvalidJsonTokenException; import org.apache.commons.codec.binary.Base64; -import org.joda.time.Duration; -import org.joda.time.Instant; import org.junit.function.ThrowingRunnable; public abstract class JsonTokenTestBase extends TestCase { @@ -49,54 +48,63 @@ public abstract class JsonTokenTestBase extends TestCase { protected static final byte[] SYMMETRIC_KEY = "kjdhasdkjhaskdjhaskdjhaskdjh".getBytes(); protected static final String PRIVATE_KEY = - "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6nMEXFuxTnM5+yM4Afngybf5Z" + - "89JxlchBA3Ni//Gm1/25MetzfId2Jg8NkthmRDzH6sFaoNS7n6Z6JyNJFszb2PXKBkZdem219F5k" + - "jawoHrfA1Lu8fBmGQYG/aG70aPft2eEZbY+XqW5WUlMk7vFW7BDikwBXyv/5rrFasBfPWd13xozQ" + - "9612IErWGlGMgxmB64jcTbGWMzDgzE/scSmyeQ0vQQMW8J+Nnb/yDpY7loXrVrAgZx8IBv1f9Fv3" + - "p7tirTD/vFgzxE2rIAauM/aU8zBHEyXL1NSNq0I62OAF4DLiDlcEFOvYjqoiCPQIh0NXnQy8Dcs5" + - "xHCj0e1b3X/LAgMBAAECggEBAJ9G5iQQA7xF7ZYXTITtbSgV6+/ZBTi/kEG1cUoBjL9MQZpNOlrC" + - "4lf8mgKK4LtA6OP1wfzZo1lVJeHDAAIFPOs0nm1Ft89XjMauAdcveM5xkYM7z9VL0vlddiHqQDHK" + - "WjsgKVnrwpC/I5b4A1FVxJXdPXg14igM8zioW2Y9QMVPxeUmRJxeGfvlotRlD1At1KNKg7Q2bPoi" + - "1IlRzdae6ky18x/o6FRbTo2WGRehqIAjqmwqNib3u4k/1QfEbKGShVjMtraxdlFBM7kXb/pTfhhU" + - "xlsf4xraVy2LWBLen+BAOYScd0P7vD+5oET+e4YVqILoz/WQqI9BYmTHkzj+LLECgYEA9bVjRrXq" + - "5NtO94w0T2BI9yGnZNRFbCcSocUlc6lgX7lFa6N5JvaoWF5p9CmUPPm7lxGOeSzvLKB4qv3uP/Px" + - "RQzWvAT/isKnSJ2FuKcFYGA527uJ5BlOJAtTKViYhQdYlE2g9KsjLkxJ27aF49jrkhKWqueIdJpF" + - "VfF9w+KYvVkCgYEAwm205fCRH3WEBzii2TrHqm/nVRWZ7Kxis4JppwxUslLKp33bzbHn9uOKFGfN" + - "rtXpSq9hvAcnJlJAEyVFtVNFcazE/+GbUfnrKaC3UeomjYxBk45Lcutt441gOO2SFcra7GHiNgVv" + - "fELNMo/Rr7tk8djcUcYXuDk4Kz/T2AttzcMCgYBg/Z8YtIrqmB+N3Exx4OIsm55GUPyueqYCMZ5d" + - "D8k5QBtFKByU4t0FNQ/CD/+yKiqAsa956eDnztiTNvWrTRI6XZ0OTzLIhZofMf8tKtEWgCWWtWrz" + - "HYIY/FdxhMWADaxLrnEQ49VZW0f0cRJdJK2o1amgARF+Zb9k85TflD0S0QKBgBYFlQrCT72vcs/a" + - "k19lb/4XBK23b6LF97v7VnosRF+aTwffkoje0LY/GYGsLDjUU8M40Coa6U1G3akNfLLIBsKUXg/Z" + - "ft0vIHqrkHf/vHQl4buTz2npzp2Kgs6P4g8D1f4WLCgQP4tkiZdjgM2VvR5DgNjmRgOAv6LubNE4" + - "oiw/AoGAXKfOSrbgx8JQUE7Lt6mhGvP9oTj3uiV16GgxjOtkpP3TfjsdRcmivAuekKMMKufQvGxh" + - "nX9eCYvLqJqZZwPy/002H7So3Yd1/d9ORkKetDKGjXHPDYyEPQQ+ss9OGm53XlViklXb+i9wsdDz" + - "R7tAFexSjyVKnWSDBh52t6lBtHo="; - - private static final String SERVER_INFO_DOCUMENT = "{ \"verification_keys\": {" + - // this is the public key that goes with the above private key - "\"key1\":\"RSA.ALqcwRcW7FOczn7IzgB-eDJt_lnz0nGVyEEDc2L_8abX_bkx63N8h3YmDw2S2GZEPMfqwVqg1LufpnonI0kWzNvY9coGRl16bbX0XmSNrCget8DUu7x8GYZBgb9obvRo9-3Z4Rltj5epblZSUyTu8VbsEOKTAFfK__musVqwF89Z3XfGjND3rXYgStYaUYyDGYHriNxNsZYzMODMT-xxKbJ5DS9BAxbwn42dv_IOljuWhetWsCBnHwgG_V_0W_enu2KtMP-8WDPETasgBq4z9pTzMEcTJcvU1I2rQjrY4AXgMuIOVwQU69iOqiII9AiHQ1edDLwNyznEcKPR7Vvdf8s.AQAB\"" + - "}, " + - // some other information that might be in the server info document. - "\"foo\": \"bar\"}"; + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6nMEXFuxTnM5+yM4Afngybf5Z" + + "89JxlchBA3Ni//Gm1/25MetzfId2Jg8NkthmRDzH6sFaoNS7n6Z6JyNJFszb2PXKBkZdem219F5k" + + "jawoHrfA1Lu8fBmGQYG/aG70aPft2eEZbY+XqW5WUlMk7vFW7BDikwBXyv/5rrFasBfPWd13xozQ" + + "9612IErWGlGMgxmB64jcTbGWMzDgzE/scSmyeQ0vQQMW8J+Nnb/yDpY7loXrVrAgZx8IBv1f9Fv3" + + "p7tirTD/vFgzxE2rIAauM/aU8zBHEyXL1NSNq0I62OAF4DLiDlcEFOvYjqoiCPQIh0NXnQy8Dcs5" + + "xHCj0e1b3X/LAgMBAAECggEBAJ9G5iQQA7xF7ZYXTITtbSgV6+/ZBTi/kEG1cUoBjL9MQZpNOlrC" + + "4lf8mgKK4LtA6OP1wfzZo1lVJeHDAAIFPOs0nm1Ft89XjMauAdcveM5xkYM7z9VL0vlddiHqQDHK" + + "WjsgKVnrwpC/I5b4A1FVxJXdPXg14igM8zioW2Y9QMVPxeUmRJxeGfvlotRlD1At1KNKg7Q2bPoi" + + "1IlRzdae6ky18x/o6FRbTo2WGRehqIAjqmwqNib3u4k/1QfEbKGShVjMtraxdlFBM7kXb/pTfhhU" + + "xlsf4xraVy2LWBLen+BAOYScd0P7vD+5oET+e4YVqILoz/WQqI9BYmTHkzj+LLECgYEA9bVjRrXq" + + "5NtO94w0T2BI9yGnZNRFbCcSocUlc6lgX7lFa6N5JvaoWF5p9CmUPPm7lxGOeSzvLKB4qv3uP/Px" + + "RQzWvAT/isKnSJ2FuKcFYGA527uJ5BlOJAtTKViYhQdYlE2g9KsjLkxJ27aF49jrkhKWqueIdJpF" + + "VfF9w+KYvVkCgYEAwm205fCRH3WEBzii2TrHqm/nVRWZ7Kxis4JppwxUslLKp33bzbHn9uOKFGfN" + + "rtXpSq9hvAcnJlJAEyVFtVNFcazE/+GbUfnrKaC3UeomjYxBk45Lcutt441gOO2SFcra7GHiNgVv" + + "fELNMo/Rr7tk8djcUcYXuDk4Kz/T2AttzcMCgYBg/Z8YtIrqmB+N3Exx4OIsm55GUPyueqYCMZ5d" + + "D8k5QBtFKByU4t0FNQ/CD/+yKiqAsa956eDnztiTNvWrTRI6XZ0OTzLIhZofMf8tKtEWgCWWtWrz" + + "HYIY/FdxhMWADaxLrnEQ49VZW0f0cRJdJK2o1amgARF+Zb9k85TflD0S0QKBgBYFlQrCT72vcs/a" + + "k19lb/4XBK23b6LF97v7VnosRF+aTwffkoje0LY/GYGsLDjUU8M40Coa6U1G3akNfLLIBsKUXg/Z" + + "ft0vIHqrkHf/vHQl4buTz2npzp2Kgs6P4g8D1f4WLCgQP4tkiZdjgM2VvR5DgNjmRgOAv6LubNE4" + + "oiw/AoGAXKfOSrbgx8JQUE7Lt6mhGvP9oTj3uiV16GgxjOtkpP3TfjsdRcmivAuekKMMKufQvGxh" + + "nX9eCYvLqJqZZwPy/002H7So3Yd1/d9ORkKetDKGjXHPDYyEPQQ+ss9OGm53XlViklXb+i9wsdDz" + + "R7tAFexSjyVKnWSDBh52t6lBtHo="; + + private static final String SERVER_INFO_DOCUMENT = + "{ \"verification_keys\": {" + + + // this is the public key that goes with the above private key + "\"key1\":\"RSA.ALqcwRcW7FOczn7IzgB-eDJt_lnz0nGVyEEDc2L_8abX_bkx63N8h3YmDw2S2GZEPMfqwVqg1LufpnonI0kWzNvY9coGRl16bbX0XmSNrCget8DUu7x8GYZBgb9obvRo9-3Z4Rltj5epblZSUyTu8VbsEOKTAFfK__musVqwF89Z3XfGjND3rXYgStYaUYyDGYHriNxNsZYzMODMT-xxKbJ5DS9BAxbwn42dv_IOljuWhetWsCBnHwgG_V_0W_enu2KtMP-8WDPETasgBq4z9pTzMEcTJcvU1I2rQjrY4AXgMuIOVwQU69iOqiII9AiHQ1edDLwNyznEcKPR7Vvdf8s.AQAB\"}," + + " " + + + // some other information that might be in the server info document. + "\"foo\": \"bar\"}"; protected VerifierProviders locators; protected VerifierProviders locatorsFromRuby; protected RSAPrivateKey privateKey; - protected static final String TOKEN_STRING = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - protected static final String TOKEN_STRING_BAD_SIG = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Wugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - protected static final String TOKEN_STRING_2PARTS = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ"; - protected static final String TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM = "eyJhbGciOiJIUzUxMiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.44qsiZg1Hnf95N-2wNqd1htgDlE7X0BSUMMkboMcZ5QLKbmVATozMuzdoE0MAhU-IdWUuICFbzu_wcDEXDTLug"; - protected static final String TOKEN_STRING_CORRUPT_HEADER = "fyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - protected static final String TOKEN_STRING_HEADER_MISSING_ALG = "eyJ3cm9uZ1BhcmFtIjoiSFMyNTYifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.mBtVwsgT2uZJqu2zyUzbCXF4tfo8jSSlOeRI0Tv222o"; - protected static final String TOKEN_FROM_RUBY = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8"; - - protected static final Duration SKEW = Duration.standardMinutes(1); + protected static final String TOKEN_STRING = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + protected static final String TOKEN_STRING_BAD_SIG = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Wugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + protected static final String TOKEN_STRING_2PARTS = + "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ"; + protected static final String TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM = + "eyJhbGciOiJIUzUxMiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.44qsiZg1Hnf95N-2wNqd1htgDlE7X0BSUMMkboMcZ5QLKbmVATozMuzdoE0MAhU-IdWUuICFbzu_wcDEXDTLug"; + protected static final String TOKEN_STRING_CORRUPT_HEADER = + "fyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + protected static final String TOKEN_STRING_HEADER_MISSING_ALG = + "eyJ3cm9uZ1BhcmFtIjoiSFMyNTYifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.mBtVwsgT2uZJqu2zyUzbCXF4tfo8jSSlOeRI0Tv222o"; + protected static final String TOKEN_FROM_RUBY = + "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8"; + + protected static final Duration SKEW = Duration.ofMinutes(1); protected FakeClock clock = new FakeClock(SKEW); /** - * Convert encoded tokens into a more human-readable form without verifying. - * Useful for logging. + * Convert encoded tokens into a more human-readable form without verifying. Useful for logging. */ protected static String decodeTokenForHumans(String encodedToken) { String[] pieces = encodedToken.split(Pattern.quote(".")); @@ -115,10 +123,10 @@ protected void setUp() throws Exception { VerifierProvider hmacLocator = (signerId, keyId) -> Lists.newArrayList(hmacVerifier); - VerifierProvider rsaLocator = new DefaultPublicKeyLocator( - new IdentityServerDescriptorProvider(), - uri -> JsonServerInfo.getDocument(SERVER_INFO_DOCUMENT) - ); + VerifierProvider rsaLocator = + new DefaultPublicKeyLocator( + new IdentityServerDescriptorProvider(), + uri -> JsonServerInfo.getDocument(SERVER_INFO_DOCUMENT)); locators = new VerifierProviders(); locators.setVerifierProvider(SignatureAlgorithm.HS256, hmacLocator); @@ -134,7 +142,7 @@ protected void setUp() throws Exception { locatorsFromRuby = new VerifierProviders(); locatorsFromRuby.setVerifierProvider(SignatureAlgorithm.HS256, hmacLocatorFromRuby); - clock.setNow(new Instant(1276669722000L)); + clock.setNow(Instant.ofEpochSecond(1276669722L)); } protected void assertHeader(JsonToken token) { @@ -145,36 +153,36 @@ protected void assertHeader(JsonToken token) { protected void assertPayload(JsonToken token) { assertEquals("google.com", token.getIssuer()); assertEquals("http://www.google.com", token.getAudience()); - assertEquals(new Instant(1276669722000L), token.getIssuedAt()); - assertEquals(new Instant(1276669723000L), token.getExpiration()); + assertEquals(Instant.ofEpochSecond(1276669722L), token.getIssuedAt()); + assertEquals(Instant.ofEpochSecond(1276669723L), token.getExpiration()); assertEquals(15, token.getParamAsPrimitive("bar").getAsLong()); assertEquals("some value", token.getParamAsPrimitive("foo").getAsString()); } - protected void assertThrowsWithErrorCode - (Class throwsClass, ErrorCode errorCode, ThrowingRunnable func) { + protected void assertThrowsWithErrorCode( + Class throwsClass, ErrorCode errorCode, ThrowingRunnable func) { Throwable t = assertThrows(throwsClass, func); assertTrue(t.getCause() instanceof InvalidJsonTokenException); assertTrue(((InvalidJsonTokenException) t.getCause()).getErrorCode().equals(errorCode)); } /** - * Deserializes the token string such that tokenStrings without signatures are allowed. - * Only supports token strings with at least two parts. + * Deserializes the token string such that tokenStrings without signatures are allowed. Only + * supports token strings with at least two parts. */ protected JsonToken naiveDeserialize(String tokenString) { List pieces = Splitter.on(JsonTokenUtil.DELIMITER).splitToList(tokenString); JsonParser jsonParser = new JsonParser(); - JsonObject header = jsonParser.parse(JsonTokenUtil.fromBase64ToJsonString(pieces.get(0))) - .getAsJsonObject(); - JsonObject payload = jsonParser.parse(JsonTokenUtil.fromBase64ToJsonString(pieces.get(1))) - .getAsJsonObject(); + JsonObject header = + jsonParser.parse(JsonTokenUtil.fromBase64ToJsonString(pieces.get(0))).getAsJsonObject(); + JsonObject payload = + jsonParser.parse(JsonTokenUtil.fromBase64ToJsonString(pieces.get(1))).getAsJsonObject(); return new JsonToken(header, payload, clock, tokenString); } protected List getVerifiers() { - return locators.getVerifierProvider(SignatureAlgorithm.HS256) + return locators + .getVerifierProvider(SignatureAlgorithm.HS256) .findVerifier("google.com", "key2"); } - } diff --git a/src/test/java/net/oauth/jsontoken/crypto/HmacSHA256VerifierTest.java b/src/test/java/net/oauth/jsontoken/crypto/HmacSHA256VerifierTest.java index b7b08bc..b1aaeb1 100644 --- a/src/test/java/net/oauth/jsontoken/crypto/HmacSHA256VerifierTest.java +++ b/src/test/java/net/oauth/jsontoken/crypto/HmacSHA256VerifierTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2012 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,18 +12,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.jsontoken.crypto; import static org.junit.Assert.assertThrows; -import junit.framework.TestCase; import java.security.SignatureException; +import junit.framework.TestCase; -/** - * Basic unit tests for the {@link HmacSHA256Verifier} class. - */ +/** Basic unit tests for the {@link HmacSHA256Verifier} class. */ public class HmacSHA256VerifierTest extends TestCase { private static final byte[] SYMMETRIC_KEY = "kjdhasdkjhaskdjhaskdjhaskdjh".getBytes(); private static final byte[] SOURCE = "randomdatatobesignedfortest".getBytes(); @@ -44,9 +41,6 @@ public void testBadSignature() throws Exception { byte[] signature = signer.sign(SOURCE); signature[0] ^= 1; - assertThrows( - SignatureException.class, - () -> verifier.verifySignature(SOURCE, signature) - ); + assertThrows(SignatureException.class, () -> verifier.verifySignature(SOURCE, signature)); } } diff --git a/src/test/java/net/oauth/signatures/SignedJsonAssertionBuilderTest.java b/src/test/java/net/oauth/signatures/SignedJsonAssertionBuilderTest.java index 6b750e6..d9fffb0 100644 --- a/src/test/java/net/oauth/signatures/SignedJsonAssertionBuilderTest.java +++ b/src/test/java/net/oauth/signatures/SignedJsonAssertionBuilderTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; @@ -34,10 +33,10 @@ public void testSignature() throws Exception { assertEquals("nonce", token.getNonce()); assertEquals("http://www.example.com/api", token.getAudience()); - SignedJsonAssertionTokenParser parser = new SignedJsonAssertionTokenParser( - locators, null); - SignedJsonAssertionToken compare = parser.parseToken(token.serializeAndSign(), "HTTP://www.Example.Com/api"); - + SignedJsonAssertionTokenParser parser = new SignedJsonAssertionTokenParser(locators, null); + SignedJsonAssertionToken compare = + parser.parseToken(token.serializeAndSign(), "HTTP://www.Example.Com/api"); + assertEquals("nonce", compare.getNonce()); assertEquals("http://www.example.com/api", compare.getAudience()); } diff --git a/src/test/java/net/oauth/signatures/SignedTokenBuilderTest.java b/src/test/java/net/oauth/signatures/SignedTokenBuilderTest.java index e80d024..8b329c3 100644 --- a/src/test/java/net/oauth/signatures/SignedTokenBuilderTest.java +++ b/src/test/java/net/oauth/signatures/SignedTokenBuilderTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2010 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ package net.oauth.signatures; @@ -20,8 +19,6 @@ import net.oauth.jsontoken.crypto.RsaSHA256Signer; import net.oauth.jsontoken.crypto.Signer; -import org.joda.time.Instant; - public class SignedTokenBuilderTest extends JsonTokenTestBase { public void testSignature() throws Exception { @@ -40,7 +37,8 @@ public void testSignature() throws Exception { assertEquals("http://www.example.com/api", token.getAudience()); SignedOAuthTokenParser parser = new SignedOAuthTokenParser(locators, null); - SignedOAuthToken compare = parser.parseToken(token.serializeAndSign(), "GET", "HTTP://www.Example.Com/api"); + SignedOAuthToken compare = + parser.parseToken(token.serializeAndSign(), "GET", "HTTP://www.Example.Com/api"); assertEquals("GET", compare.getMethod()); assertEquals("nonce", compare.getNonce());