From d06abd97d5d1544f5fc1dd4c1ad930117d9cb854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Tue, 21 Feb 2023 23:45:35 +0100 Subject: [PATCH 1/3] Support other PSR-20 implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This promotes better interoperability by allowing users to plug any Clock implementation that follows PSR-20 - we still fallback to lcobucci/clock. Signed-off-by: Luís Cobucci --- composer.json | 3 +- composer.lock | 2 +- src/JwtFacade.php | 2 +- src/Validation/Constraint/LooseValidAt.php | 2 +- src/Validation/Constraint/StrictValidAt.php | 2 +- tests/JwtFacadeTest.php | 40 ++++++++++++++++++--- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index daa066b2..a22ad4ac 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "ext-json": "*", "ext-openssl": "*", "ext-sodium": "*", - "lcobucci/clock": "^3.0.0" + "lcobucci/clock": "^3.0.0", + "psr/clock": "^1.0" }, "require-dev": { "infection/infection": "^0.26.19", diff --git a/composer.lock b/composer.lock index 41201820..36f722c5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0845c883bfa853ed0065aa7af416eac1", + "content-hash": "6213231e73ab90ed5ac862e518dbee2b", "packages": [ { "name": "lcobucci/clock", diff --git a/src/JwtFacade.php b/src/JwtFacade.php index 3a08291a..cbd47160 100644 --- a/src/JwtFacade.php +++ b/src/JwtFacade.php @@ -5,7 +5,6 @@ use Closure; use DateTimeImmutable; -use Lcobucci\Clock\Clock; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Encoding\ChainedFormatter; use Lcobucci\JWT\Encoding\JoseEncoder; @@ -14,6 +13,7 @@ use Lcobucci\JWT\Validation\SignedWith; use Lcobucci\JWT\Validation\ValidAt; use Lcobucci\JWT\Validation\Validator; +use Psr\Clock\ClockInterface as Clock; use function assert; diff --git a/src/Validation/Constraint/LooseValidAt.php b/src/Validation/Constraint/LooseValidAt.php index 90a459a9..9be0cc40 100644 --- a/src/Validation/Constraint/LooseValidAt.php +++ b/src/Validation/Constraint/LooseValidAt.php @@ -5,10 +5,10 @@ use DateInterval; use DateTimeInterface; -use Lcobucci\Clock\Clock; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\ConstraintViolation; use Lcobucci\JWT\Validation\ValidAt as ValidAtInterface; +use Psr\Clock\ClockInterface as Clock; final class LooseValidAt implements ValidAtInterface { diff --git a/src/Validation/Constraint/StrictValidAt.php b/src/Validation/Constraint/StrictValidAt.php index 68994766..93db0a3a 100644 --- a/src/Validation/Constraint/StrictValidAt.php +++ b/src/Validation/Constraint/StrictValidAt.php @@ -5,11 +5,11 @@ use DateInterval; use DateTimeInterface; -use Lcobucci\Clock\Clock; use Lcobucci\JWT\Token; use Lcobucci\JWT\UnencryptedToken; use Lcobucci\JWT\Validation\ConstraintViolation; use Lcobucci\JWT\Validation\ValidAt as ValidAtInterface; +use Psr\Clock\ClockInterface as Clock; final class StrictValidAt implements ValidAtInterface { diff --git a/tests/JwtFacadeTest.php b/tests/JwtFacadeTest.php index 3255b25e..ed3caea4 100644 --- a/tests/JwtFacadeTest.php +++ b/tests/JwtFacadeTest.php @@ -17,6 +17,7 @@ use Lcobucci\JWT\Validation\Constraint\StrictValidAt; use Lcobucci\JWT\Validation\RequiredConstraintsViolated; use PHPUnit\Framework\TestCase; +use Psr\Clock\ClockInterface; /** * @covers ::__construct @@ -65,11 +66,9 @@ private function createToken(): string return (new JwtFacade(clock: $this->clock))->issue( $this->signer, $this->key, - function (Builder $builder, DateTimeImmutable $issuedAt): Builder { - return $builder + fn (Builder $builder, DateTimeImmutable $issuedAt): Builder => $builder ->expiresAt($issuedAt->modify('+5 minutes')) - ->issuedBy($this->issuer); - }, + ->issuedBy($this->issuer), )->toString(); } @@ -258,4 +257,37 @@ public function parserForNonUnencryptedTokens(): void new IssuedBy($this->issuer), ); } + + /** + * @test + * + * @covers ::issue + * @covers ::parse + */ + public function customPsrClock(): void + { + $clock = new class () implements ClockInterface { + public function now(): DateTimeImmutable + { + return new DateTimeImmutable('2021-07-10'); + } + }; + + $facade = new JwtFacade(clock: $clock); + + $token = $facade->issue( + $this->signer, + $this->key, + static fn (Builder $builder): Builder => $builder, + ); + + self::assertEquals( + $token, + $facade->parse( + $token->toString(), + new SignedWith($this->signer, $this->key), + new StrictValidAt($clock), + ), + ); + } } From 3aa05aa8076d3950c29c2b710f78b802d17ea9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Thu, 23 Feb 2023 22:11:20 +0100 Subject: [PATCH 2/3] Move dependency on lcobucci/clock to dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows users to choose which PSR-20 they want to have installed in their systems, without changing our test suite that much. Signed-off-by: Luís Cobucci --- composer.json | 5 +- composer.lock | 130 +++++++++++++++++++++++----------------------- src/JwtFacade.php | 8 ++- 3 files changed, 75 insertions(+), 68 deletions(-) diff --git a/composer.json b/composer.json index a22ad4ac..08252062 100644 --- a/composer.json +++ b/composer.json @@ -22,11 +22,11 @@ "ext-json": "*", "ext-openssl": "*", "ext-sodium": "*", - "lcobucci/clock": "^3.0.0", "psr/clock": "^1.0" }, "require-dev": { "infection/infection": "^0.26.19", + "lcobucci/clock": "^3.0", "lcobucci/coding-standard": "^9.0", "phpbench/phpbench": "^1.2.8", "phpstan/extension-installer": "^1.2", @@ -36,6 +36,9 @@ "phpstan/phpstan-strict-rules": "^1.5.0", "phpunit/phpunit": "^10.0.12" }, + "suggest": { + "lcobucci/clock": ">= 3.0" + }, "autoload": { "psr-4": { "Lcobucci\\JWT\\": "src" diff --git a/composer.lock b/composer.lock index 36f722c5..6c45daf4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,72 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6213231e73ab90ed5ac862e518dbee2b", + "content-hash": "c0d16b3be9c2f7b5b9d81fb835ad6d0f", "packages": [ - { - "name": "lcobucci/clock", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc", - "shasum": "" - }, - "require": { - "php": "~8.1.0 || ~8.2.0", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.26", - "lcobucci/coding-standard": "^9.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.27" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2022-12-19T15:00:24+00:00" - }, { "name": "psr/clock", "version": "1.0.0", @@ -1067,6 +1003,70 @@ }, "time": "2022-04-13T08:02:27+00:00" }, + { + "name": "lcobucci/clock", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc", + "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc", + "shasum": "" + }, + "require": { + "php": "~8.1.0 || ~8.2.0", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "infection/infection": "^0.26", + "lcobucci/coding-standard": "^9.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^9.5.27" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "support": { + "issues": "https://github.com/lcobucci/clock/issues", + "source": "https://github.com/lcobucci/clock/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2022-12-19T15:00:24+00:00" + }, { "name": "lcobucci/coding-standard", "version": "9.0.0", diff --git a/src/JwtFacade.php b/src/JwtFacade.php index cbd47160..90464757 100644 --- a/src/JwtFacade.php +++ b/src/JwtFacade.php @@ -5,7 +5,6 @@ use Closure; use DateTimeImmutable; -use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Encoding\ChainedFormatter; use Lcobucci\JWT\Encoding\JoseEncoder; use Lcobucci\JWT\Signer\Key; @@ -25,7 +24,12 @@ public function __construct( private readonly Parser $parser = new Token\Parser(new JoseEncoder()), ?Clock $clock = null, ) { - $this->clock = $clock ?? SystemClock::fromSystemTimezone(); + $this->clock = $clock ?? new class implements Clock { + public function now(): DateTimeImmutable + { + return new DateTimeImmutable(); + } + }; } /** @param Closure(Builder, DateTimeImmutable):Builder $customiseBuilder */ From 47307cc1057278a3895b9c5ce0ab68a0c627c806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Thu, 23 Feb 2023 22:37:50 +0100 Subject: [PATCH 3/3] Mention clock interoperability on docs too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Luís Cobucci --- docs/configuration.md | 3 ++- docs/quick-start.md | 6 ++++-- docs/upgrading.md | 10 ++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 884a7e5d..68ea2966 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -200,7 +200,8 @@ It configures which are the base constraints to be used during validation.