From d7d37885921a0a6cc10ef57a86c5ea3a4435208e Mon Sep 17 00:00:00 2001 From: Dante Marshal Date: Mon, 20 Apr 2020 23:51:05 +0430 Subject: [PATCH 01/10] feat: adds payload to exceptions * Add payload to following exceptions : - ExpiredException - Signature Exception + Add and Run Tests Note : I have run the tests using Php 7.2.24 Someone please run the tests using Php 5.3 --- src/ExpiredException.php | 13 ++++++++++++- src/IJWTException.php | 11 +++++++++++ src/JWT.php | 4 ++-- src/SignatureInvalidException.php | 11 +++++++++++ tests/JWTTest.php | 22 +++++++++++++++++++--- 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 src/IJWTException.php diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 7f7d0568..089c44dc 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -1,6 +1,17 @@ payload = $payload; + } + + public function getPayload() + { + return $this->payload; + } } diff --git a/src/IJWTException.php b/src/IJWTException.php new file mode 100644 index 00000000..580f7b12 --- /dev/null +++ b/src/IJWTException.php @@ -0,0 +1,11 @@ +alg)) { - throw new SignatureInvalidException('Signature verification failed'); + throw new SignatureInvalidException($payload, 'Signature verification failed'); } // Check the nbf if it is defined. This is the time that the @@ -141,7 +141,7 @@ public static function decode($jwt, $key, array $allowed_algs = array()) // Check if this token has expired. if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) { - throw new ExpiredException('Expired token'); + throw new ExpiredException($payload, 'Expired token'); } return $payload; diff --git a/src/SignatureInvalidException.php b/src/SignatureInvalidException.php index 87cb34df..e17fd76b 100644 --- a/src/SignatureInvalidException.php +++ b/src/SignatureInvalidException.php @@ -3,4 +3,15 @@ class SignatureInvalidException extends \UnexpectedValueException { + private $payload; + + public function __construct(object $payload, string $message = "", int $code = 0, Throwable $previous = NULL){ + parent::__construct($message, $code, $previous); + $this->payload = $payload; + } + + public function getPayload() + { + return $this->payload; + } } diff --git a/tests/JWTTest.php b/tests/JWTTest.php index fc9c3756..b60a357c 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -58,7 +58,12 @@ public function testExpiredToken() "message" => "abc", "exp" => time() - 20); // time in the past $encoded = JWT::encode($payload, 'my_key'); - JWT::decode($encoded, 'my_key', array('HS256')); + try { JWT::decode($encoded, 'my_key', array('HS256')); } + catch (\Exception $e) { + $exceptionPayload = (array)($e->getPayload()); + $this->assertEquals($exceptionPayload, $payload); + throw $e; + } } public function testBeforeValidTokenWithNbf() @@ -111,7 +116,12 @@ public function testExpiredTokenWithLeeway() "exp" => time() - 70); // time far in the past $this->setExpectedException('Firebase\JWT\ExpiredException'); $encoded = JWT::encode($payload, 'my_key'); - $decoded = JWT::decode($encoded, 'my_key', array('HS256')); + try { $decoded = JWT::decode($encoded, 'my_key', array('HS256')); } + catch (\Exception $e) { + $exceptionPayload = (array)($e->getPayload()); + $this->assertEquals($exceptionPayload, $payload); + throw $e; + } $this->assertEquals($decoded->message, 'abc'); JWT::$leeway = 0; } @@ -193,7 +203,13 @@ public function testInvalidToken() "exp" => time() + 20); // time in the future $encoded = JWT::encode($payload, 'my_key'); $this->setExpectedException('Firebase\JWT\SignatureInvalidException'); - JWT::decode($encoded, 'my_key2', array('HS256')); + + try { JWT::decode($encoded, 'my_key2', array('HS256')); } + catch (\Exception $e) { + $exceptionPayload = (array)($e->getPayload()); + $this->assertEquals($exceptionPayload, $payload); + throw $e; + } } public function testNullKeyFails() From ed47bbb4744df335b8e955662281af10b297f4bf Mon Sep 17 00:00:00 2001 From: Dante Marshal Date: Tue, 21 Apr 2020 00:14:41 +0430 Subject: [PATCH 02/10] test: Fix bugs indicated by Travis CI --- src/ExpiredException.php | 3 ++- src/IJWTException.php | 3 ++- src/SignatureInvalidException.php | 3 ++- tests/JWTTest.php | 15 +++++++++------ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 089c44dc..34f86877 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -5,7 +5,8 @@ class ExpiredException extends \UnexpectedValueException implements IJWTExceptio { private $payload; - public function __construct(object $payload, string $message = "", int $code = 0, Throwable $previous = NULL){ + public function __construct($payload, string $message = NULL, int $code = 0, Throwable $previous = NULL) + { parent::__construct($message, $code, $previous); $this->payload = $payload; } diff --git a/src/IJWTException.php b/src/IJWTException.php index 580f7b12..58ca9009 100644 --- a/src/IJWTException.php +++ b/src/IJWTException.php @@ -1,7 +1,8 @@ payload = $payload; } diff --git a/tests/JWTTest.php b/tests/JWTTest.php index b60a357c..4e72ffae 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -58,8 +58,9 @@ public function testExpiredToken() "message" => "abc", "exp" => time() - 20); // time in the past $encoded = JWT::encode($payload, 'my_key'); - try { JWT::decode($encoded, 'my_key', array('HS256')); } - catch (\Exception $e) { + try { + JWT::decode($encoded, 'my_key', array('HS256')); + } catch (\Exception $e) { $exceptionPayload = (array)($e->getPayload()); $this->assertEquals($exceptionPayload, $payload); throw $e; @@ -116,8 +117,9 @@ public function testExpiredTokenWithLeeway() "exp" => time() - 70); // time far in the past $this->setExpectedException('Firebase\JWT\ExpiredException'); $encoded = JWT::encode($payload, 'my_key'); - try { $decoded = JWT::decode($encoded, 'my_key', array('HS256')); } - catch (\Exception $e) { + try { + $decoded = JWT::decode($encoded, 'my_key', array('HS256')); + } catch (\Exception $e) { $exceptionPayload = (array)($e->getPayload()); $this->assertEquals($exceptionPayload, $payload); throw $e; @@ -204,8 +206,9 @@ public function testInvalidToken() $encoded = JWT::encode($payload, 'my_key'); $this->setExpectedException('Firebase\JWT\SignatureInvalidException'); - try { JWT::decode($encoded, 'my_key2', array('HS256')); } - catch (\Exception $e) { + try { + JWT::decode($encoded, 'my_key2', array('HS256')); + } catch (\Exception $e) { $exceptionPayload = (array)($e->getPayload()); $this->assertEquals($exceptionPayload, $payload); throw $e; From 97e8a02eb731a449283f32ad8634a7e09cfb2139 Mon Sep 17 00:00:00 2001 From: Dante Marshal Date: Tue, 21 Apr 2020 00:24:44 +0430 Subject: [PATCH 03/10] test: Fix bugs indicated by Travis CI --- src/ExpiredException.php | 2 +- src/SignatureInvalidException.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 34f86877..b6efe529 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -5,7 +5,7 @@ class ExpiredException extends \UnexpectedValueException implements IJWTExceptio { private $payload; - public function __construct($payload, string $message = NULL, int $code = 0, Throwable $previous = NULL) + public function __construct($payload, $message = "", $code = 0, $previous = null) { parent::__construct($message, $code, $previous); $this->payload = $payload; diff --git a/src/SignatureInvalidException.php b/src/SignatureInvalidException.php index 4ac4dec6..3fa984cf 100644 --- a/src/SignatureInvalidException.php +++ b/src/SignatureInvalidException.php @@ -5,7 +5,7 @@ class SignatureInvalidException extends \UnexpectedValueException { private $payload; - public function __construct($payload, string $message = NULL, int $code = 0, Throwable $previous = NULL) + public function __construct($payload, $message = "", $code = 0, $previous = null) { parent::__construct($message, $code, $previous); $this->payload = $payload; From d7c62f42bf652e97f3c3001d41f270c7af06faaf Mon Sep 17 00:00:00 2001 From: Marshal313 Date: Mon, 20 Apr 2020 20:31:32 +0000 Subject: [PATCH 04/10] Add a new line at the end of IJWTException.php --- src/IJWTException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IJWTException.php b/src/IJWTException.php index 58ca9009..40c9de6a 100644 --- a/src/IJWTException.php +++ b/src/IJWTException.php @@ -9,4 +9,4 @@ interface IJWTException * @return object */ public function getPayload(); -} \ No newline at end of file +} From f5cdf34ffcd806a4b3ff921e0c1d3e105084439d Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 20 Jun 2023 12:38:37 -0700 Subject: [PATCH 05/10] rename exception interface --- src/ExpiredException.php | 4 ++-- src/{IJWTException.php => JWTExceptionInterface.php} | 2 +- tests/JWTTest.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename src/{IJWTException.php => JWTExceptionInterface.php} (83%) diff --git a/src/ExpiredException.php b/src/ExpiredException.php index b6efe529..6cdcef33 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -1,10 +1,10 @@ getPayload()); $this->assertEquals($exceptionPayload, $payload); throw $e; From 138d03ed662f10db4fef1016b9c056690aa3c090 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 20 Jun 2023 12:49:23 -0700 Subject: [PATCH 06/10] add two more tests --- tests/JWTTest.php | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 58055906..1904ae28 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -108,7 +108,7 @@ public function testExpiredExceptionPayload() $this->expectException(ExpiredException::class); $payload = [ 'message' => 'abc', - 'exp' => time() - 20, // time in the past + 'exp' => time() - 100, // time in the past ]; $encoded = JWT::encode($payload, 'my_key', 'HS256'); try { @@ -120,6 +120,40 @@ public function testExpiredExceptionPayload() } } + public function testBeforeValidExceptionPayload() + { + $this->expectException(BeforeValidException::class); + $payload = [ + 'message' => 'abc', + 'iat' => time() + 20, // time in the future + ]; + $encoded = JWT::encode($payload, 'my_key', 'HS256'); + try { + JWT::decode($encoded, new Key('my_key', 'HS256')); + } catch (BeforeValidException $e) { + $exceptionPayload = (array) $e->getPayload(); + $this->assertEquals($exceptionPayload, $payload); + throw $e; + } + } + + public function testSignatureInvalidExceptionPayload() + { + $payload = [ + 'message' => 'abc', + 'exp' => time() + 20, // time in the future + ]; + $encoded = JWT::encode($payload, 'my_key', 'HS256'); + $this->expectException(SignatureInvalidException::class); + try { + JWT::decode($encoded, new Key('my_key2', 'HS256')); + } catch (SignatureInvalidException $e) { + $exceptionPayload = (array) $e->getPayload(); + $this->assertEquals($exceptionPayload, $payload); + throw $e; + } + } + public function testValidTokenWithNbf() { $payload = [ From 91f9f01e604492f07176a39807c15a943bf2adb0 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 20 Jun 2023 12:52:10 -0700 Subject: [PATCH 07/10] increase leeway --- tests/JWTTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 1904ae28..0145d373 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -125,7 +125,7 @@ public function testBeforeValidExceptionPayload() $this->expectException(BeforeValidException::class); $payload = [ 'message' => 'abc', - 'iat' => time() + 20, // time in the future + 'iat' => time() + 100, // time in the future ]; $encoded = JWT::encode($payload, 'my_key', 'HS256'); try { From 3c71f7a96f0073011d024958abe18fff525bbfbe Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 20 Jun 2023 12:55:54 -0700 Subject: [PATCH 08/10] fix static analysis --- src/BeforeValidException.php | 4 ++-- src/ExpiredException.php | 2 +- src/JWTExceptionInterface.php | 10 +++++++++- src/SignatureInvalidException.php | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/BeforeValidException.php b/src/BeforeValidException.php index 9e0de8f0..e8a92f8e 100644 --- a/src/BeforeValidException.php +++ b/src/BeforeValidException.php @@ -2,9 +2,9 @@ namespace Firebase\JWT; -class BeforeValidException extends \UnexpectedValueException implements JwtExceptionInterface +class BeforeValidException extends \UnexpectedValueException implements JWTExceptionInterface { - private $payload; + private object $payload; public function setPayload(object $payload): void { diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 338660dd..0e207a09 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -4,7 +4,7 @@ class ExpiredException extends \UnexpectedValueException implements JWTExceptionInterface { - private $payload; + private object $payload; public function setPayload(object $payload): void { diff --git a/src/JWTExceptionInterface.php b/src/JWTExceptionInterface.php index cf3580fd..b78358aa 100644 --- a/src/JWTExceptionInterface.php +++ b/src/JWTExceptionInterface.php @@ -8,5 +8,13 @@ interface JWTExceptionInterface * * @return object */ - public function getPayload(); + public function getPayload(): object; + + /** + * Get the payload that caused this exception. + * + * @param object $payload + * @return void + */ + public function setPayload(object $object): void; } diff --git a/src/SignatureInvalidException.php b/src/SignatureInvalidException.php index f936e4df..cf31c4c6 100644 --- a/src/SignatureInvalidException.php +++ b/src/SignatureInvalidException.php @@ -2,9 +2,9 @@ namespace Firebase\JWT; -class SignatureInvalidException extends \UnexpectedValueException implements JwtExceptionInterface +class SignatureInvalidException extends \UnexpectedValueException implements JWTExceptionInterface { - private $payload; + private object $payload; public function setPayload(object $payload): void { From a652201a0d5f1d3c939cbf985288e24991dba65a Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 20 Jun 2023 12:59:45 -0700 Subject: [PATCH 09/10] fix phpstan again --- src/JWTExceptionInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JWTExceptionInterface.php b/src/JWTExceptionInterface.php index b78358aa..8277eb30 100644 --- a/src/JWTExceptionInterface.php +++ b/src/JWTExceptionInterface.php @@ -16,5 +16,5 @@ public function getPayload(): object; * @param object $payload * @return void */ - public function setPayload(object $object): void; + public function setPayload(object $payload): void; } From 4b1d30299b69ebff0afed22fb0296d3e3ff51972 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Wed, 21 Jun 2023 09:54:29 -0700 Subject: [PATCH 10/10] revert adding payload to SignatureInvalidException, rename interface --- src/BeforeValidException.php | 2 +- src/ExpiredException.php | 2 +- src/JWT.php | 4 +--- ...php => JWTExceptionWithPayloadInterface.php} | 2 +- src/SignatureInvalidException.php | 13 +------------ tests/JWTTest.php | 17 ----------------- 6 files changed, 5 insertions(+), 35 deletions(-) rename src/{JWTExceptionInterface.php => JWTExceptionWithPayloadInterface.php} (89%) diff --git a/src/BeforeValidException.php b/src/BeforeValidException.php index e8a92f8e..595164bf 100644 --- a/src/BeforeValidException.php +++ b/src/BeforeValidException.php @@ -2,7 +2,7 @@ namespace Firebase\JWT; -class BeforeValidException extends \UnexpectedValueException implements JWTExceptionInterface +class BeforeValidException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface { private object $payload; diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 0e207a09..12fef094 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -2,7 +2,7 @@ namespace Firebase\JWT; -class ExpiredException extends \UnexpectedValueException implements JWTExceptionInterface +class ExpiredException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface { private object $payload; diff --git a/src/JWT.php b/src/JWT.php index 2204b4cc..82853278 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -147,9 +147,7 @@ public static function decode( $sig = self::signatureToDER($sig); } if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) { - $ex = new SignatureInvalidException('Signature verification failed'); - $ex->setPayload($payload); - throw $ex; + throw new SignatureInvalidException('Signature verification failed'); } // Check the nbf if it is defined. This is the time that the diff --git a/src/JWTExceptionInterface.php b/src/JWTExceptionWithPayloadInterface.php similarity index 89% rename from src/JWTExceptionInterface.php rename to src/JWTExceptionWithPayloadInterface.php index 8277eb30..7933ed68 100644 --- a/src/JWTExceptionInterface.php +++ b/src/JWTExceptionWithPayloadInterface.php @@ -1,7 +1,7 @@ payload = $payload; - } - - public function getPayload(): object - { - return $this->payload; - } } diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 0145d373..8c901d92 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -137,23 +137,6 @@ public function testBeforeValidExceptionPayload() } } - public function testSignatureInvalidExceptionPayload() - { - $payload = [ - 'message' => 'abc', - 'exp' => time() + 20, // time in the future - ]; - $encoded = JWT::encode($payload, 'my_key', 'HS256'); - $this->expectException(SignatureInvalidException::class); - try { - JWT::decode($encoded, new Key('my_key2', 'HS256')); - } catch (SignatureInvalidException $e) { - $exceptionPayload = (array) $e->getPayload(); - $this->assertEquals($exceptionPayload, $payload); - throw $e; - } - } - public function testValidTokenWithNbf() { $payload = [