From f903dd27f2a9c59e329d6d5c404fc439f93fc064 Mon Sep 17 00:00:00 2001 From: William Lin <31808623+Will-Lin4@users.noreply.github.com> Date: Tue, 23 Jun 2020 11:49:56 -0700 Subject: [PATCH] Move abstract tests to their own file (#38) Separate abstract and sync unit tests into their own respective files. --- .../AbstractJsonTokenParserTest.java | 324 ++++++++++++++++++ .../oauth/jsontoken/JsonTokenParserTest.java | 319 +---------------- .../oauth/jsontoken/JsonTokenTestBase.java | 37 +- 3 files changed, 355 insertions(+), 325 deletions(-) create mode 100644 src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java diff --git a/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java b/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java new file mode 100644 index 0000000..cdb8888 --- /dev/null +++ b/src/test/java/net/oauth/jsontoken/AbstractJsonTokenParserTest.java @@ -0,0 +1,324 @@ +/** + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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.JsonParseException; +import java.security.SignatureException; +import java.util.ArrayList; +import java.util.List; +import net.oauth.jsontoken.crypto.HmacSHA256Signer; +import net.oauth.jsontoken.crypto.SignatureAlgorithm; +import net.oauth.jsontoken.crypto.Verifier; +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_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_HEADER = "fyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + + public void testVerify_valid() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING); + parser.verify(checkToken, getVerifiers()); + } + + public void testVerify_issuedAtAfterExpiration() throws Exception { + Instant issuedAt = clock.now(); + Instant expiration = issuedAt.minus(Duration.standardSeconds(1)); + assertFalse(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_issuedAtSkew() throws Exception { + Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); + Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); + assertTrue(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_issuedAtTooMuchSkew() throws Exception { + Instant issuedAt = clock.now().plus(SKEW.plus(Duration.standardSeconds(1))); + Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); + assertFalse(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_issuedAtNull() throws Exception { + Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); + assertTrue(verifyTimeFrame(null, expiration)); + } + + public void testVerify_expirationSkew() throws Exception { + Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); + Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); + assertTrue(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_expirationTooMuchSkew() throws Exception { + Instant expiration = clock.now().minus(SKEW.plus(Duration.standardSeconds(1))); + Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); + assertFalse(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_expirationNull() throws Exception { + Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); + assertTrue(verifyTimeFrame(issuedAt, null)); + } + + public void testVerify_issuedAtNullExpirationNull() throws Exception { + assertTrue(verifyTimeFrame(null, null)); + } + + public void testVerify_futureToken() throws Exception { + Instant issuedAt = clock.now().plus(SKEW.plus(Duration.standardSeconds(1))); + Instant expiration = issuedAt.plus(Duration.standardDays(1)); + assertFalse(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_pastToken() throws Exception { + Instant expiration = clock.now().minus(SKEW.plus(Duration.standardSeconds(1))); + Instant issuedAt = expiration.minus(Duration.standardDays(1)); + assertFalse(verifyTimeFrame(issuedAt, expiration)); + } + + public void testVerify_badSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING_BAD_SIG); + assertThrows( + SignatureException.class, + () -> parser.verify(checkToken, getVerifiers()) + ); + } + + public void testVerify_emptySignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING_EMPTY_SIG); + assertThrows( + SignatureException.class, + () -> parser.verify(checkToken, getVerifiers()) + ); + } + + public void testVerify_nullSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING_2PARTS); + assertThrows( + IllegalStateException.class, + () -> parser.verify(checkToken, getVerifiers()) + ); + } + + public void testVerify_unsupportedSignatureAlgorithm() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); + assertThrows( + SignatureException.class, + () -> parser.verify(checkToken, getVerifiers()) + ); + } + + public void testVerify_failChecker() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(new IgnoreAudience(), new AlwaysFailAudience()); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING); + assertThrows( + SignatureException.class, + () -> parser.verify(checkToken, getVerifiers()) + ); + } + + public void testVerify_noVerifiers() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = naiveDeserialize(TOKEN_STRING); + assertThrows( + SignatureException.class, + () -> parser.verify(checkToken, new ArrayList<>()) + ); + } + + public void testDeserialize_valid() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken token = parser.deserialize(TOKEN_STRING); + + assertHeader(token); + assertPayload(token); + } + + public void testDeserialize_nullIssuer() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(null); + JsonToken token = parser.deserialize(TOKEN_STRING_ISSUER_NULL); + assertNull(token.getIssuer()); + } + + public void testDeserialize_badSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + parser.deserialize(TOKEN_STRING_BAD_SIG); + } + + public void testDeserialize_noSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertThrows( + IllegalStateException.class, + () -> parser.deserialize(TOKEN_STRING_2PARTS) + ); + } + + public void testDeserialize_emptySignature() throws Exception { + JsonTokenParser parser = new JsonTokenParser(clock, locators, new IgnoreAudience()); + parser.deserialize(TOKEN_STRING_EMPTY_SIG); + } + + public void testDeserialize_unsupportedSignatureAlgorithm() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + parser.deserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); + } + + public void testDeserialize_headerOnly() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertThrows( + IllegalStateException.class, + () -> parser.deserialize(TOKEN_STRING_1PART) + ); + } + + public void testDeserialize_corruptHeader() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertThrows( + JsonParseException.class, + () -> parser.deserialize(TOKEN_STRING_CORRUPT_HEADER) + ); + } + + public void testDeserialize_corruptPayload() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertThrows( + JsonParseException.class, + () -> parser.deserialize(TOKEN_STRING_CORRUPT_PAYLOAD) + ); + } + + public void testSignatureIsValid_valid() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertTrue(parser.signatureIsValid(TOKEN_STRING, getVerifiers())); + } + + public void testSignatureIsValid_badSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertFalse(parser.signatureIsValid(TOKEN_STRING_BAD_SIG, getVerifiers())); + } + + public void testSignatureIsValid_emptySignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertFalse(parser.signatureIsValid(TOKEN_STRING_EMPTY_SIG, getVerifiers())); + } + + public void testSignatureIsValid_nullSignature() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + assertThrows( + IllegalStateException.class, + () -> parser.signatureIsValid(TOKEN_STRING_2PARTS, getVerifiers()) + ); + } + + public void testExpirationIsValid_futureExpiration() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + Instant expiration = clock.now().plus(Duration.standardSeconds(1)); + JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); + + assertTrue(parser.expirationIsValid(checkToken, clock.now())); + } + + public void testExpirationIsValid_pastExpiration() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + Instant expiration = clock.now().minus(Duration.standardSeconds(1)); + JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); + + assertFalse(parser.expirationIsValid(checkToken, clock.now())); + } + + public void testExpirationIsValid_nullExpiration() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = getJsonTokenWithTimeRange(null, null); + + assertTrue(parser.expirationIsValid(checkToken, clock.now())); + } + + public void testIssuedAtIsValid_pastIssuedAt() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + Instant issuedAt = clock.now().minus(Duration.standardSeconds(1)); + JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); + + assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); + } + + public void testIssuedAtIsValid_futureIssuedAt() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + Instant issuedAt = clock.now().plus(Duration.standardSeconds(1)); + JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); + + assertFalse(parser.issuedAtIsValid(checkToken, clock.now())); + } + + public void testIssuedAtIsValid_nullIssuedAt() throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = getJsonTokenWithTimeRange(null, null); + + assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); + } + + private boolean verifyTimeFrame(Instant issuedAt, Instant expiration) throws Exception { + AbstractJsonTokenParser parser = getAbstractJsonTokenParser(); + JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); + + try { + parser.verify(checkToken, getVerifiers()); + return true; + } catch (IllegalStateException e) { + return false; + } + } + + 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) { + token.setIssuedAt(issuedAt); + } + + if (expiration != null) { + token.setExpiration(expiration); + } + + return new JsonToken( + token.getHeader(), token.getPayloadAsJsonObject(), clock, token.serializeAndSign()); + } + + private List getVerifiers() { + return locators.getVerifierProvider(SignatureAlgorithm.HS256) + .findVerifier("google.com", "key2"); + } + + private AbstractJsonTokenParser getAbstractJsonTokenParser() { + return new AbstractJsonTokenParser(clock, new IgnoreAudience()){}; + } + + private AbstractJsonTokenParser getAbstractJsonTokenParser(Checker... checkers) { + return new AbstractJsonTokenParser(clock, checkers){}; + } +} diff --git a/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java b/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java index f433a6d..8648c22 100644 --- a/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java +++ b/src/test/java/net/oauth/jsontoken/JsonTokenParserTest.java @@ -18,164 +18,28 @@ import static org.junit.Assert.assertThrows; -import com.google.common.base.Splitter; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; - -import net.oauth.jsontoken.crypto.HmacSHA256Signer; +import java.security.SignatureException; +import java.util.regex.Pattern; import net.oauth.jsontoken.crypto.RsaSHA256Signer; - import net.oauth.jsontoken.crypto.SignatureAlgorithm; -import net.oauth.jsontoken.crypto.Verifier; import net.oauth.jsontoken.discovery.VerifierProvider; import net.oauth.jsontoken.discovery.VerifierProviders; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.StringUtils; -import org.joda.time.Duration; -import org.joda.time.Instant; - -import java.security.SignatureException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; public class JsonTokenParserTest extends JsonTokenTestBase { - private static final String TOKEN_STRING_ISSUER_NULL = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOm51bGwsImJhciI6MTUsImZvbyI6InNvbWUgdmFsdWUiLCJhdWQiOiJodHRwOi8vd3d3Lmdvb2dsZS5jb20iLCJpYXQiOjEyNzY2Njk3MjIsImV4cCI6MTI3NjY2OTcyM30.WPaa6PoLWPzNfnIBisBX9549kWeABSj9tXnwnPE4IJk"; - private static final String TOKEN_STRING_BAD_SIG = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Wugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - 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_HEADER = "fyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - private static final String TOKEN_STRING_CORRUPT_PAYLOAD = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3&&&&&nb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; - private static final String TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM = "eyJhbGciOiJIUzUxMiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.44qsiZg1Hnf95N-2wNqd1htgDlE7X0BSUMMkboMcZ5QLKbmVATozMuzdoE0MAhU-IdWUuICFbzu_wcDEXDTLug"; - private static final String TOKEN_FROM_RUBY = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8"; - public void testVerify_valid() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - parser.verify(checkToken, getVerifiers()); - } - - public void testVerify_issuedAtAfterExpiration() throws Exception { - Instant issuedAt = clock.now(); - Instant expiration = issuedAt.minus(Duration.standardSeconds(1)); - assertFalse(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_issuedAtSkew() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); - Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); - assertTrue(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_issuedAtTooMuchSkew() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.plus(Duration.standardSeconds(1))); - Instant expiration = issuedAt.plus(Duration.standardSeconds(1)); - assertFalse(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_issuedAtNull() throws Exception { - Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); - assertTrue(verifyTimeFrame(null, expiration)); - } - - public void testVerify_expirationSkew() throws Exception { - Instant expiration = clock.now().minus(SKEW.minus(Duration.standardSeconds(1))); - Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); - assertTrue(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_expirationTooMuchSkew() throws Exception { - Instant expiration = clock.now().minus(SKEW.plus(Duration.standardSeconds(1))); - Instant issuedAt = expiration.minus(Duration.standardSeconds(1)); - assertFalse(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_expirationNull() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.minus(Duration.standardSeconds(1))); - assertTrue(verifyTimeFrame(issuedAt, null)); - } - - public void testVerify_issuedAtNullExpirationNull() throws Exception { - assertTrue(verifyTimeFrame(null, null)); - } - - public void testVerify_futureToken() throws Exception { - Instant issuedAt = clock.now().plus(SKEW.plus(Duration.standardSeconds(1))); - Instant expiration = issuedAt.plus(Duration.standardDays(1)); - assertFalse(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_pastToken() throws Exception { - Instant expiration = clock.now().minus(SKEW.plus(Duration.standardSeconds(1))); - Instant issuedAt = expiration.minus(Duration.standardDays(1)); - assertFalse(verifyTimeFrame(issuedAt, expiration)); - } - - public void testVerify_badSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING_BAD_SIG); - assertThrows( - SignatureException.class, - () -> parser.verify(checkToken, getVerifiers()) - ); - } - - public void testVerify_emptySignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING_EMPTY_SIG); - assertThrows( - SignatureException.class, - () -> parser.verify(checkToken, getVerifiers()) - ); - } - - public void testVerify_nullSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING_2PARTS); - assertThrows( - IllegalStateException.class, - () -> parser.verify(checkToken, getVerifiers()) - ); - } - - public void testVerify_unsupportedSignatureAlgorithm() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); - assertThrows( - SignatureException.class, - () -> parser.verify(checkToken, getVerifiers()) - ); - } - - public void testVerify_failChecker() throws Exception { - JsonTokenParser parser = getJsonTokenParser(locators, new IgnoreAudience(), new AlwaysFailAudience()); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertThrows( - SignatureException.class, - () -> parser.verify(checkToken, getVerifiers()) - ); - } - - public void testVerify_noVerifiers() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = naiveDeserialize(TOKEN_STRING); - assertThrows( - SignatureException.class, - () -> parser.verify(checkToken, new ArrayList<>()) - ); - } - - public void testVerifyWithJsonToken_valid() throws Exception { JsonTokenParser parser = getJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING); parser.verify(checkToken); } - public void testVerifyWithJsonToken_unsupportedSignature() throws Exception { + public void testVerify_unsupportedSignature() throws Exception { JsonTokenParser parser = getJsonTokenParser(); JsonToken checkToken = naiveDeserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); assertThrows( @@ -184,7 +48,7 @@ public void testVerifyWithJsonToken_unsupportedSignature() throws Exception { ); } - public void testVerifyWithJsonToken_noVerifiers() throws Exception { + public void testVerify_noVerifiers() throws Exception { VerifierProvider noLocator = (signerId, keyId) -> null; VerifierProviders noLocators = new VerifierProviders(); noLocators.setVerifierProvider(SignatureAlgorithm.HS256, noLocator); @@ -197,67 +61,6 @@ public void testVerifyWithJsonToken_noVerifiers() throws Exception { ); } - public void testDeserialize_valid() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken token = parser.deserialize(TOKEN_STRING); - - assertHeader(token); - assertPayload(token); - } - - public void testDeserialize_nullIssuer() throws Exception { - JsonTokenParser parser = getJsonTokenParser(null); - JsonToken token = parser.deserialize(TOKEN_STRING_ISSUER_NULL); - assertNull(token.getIssuer()); - } - - public void testDeserialize_badSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - parser.deserialize(TOKEN_STRING_BAD_SIG); - } - - public void testDeserialize_noSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - IllegalStateException.class, - () -> parser.deserialize(TOKEN_STRING_2PARTS) - ); - } - - public void testDeserialize_emptySignature() throws Exception { - JsonTokenParser parser = new JsonTokenParser(clock, locators, new IgnoreAudience()); - parser.deserialize(TOKEN_STRING_EMPTY_SIG); - } - - public void testDeserialize_unsupportedSignatureAlgorithm() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - parser.deserialize(TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM); - } - - public void testDeserialize_headerOnly() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - IllegalStateException.class, - () -> parser.deserialize(TOKEN_STRING_1PART) - ); - } - - public void testDeserialize_corruptHeader() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - JsonParseException.class, - () -> parser.deserialize(TOKEN_STRING_CORRUPT_HEADER) - ); - } - - public void testDeserialize_corruptPayload() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - JsonParseException.class, - () -> parser.deserialize(TOKEN_STRING_CORRUPT_PAYLOAD) - ); - } - public void testVerifyAndDeserialize_valid() throws Exception { JsonTokenParser parser = getJsonTokenParser(); JsonToken token = parser.verifyAndDeserialize(TOKEN_STRING); @@ -290,75 +93,6 @@ public void testVerifyAndDeserialize_tokenFromRuby() throws Exception { assertEquals("world", token.getParamAsPrimitive("hello").getAsString()); } - public void testSignatureIsValid_valid() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertTrue(parser.signatureIsValid(TOKEN_STRING, getVerifiers())); - } - - public void testSignatureIsValid_badSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertFalse(parser.signatureIsValid(TOKEN_STRING_BAD_SIG, getVerifiers())); - } - - public void testSignatureIsValid_emptySignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertFalse(parser.signatureIsValid(TOKEN_STRING_EMPTY_SIG, getVerifiers())); - } - - public void testSignatureIsValid_nullSignature() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - assertThrows( - IllegalStateException.class, - () -> parser.signatureIsValid(TOKEN_STRING_2PARTS, getVerifiers()) - ); - } - - public void testExpirationIsValid_futureExpiration() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - Instant expiration = clock.now().plus(Duration.standardSeconds(1)); - JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); - - assertTrue(parser.expirationIsValid(checkToken, clock.now())); - } - - public void testExpirationIsValid_pastExpiration() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - Instant expiration = clock.now().minus(Duration.standardSeconds(1)); - JsonToken checkToken = getJsonTokenWithTimeRange(null, expiration); - - assertFalse(parser.expirationIsValid(checkToken, clock.now())); - } - - public void testExpirationIsValid_nullExpiration() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = getJsonTokenWithTimeRange(null, null); - - assertTrue(parser.expirationIsValid(checkToken, clock.now())); - } - - public void testIssuedAtIsValid_pastIssuedAt() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - Instant issuedAt = clock.now().minus(Duration.standardSeconds(1)); - JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); - - assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); - } - - public void testIssuedAtIsValid_futureIssuedAt() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - Instant issuedAt = clock.now().plus(Duration.standardSeconds(1)); - JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, null); - - assertFalse(parser.issuedAtIsValid(checkToken, clock.now())); - } - - public void testIssuedAtIsValid_nullIssuedAt() throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = getJsonTokenWithTimeRange(null, null); - - assertTrue(parser.issuedAtIsValid(checkToken, clock.now())); - } - public void testPublicKey() throws Exception { RsaSHA256Signer signer = new RsaSHA256Signer("google.com", "key1", privateKey); @@ -396,50 +130,6 @@ public void testPublicKey() throws Exception { ); } - private boolean verifyTimeFrame(Instant issuedAt, Instant expiration) throws Exception { - JsonTokenParser parser = getJsonTokenParser(); - JsonToken checkToken = getJsonTokenWithTimeRange(issuedAt, expiration); - - try { - parser.verify(checkToken); - return true; - } catch (IllegalStateException e) { - return false; - } - } - - 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) { - token.setIssuedAt(issuedAt); - } - - if (expiration != null) { - token.setExpiration(expiration); - } - - return new JsonToken( - token.getHeader(), token.getPayloadAsJsonObject(), clock, token.serializeAndSign()); - } - - /** - * Deserializes the token string such that tokenStrings without signatures are allowed. - * Only supports token strings with at least two parts. - */ - private 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(); - return new JsonToken(header, payload, clock, tokenString); - } - - private List getVerifiers() { - return locators.getVerifierProvider(SignatureAlgorithm.HS256) - .findVerifier("google.com", "key2"); - } - private JsonTokenParser getJsonTokenParser() { return new JsonTokenParser(clock, locators, new IgnoreAudience()); } @@ -447,4 +137,5 @@ 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/JsonTokenTestBase.java b/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java index e6a6f34..bfd13ab 100644 --- a/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java +++ b/src/test/java/net/oauth/jsontoken/JsonTokenTestBase.java @@ -16,11 +16,18 @@ */ package net.oauth.jsontoken; +import com.google.common.base.Splitter; import com.google.common.collect.Lists; - import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.net.URI; +import java.security.KeyFactory; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.EncodedKeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.List; +import java.util.regex.Pattern; import junit.framework.TestCase; - import net.oauth.jsontoken.crypto.HmacSHA256Verifier; import net.oauth.jsontoken.crypto.SignatureAlgorithm; import net.oauth.jsontoken.crypto.Verifier; @@ -31,19 +38,10 @@ import net.oauth.jsontoken.discovery.ServerInfoResolver; import net.oauth.jsontoken.discovery.VerifierProvider; import net.oauth.jsontoken.discovery.VerifierProviders; - import org.apache.commons.codec.binary.Base64; import org.joda.time.Duration; import org.joda.time.Instant; -import java.net.URI; -import java.security.KeyFactory; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.EncodedKeySpec; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.List; -import java.util.regex.Pattern; - public abstract class JsonTokenTestBase extends TestCase { protected static final byte[] SYMMETRIC_KEY = "kjdhasdkjhaskdjhaskdjhaskdjh".getBytes(); @@ -84,6 +82,11 @@ public abstract class JsonTokenTestBase extends TestCase { 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_CORRUPT_PAYLOAD = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleTIifQ.eyJpc3&&&&&nb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.Xugb4nb5kLV3NTpOLaz9er5PhAI5mFehHst_33EUFHs"; + protected static final String TOKEN_STRING_UNSUPPORTED_SIGNATURE_ALGORITHM = "eyJhbGciOiJIUzUxMiIsImtpZCI6ImtleTIifQ.eyJpc3MiOiJnb29nbGUuY29tIiwiYmFyIjoxNSwiZm9vIjoic29tZSB2YWx1ZSIsImF1ZCI6Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbSIsImlhdCI6MTI3NjY2OTcyMiwiZXhwIjoxMjc2NjY5NzIzfQ.44qsiZg1Hnf95N-2wNqd1htgDlE7X0BSUMMkboMcZ5QLKbmVATozMuzdoE0MAhU-IdWUuICFbzu_wcDEXDTLug"; + protected static final String TOKEN_FROM_RUBY = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8"; + protected static final Duration SKEW = Duration.standardMinutes(1); protected FakeClock clock = new FakeClock(SKEW); @@ -158,4 +161,16 @@ protected void assertPayload(JsonToken token) { assertEquals(15, token.getParamAsPrimitive("bar").getAsLong()); assertEquals("some value", token.getParamAsPrimitive("foo").getAsString()); } + + /** + * 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(); + return new JsonToken(header, payload, clock, tokenString); + } }