From 49f7de66cfb3ae4867a0c95665102b2b0386c4a0 Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Wed, 8 Jul 2015 12:50:06 -0500 Subject: [PATCH 1/2] require a non-empty key to decode a JWT --- Authentication/JWT.php | 82 +++++++++++++++++++++--------------------- tests/JWTTest.php | 20 +++++++++++ 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/Authentication/JWT.php b/Authentication/JWT.php index 161424bb..becd100b 100644 --- a/Authentication/JWT.php +++ b/Authentication/JWT.php @@ -49,8 +49,11 @@ class JWT * @uses jsonDecode * @uses urlsafeB64Decode */ - public static function decode($jwt, $key = null, $allowed_algs = array()) + public static function decode($jwt, $key, $allowed_algs = array()) { + if (empty($key)) { + throw new InvalidArgumentException('Key may not be empty'); + } $tks = explode('.', $jwt); if (count($tks) != 3) { throw new UnexpectedValueException('Wrong number of segments'); @@ -63,50 +66,49 @@ public static function decode($jwt, $key = null, $allowed_algs = array()) throw new UnexpectedValueException('Invalid claims encoding'); } $sig = JWT::urlsafeB64Decode($cryptob64); - if (isset($key)) { - if (empty($header->alg)) { - throw new DomainException('Empty algorithm'); - } - if (empty(self::$supported_algs[$header->alg])) { - throw new DomainException('Algorithm not supported'); - } - if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) { - throw new DomainException('Algorithm not allowed'); - } - if (is_array($key) || $key instanceof \ArrayAccess) { - if (isset($header->kid)) { - $key = $key[$header->kid]; - } else { - throw new DomainException('"kid" empty, unable to lookup correct key'); - } + + if (empty($header->alg)) { + throw new DomainException('Empty algorithm'); + } + if (empty(self::$supported_algs[$header->alg])) { + throw new DomainException('Algorithm not supported'); + } + if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) { + throw new DomainException('Algorithm not allowed'); + } + if (is_array($key) || $key instanceof \ArrayAccess) { + if (isset($header->kid)) { + $key = $key[$header->kid]; + } else { + throw new DomainException('"kid" empty, unable to lookup correct key'); } + } - // Check the signature - if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) { - throw new SignatureInvalidException('Signature verification failed'); - } + // Check the signature + if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) { + throw new SignatureInvalidException('Signature verification failed'); + } - // Check if the nbf if it is defined. This is the time that the - // token can actually be used. If it's not yet that time, abort. - if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) { - throw new BeforeValidException( - 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf) - ); - } + // Check if the nbf if it is defined. This is the time that the + // token can actually be used. If it's not yet that time, abort. + if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) { + throw new BeforeValidException( + 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf) + ); + } - // Check that this token has been created before 'now'. This prevents - // using tokens that have been created for later use (and haven't - // correctly used the nbf claim). - if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) { - throw new BeforeValidException( - 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat) - ); - } + // Check that this token has been created before 'now'. This prevents + // using tokens that have been created for later use (and haven't + // correctly used the nbf claim). + if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) { + throw new BeforeValidException( + 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat) + ); + } - // Check if this token has expired. - if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) { - throw new ExpiredException('Expired token'); - } + // Check if this token has expired. + if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) { + throw new ExpiredException('Expired token'); } return $payload; diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 2aeb2017..ab1ae369 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -180,6 +180,26 @@ public function testInvalidToken() $decoded = JWT::decode($encoded, 'my_key2', array('HS256')); } + public function testNullKeyFails() + { + $payload = array( + "message" => "abc", + "exp" => time() + JWT::$leeway + 20); // time in the future + $encoded = JWT::encode($payload, 'my_key'); + $this->setExpectedException('InvalidArgumentException'); + $decoded = JWT::decode($encoded, null, array('HS256')); + } + + public function testEmptyKeyFails() + { + $payload = array( + "message" => "abc", + "exp" => time() + JWT::$leeway + 20); // time in the future + $encoded = JWT::encode($payload, 'my_key'); + $this->setExpectedException('InvalidArgumentException'); + $decoded = JWT::decode($encoded, '', array('HS256')); + } + public function testRSEncodeDecode() { $privKey = openssl_pkey_new(array('digest_alg' => 'sha256', From 17180b102ec0dfed88174aec6a7d54aac53ca871 Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Tue, 21 Jul 2015 17:19:09 -0500 Subject: [PATCH 2/2] add use InvalidArgumentException to account for JWT namespace --- src/JWT.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/JWT.php b/src/JWT.php index e8426b58..b3532df7 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -2,6 +2,7 @@ namespace Firebase\JWT; use \DomainException; +use \InvalidArgumentException; use \UnexpectedValueException; use \DateTime;