From 803cf79ef6320d0412267acf8815dd846f848883 Mon Sep 17 00:00:00 2001 From: V13Axel Date: Tue, 8 Aug 2023 14:47:17 -0400 Subject: [PATCH 1/5] Initializing Signer_And_Formatter_Config for empty Pull Request From 5162a403ed3084bdc9cc3ac6dab34c11eec2873d Mon Sep 17 00:00:00 2001 From: V13Axel Date: Tue, 8 Aug 2023 15:07:33 -0400 Subject: [PATCH 2/5] Move formatter and signer into config --- config/jwt.php | 12 ++++++++++-- src/Client.php | 10 ++++++---- src/JWTServiceProvider.php | 7 ++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/config/jwt.php b/config/jwt.php index 4f99d71..d275418 100644 --- a/config/jwt.php +++ b/config/jwt.php @@ -1,8 +1,14 @@ env('JWT_SIGNING_KEY', env('APP_KEY')), + // Default Signer class + 'signer' => \Lcobucci\JWT\Signer\Hmac\Sha256::class, + // Default lifetime in seconds 'lifetime' => env('JWT_LIFETIME', 600), @@ -17,5 +23,7 @@ 'validate' => [ // If you really need to avoid automatic audience validation 'audience' => env('JWT_VALIDATE_AUDIENCE', true), - ] -]; \ No newline at end of file + ], + + 'chained_formatter' => ChainedFormatter::default(), +]; diff --git a/src/Client.php b/src/Client.php index 67a986e..b3dba9a 100644 --- a/src/Client.php +++ b/src/Client.php @@ -11,7 +11,7 @@ use Illuminate\Support\Traits\ForwardsCalls; use Lcobucci\JWT\Encoding\ChainedFormatter; use Lcobucci\JWT\Encoding\JoseEncoder; -use Lcobucci\JWT\Signer\Hmac\Sha256; +use Lcobucci\JWT\Signer; use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Token\Builder; use Lcobucci\JWT\Token\Plain; @@ -28,11 +28,13 @@ class Client public function __construct( protected string $signingKey, + protected Signer $signer, + protected ChainedFormatter $chainedFormatter, protected int|CarbonImmutable $lifetime, protected string $issuer, protected string $audience) { - $this->builder = new Builder(new JoseEncoder(), ChainedFormatter::default()); + $this->builder = new Builder(new JoseEncoder(), $this->chainedFormatter); } public function signWith(string $signingKey): self @@ -64,7 +66,7 @@ public function getToken(): Plain in_array('issuedBy', $this->configures) || $this->issuedBy($this->issuer()); in_array('expiresAt', $this->configures) || $this->lifetime($this->lifetime); - return $this->builder->getToken(new Sha256(), InMemory::plainText($this->signingKey())); + return $this->builder->getToken($this->signer, InMemory::plainText($this->signingKey())); } public function __toString(): string @@ -127,4 +129,4 @@ public function parse(string $jwt): ParsedToken { return ParsedToken::fromString($jwt); } -} \ No newline at end of file +} diff --git a/src/JWTServiceProvider.php b/src/JWTServiceProvider.php index 5552886..399b087 100644 --- a/src/JWTServiceProvider.php +++ b/src/JWTServiceProvider.php @@ -36,8 +36,13 @@ public function register(): void $key = base64_decode(substr($key, 7)); } + $signer = config('jwt.signer'); + $chainedFormatter = config('jwt.chained_formatter'); + return new Client( $key, + new $signer(), + $chainedFormatter, config('jwt.lifetime'), config('jwt.issuer'), config('jwt.audience') @@ -49,4 +54,4 @@ public function provides(): array { return [Client::class]; } -} \ No newline at end of file +} From 5f4bbb3992ffeb729e71b30471abbe21e4579eac Mon Sep 17 00:00:00 2001 From: V13Axel Date: Tue, 8 Aug 2023 15:13:59 -0400 Subject: [PATCH 3/5] Include defaults in test case setup --- tests/ClientTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index fbcc9c6..792f994 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,6 +2,7 @@ use Carbon\Carbon; use Carbon\CarbonImmutable; +use Lcobucci\JWT\Encoding\ChainedFormatter; use Lcobucci\JWT\Encoding\JoseEncoder; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Key\InMemory; @@ -32,6 +33,8 @@ protected function getEnvironmentSetUp($app): void 'audience' => 'myappaud', 'issuer' => 'myappiss', 'lifetime' => 900, + 'signer' => \Lcobucci\JWT\Signer\Hmac\Sha256::class, + 'chained_formatter' => ChainedFormatter::default(), ]]); } @@ -132,4 +135,4 @@ public function testQuickGet() ) ); } -} \ No newline at end of file +} From 2a088c748695fecf8e486b1daf1dec0b1f68ff66 Mon Sep 17 00:00:00 2001 From: V13Axel Date: Tue, 8 Aug 2023 16:17:15 -0400 Subject: [PATCH 4/5] signer config test using rsa --- tests/ClientTest.php | 32 +++++++++++++++++++++++ tests/keys/jwtRS256.key | 51 +++++++++++++++++++++++++++++++++++++ tests/keys/jwtRS256.key.pub | 14 ++++++++++ 3 files changed, 97 insertions(+) create mode 100644 tests/keys/jwtRS256.key create mode 100644 tests/keys/jwtRS256.key.pub diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 792f994..0156247 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -116,6 +116,38 @@ public function testLifetime() $this->assertTrue($token->isExpired(CarbonImmutable::now()->addMinutes(5))); } + public function testDefaultSigner() + { + $token = JWT::expiresAt(Carbon::now()->addMinutes(10))->getToken(); + + $this->assertTrue( + (new Validator())->validate( + $token, + new SignedWith(new Sha256(), InMemory::plainText("thisissigningkeythisissigningkey")) + ) + ); + } + + public function testRsaSha256Signer() + { + $rsa = new \Lcobucci\JWT\Signer\Rsa\Sha256(); + $privateKey = file_get_contents(__DIR__ . '/keys/jwtRS256.key'); + $publicKey = InMemory::plainText(file_get_contents(__DIR__ . '/keys/jwtRS256.key.pub')); + + config(['jwt.signer' => \Lcobucci\JWT\Signer\Rsa\Sha256::class]); + + $token = JWT::get('test-id', ['foo' => 'bar'], 1800, $privateKey); + + $parsedToken = (new Parser(new JoseEncoder()))->parse($token); + + $this->assertTrue( + (new Validator())->validate( + $parsedToken, + new SignedWith($rsa, $publicKey) + ) + ); + } + public function testQuickGet() { $jwt = JWT::get('test-id', ['foo' => 'bar'], 1800); diff --git a/tests/keys/jwtRS256.key b/tests/keys/jwtRS256.key new file mode 100644 index 0000000..d57ec1a --- /dev/null +++ b/tests/keys/jwtRS256.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/tests/keys/jwtRS256.key.pub b/tests/keys/jwtRS256.key.pub new file mode 100644 index 0000000..00530bb --- /dev/null +++ b/tests/keys/jwtRS256.key.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt/kVyHFiIz1uQdiL2ECX +xVGqy2brucaCmp5Tp1uVvgx17v/x2fhzBqBSJvpZ37s41klVQP1ZMLoqoB9jkuui +KJxnjCJMA7YQZEwI9Z+mZETdnDF10IY/uC+9aGGmDdcDoKjkPKsXcjNypZpclHWn +hmeY4+L+Ep9fdx4ust5j0lYIaEZaInM0itZrepVENjMwFCsnr7DZNZSuWljZ9gqu +D1A20uLOutTxCRpRB/3I+qOwUdHRG3w6hyE4pLNhqWsjVMVCYps9e/YePmBuDnUR +RWe/5Kpnai/ojVzKjDzn+z2Y9F8htR46Tpg/3PUpNcEwK2WOFN4CaJsC7leXy5TO +4U/f9sBlJ/ER5Z9CMIZKInK+QvOJwExelyWfDZzGuTfRHxWl/HuNQLUKciuqzwKj +DfV4wEdQjz7SaLyTjAQzy9ZArylA3pEzJmlnWVdCTi5Xt+q5mWtfbZUY+XeIuvjq +A1u/dCXiPpArQgpTfwb3CKxLiXRvRV73UQ3moTNS/4XP33eqY0HXlmW9HvhUVhty +AT6/zLbRx+dLyq89kvgt1kUXke4cRxDbrajlKurrQSSp8BZ+MQQrvT1cucuNAjhz +OQw/Jlj4Is6OgoUAENX4az0TjWmhb41gplZGfhfF7f5YHattY55HH/jovB5mO2Jy +jOJhDZN3soMdwwO4lYysZz0CAwEAAQ== +-----END PUBLIC KEY----- From 1b63ba898820e8839552d1053108f59b87b8e3e8 Mon Sep 17 00:00:00 2001 From: V13Axel Date: Tue, 8 Aug 2023 16:28:14 -0400 Subject: [PATCH 5/5] Formatter config tests --- tests/ClientTest.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 0156247..d070875 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -148,6 +148,34 @@ public function testRsaSha256Signer() ); } + public function testDefaultTimestampFormatter() + { + $time = Carbon::now()->addMinutes(10); + $token = JWT::expiresAt($time)->getToken(); + + $parts = array_map('base64_decode', explode('.', $token->toString())); + + $this->assertEquals( + $time->format('U.u'), + json_decode($parts[1])->exp + ); + } + + public function testUnixTimestampFormatter() + { + config(['jwt.chained_formatter' => ChainedFormatter::withUnixTimestampDates()]); + + $time = Carbon::now()->addMinutes(10); + $token = JWT::expiresAt($time)->getToken(); + + $parts = array_map('base64_decode', explode('.', $token->toString())); + + $this->assertEquals( + $time->format('U'), + json_decode($parts[1])->exp + ); + } + public function testQuickGet() { $jwt = JWT::get('test-id', ['foo' => 'bar'], 1800); @@ -168,3 +196,4 @@ public function testQuickGet() ); } } +