From c95a4f0d4f27c4faa711f576e650e85e0cb8c412 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 10 Nov 2020 14:01:07 +0100 Subject: [PATCH 01/33] PHP 8 Support --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 658cc6553..0bae02857 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": ">=7.2.0", "ext-openssl": "*", "league/event": "^2.2", - "lcobucci/jwt": "^3.3.1", + "lcobucci/jwt": "^3.4 || ^4.0", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.2.1", "ext-json": "*" @@ -16,7 +16,7 @@ "phpunit/phpunit": "^8.5.4 || ^9.1.3", "laminas/laminas-diactoros": "^2.3.0", "phpstan/phpstan": "^0.11.19", - "phpstan/phpstan-phpunit": "^0.11.2", + "phpstan/phpstan-phpunit": "^0.12.6", "roave/security-advisories": "dev-master" }, "repositories": [ From a9f39f0280458a1f317d8e0ac56b41d44b3fdd2e Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Nov 2020 00:34:03 +0000 Subject: [PATCH 02/33] Update composer dependencies --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 0bae02857..7cc4e8bd6 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": ">=7.2.0", "ext-openssl": "*", "league/event": "^2.2", - "lcobucci/jwt": "^3.4 || ^4.0", + "lcobucci/jwt": "^3.4@dev || ^4.0@dev", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.2.1", "ext-json": "*" @@ -15,8 +15,8 @@ "require-dev": { "phpunit/phpunit": "^8.5.4 || ^9.1.3", "laminas/laminas-diactoros": "^2.3.0", - "phpstan/phpstan": "^0.11.19", - "phpstan/phpstan-phpunit": "^0.12.6", + "phpstan/phpstan": "^0.12.56", + "phpstan/phpstan-phpunit": "^0.12.16", "roave/security-advisories": "dev-master" }, "repositories": [ From 3916ee7d92b46f824813c8cb8683b1c491f51a55 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Nov 2020 00:55:31 +0000 Subject: [PATCH 03/33] Add version 8 to php versions to test --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e9f2343bb..d82fe6203 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: true matrix: - php: [7.2, 7.3, 7.4] + php: [7.2, 7.3, 7.4, 8.0] stability: [prefer-lowest, prefer-stable] name: PHP ${{ matrix.php }} - ${{ matrix.stability }} From 531eb4d5b76d338df6bb47c899e7dc0f5a056e5a Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:22:38 +0000 Subject: [PATCH 04/33] Update composer dependencies for examples --- examples/composer.json | 2 +- examples/composer.lock | 167 +++++++++++++++++++++++++++-------------- 2 files changed, 113 insertions(+), 56 deletions(-) diff --git a/examples/composer.json b/examples/composer.json index e1c44efc8..de2bd7162 100644 --- a/examples/composer.json +++ b/examples/composer.json @@ -4,7 +4,7 @@ }, "require-dev": { "league/event": "^2.2", - "lcobucci/jwt": "^3.3", + "lcobucci/jwt": "^3.4@dev || ^4.0@beta", "psr/http-message": "^1.0", "defuse/php-encryption": "^2.2", "laminas/laminas-diactoros": "^2.1.2" diff --git a/examples/composer.lock b/examples/composer.lock index 6de13b69f..d732e6f0b 100644 --- a/examples/composer.lock +++ b/examples/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": "5bcbefe6cdff10a268399b1d138647ea", + "content-hash": "afc9a862edd0bfe93a224a28b1abf75d", "packages": [ { "name": "nikic/fast-route", @@ -54,29 +54,29 @@ }, { "name": "pimple/pimple", - "version": "v3.2.3", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" + "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/e55d12f9d6a0e7f9c85992b73df1267f46279930", + "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930", "shasum": "" }, "require": { - "php": ">=5.3.0", + "php": "^7.2.5", "psr/container": "^1.0" }, "require-dev": { - "symfony/phpunit-bridge": "^3.2" + "symfony/phpunit-bridge": "^3.4|^4.4|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "3.3.x-dev" } }, "autoload": { @@ -95,12 +95,12 @@ } ], "description": "Pimple, a simple Dependency Injection Container", - "homepage": "http://pimple.sensiolabs.org", + "homepage": "https://pimple.symfony.com", "keywords": [ "container", "dependency injection" ], - "time": "2018-01-21T07:42:36+00:00" + "time": "2020-03-03T09:12:48+00:00" }, { "name": "psr/container", @@ -341,46 +341,50 @@ }, { "name": "laminas/laminas-diactoros", - "version": "2.2.1", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "064f0b20e832bb232d0311f915c7422fef1b1857" + "reference": "4ff7400c1c12e404144992ef43c8b733fd9ad516" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/064f0b20e832bb232d0311f915c7422fef1b1857", - "reference": "064f0b20e832bb232d0311f915c7422fef1b1857", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/4ff7400c1c12e404144992ef43c8b733fd9ad516", + "reference": "4ff7400c1c12e404144992ef43c8b733fd9ad516", "shasum": "" }, "require": { "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^7.1", + "php": "^7.3 || ~8.0.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0" }, + "conflict": { + "phpspec/prophecy": "<1.9.0" + }, "provide": { "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "replace": { - "zendframework/zend-diactoros": "self.version" + "zendframework/zend-diactoros": "^2.2.1" }, "require-dev": { "ext-curl": "*", "ext-dom": "*", + "ext-gd": "*", "ext-libxml": "*", - "http-interop/http-factory-tests": "^0.5.0", + "http-interop/http-factory-tests": "^0.8.0", "laminas/laminas-coding-standard": "~1.0.0", - "php-http/psr7-integration-tests": "dev-master", - "phpunit/phpunit": "^7.0.2" + "php-http/psr7-integration-tests": "^1.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "2.1.x-dev", - "dev-develop": "2.2.x-dev", - "dev-release-1.8": "1.8.x-dev" + "laminas": { + "config-provider": "Laminas\\Diactoros\\ConfigProvider", + "module": "Laminas\\Diactoros" } }, "autoload": { @@ -416,37 +420,34 @@ "http", "laminas", "psr", + "psr-17", "psr-7" ], - "time": "2019-12-31T16:41:56+00:00" + "time": "2020-11-18T18:39:28+00:00" }, { "name": "laminas/laminas-zendframework-bridge", - "version": "1.0.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-zendframework-bridge.git", - "reference": "32d7095e436a31b8d98e485a5c63d70df74915a8" + "reference": "6ede70583e101030bcace4dcddd648f760ddf642" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/32d7095e436a31b8d98e485a5c63d70df74915a8", - "reference": "32d7095e436a31b8d98e485a5c63d70df74915a8", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642", + "reference": "6ede70583e101030bcace4dcddd648f760ddf642", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^5.6 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1", + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev", - "dev-develop": "1.1.x-dev" - }, "laminas": { "module": "Laminas\\ZendFrameworkBridge" } @@ -470,38 +471,92 @@ "laminas", "zf" ], - "time": "2019-12-31T15:24:03+00:00" + "time": "2020-09-14T14:23:00+00:00" + }, + { + "name": "lcobucci/clock", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/353d83fe2e6ae95745b16b3d911813df6a05bfb3", + "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "infection/infection": "^0.17", + "lcobucci/coding-standard": "^6.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/php-code-coverage": "9.1.4", + "phpunit/phpunit": "9.3.7" + }, + "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", + "time": "2020-08-27T18:56:02+00:00" }, { "name": "lcobucci/jwt", - "version": "3.3.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18" + "reference": "144de5ad99590cac0139a688c26bbf42539aeed9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a11ec5f4b4d75d1fcd04e133dede4c317aac9e18", - "reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/144de5ad99590cac0139a688c26bbf42539aeed9", + "reference": "144de5ad99590cac0139a688c26bbf42539aeed9", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-openssl": "*", - "php": "^5.6 || ^7.0" + "lcobucci/clock": "^2.0", + "php": "^7.4 || ^8.0" }, "require-dev": { - "mikey179/vfsstream": "~1.5", - "phpmd/phpmd": "~2.2", - "phpunit/php-invoker": "~1.1", - "phpunit/phpunit": "^5.7 || ^7.3", - "squizlabs/php_codesniffer": "~2.3" + "infection/infection": "^0.20", + "lcobucci/coding-standard": "^6.0", + "mikey179/vfsstream": "^1.6", + "phpbench/phpbench": "^0.17", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/php-invoker": "^3.1", + "phpunit/phpunit": "^9.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -515,7 +570,7 @@ ], "authors": [ { - "name": "Luís Otávio Cobucci Oblonczyk", + "name": "Luís Cobucci", "email": "lcobucci@gmail.com", "role": "Developer" } @@ -525,7 +580,7 @@ "JWS", "jwt" ], - "time": "2019-05-24T18:30:49+00:00" + "time": "2020-11-23T04:40:16+00:00" }, { "name": "league/event", @@ -579,20 +634,20 @@ }, { "name": "paragonie/random_compat", - "version": "v9.99.99", + "version": "v9.99.100", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", "shasum": "" }, "require": { - "php": "^7" + "php": ">= 7" }, "require-dev": { "phpunit/phpunit": "4.*|5.*", @@ -620,7 +675,7 @@ "pseudorandom", "random" ], - "time": "2018-07-02T15:55:56+00:00" + "time": "2020-10-15T08:29:30+00:00" }, { "name": "psr/http-factory", @@ -677,7 +732,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "lcobucci/jwt": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": [], From f140ce6ef1f27e0f1a8c3b21a6f7213ef858e7ac Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:24:03 +0000 Subject: [PATCH 05/33] Update composer dependencies --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7cc4e8bd6..238aad49f 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": ">=7.2.0", "ext-openssl": "*", "league/event": "^2.2", - "lcobucci/jwt": "^3.4@dev || ^4.0@dev", + "lcobucci/jwt": "^3.4@dev || ^4.0@beta", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.2.1", "ext-json": "*" From f8f832004cb86943df7cfb738e3392c939161da6 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:25:39 +0000 Subject: [PATCH 06/33] Update to use version 4 API of JWT package --- .../BearerTokenValidator.php | 82 ++++++++++++------- src/Entities/Traits/AccessTokenTrait.php | 39 +++++++-- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 213ecf893..46797b778 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -9,17 +9,25 @@ namespace League\OAuth2\Server\AuthorizationValidators; -use BadMethodCallException; -use InvalidArgumentException; -use Lcobucci\JWT\Parser; +use DateTimeImmutable; +use DateTimeZone; +use Lcobucci\Clock\FrozenClock; +use Lcobucci\Clock\SystemClock; +use Lcobucci\JWT\Configuration; +use Lcobucci\JWT\Encoding\CannotDecodeContent; +use Lcobucci\JWT\Signer\Key\InMemory; +use Lcobucci\JWT\Signer\Key\LocalFileReference; use Lcobucci\JWT\Signer\Rsa\Sha256; -use Lcobucci\JWT\ValidationData; +use Lcobucci\JWT\Token\InvalidTokenStructure; +use Lcobucci\JWT\Token\UnsupportedHeaderFound; +use Lcobucci\JWT\Validation\Constraint\SignedWith; +use Lcobucci\JWT\Validation\Constraint\ValidAt; +use Lcobucci\JWT\Validation\RequiredConstraintsViolated; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\CryptTrait; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use Psr\Http\Message\ServerRequestInterface; -use RuntimeException; class BearerTokenValidator implements AuthorizationValidatorInterface { @@ -35,6 +43,11 @@ class BearerTokenValidator implements AuthorizationValidatorInterface */ protected $publicKey; + /** + * @var Configuration + */ + private $jwtConfiguration; + /** * @param AccessTokenRepositoryInterface $accessTokenRepository */ @@ -51,6 +64,21 @@ public function __construct(AccessTokenRepositoryInterface $accessTokenRepositor public function setPublicKey(CryptKey $key) { $this->publicKey = $key; + + $this->initJwtConfiguration(); + } + + private function initJwtConfiguration() + { + $this->jwtConfiguration = Configuration::forSymmetricSigner( + new Sha256(), + InMemory::empty() + ); + + $this->jwtConfiguration->setValidationConstraints( + new ValidAt(new SystemClock(new DateTimeZone(date_default_timezone_get()))), + new SignedWith(new Sha256(), LocalFileReference::file($this->publicKey->getKeyPath())) + ); } /** @@ -67,40 +95,38 @@ public function validateAuthorization(ServerRequestInterface $request) try { // Attempt to parse and validate the JWT - $token = (new Parser())->parse($jwt); - try { - if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) { - throw OAuthServerException::accessDenied('Access token could not be verified'); - } - } catch (BadMethodCallException $exception) { - throw OAuthServerException::accessDenied('Access token is not signed', null, $exception); - } + $token = $this->jwtConfiguration->parser()->parse($jwt); - // Ensure access token hasn't expired - $data = new ValidationData(); - $data->setCurrentTime(\time()); + /*$this->jwtConfiguration->setValidationConstraints( + new SignedWith( + new Sha256(), + LocalFileReference::file($this->publicKey->getKeyPath()) + ) + );*/ - if ($token->validate($data) === false) { - throw OAuthServerException::accessDenied('Access token is invalid'); + $constraints = $this->jwtConfiguration->validationConstraints(); + + try { + $this->jwtConfiguration->validator()->assert($token, ...$constraints); + } catch (RequiredConstraintsViolated $exception) { + throw OAuthServerException::accessDenied('Access token could not be verified'); } - } catch (InvalidArgumentException $exception) { - // JWT couldn't be parsed so return the request as is + } catch (CannotDecodeContent | InvalidTokenStructure | UnsupportedHeaderFound $exception) { throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception); - } catch (RuntimeException $exception) { - // JWT couldn't be parsed so return the request as is - throw OAuthServerException::accessDenied('Error while decoding to JSON', null, $exception); } + $claims = $token->claims(); + // Check if token has been revoked - if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) { + if ($this->accessTokenRepository->isAccessTokenRevoked($claims->get('jti'))) { throw OAuthServerException::accessDenied('Access token has been revoked'); } // Return the request with additional attributes return $request - ->withAttribute('oauth_access_token_id', $token->getClaim('jti')) - ->withAttribute('oauth_client_id', $token->getClaim('aud')) - ->withAttribute('oauth_user_id', $token->getClaim('sub')) - ->withAttribute('oauth_scopes', $token->getClaim('scopes')); + ->withAttribute('oauth_access_token_id', $claims->get('jti')) + ->withAttribute('oauth_client_id', $claims->get('aud')) + ->withAttribute('oauth_user_id', $claims->get('sub')) + ->withAttribute('oauth_scopes', $claims->get('scopes')); } } diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php index 48e3d1ac4..285e93909 100644 --- a/src/Entities/Traits/AccessTokenTrait.php +++ b/src/Entities/Traits/AccessTokenTrait.php @@ -10,8 +10,9 @@ namespace League\OAuth2\Server\Entities\Traits; use DateTimeImmutable; -use Lcobucci\JWT\Builder; -use Lcobucci\JWT\Signer\Key; +use Lcobucci\JWT\Configuration; +use Lcobucci\JWT\Signer\Key\InMemory; +use Lcobucci\JWT\Signer\Key\LocalFileReference; use Lcobucci\JWT\Signer\Rsa\Sha256; use Lcobucci\JWT\Token; use League\OAuth2\Server\CryptKey; @@ -25,6 +26,11 @@ trait AccessTokenTrait */ private $privateKey; + /** + * @var Configuration + */ + private $jwtConfiguration; + /** * Set the private key used to encrypt this access token. */ @@ -33,6 +39,19 @@ public function setPrivateKey(CryptKey $privateKey) $this->privateKey = $privateKey; } + public function initJwtConfiguration() + { + $privateKeyPassPhrase = $this->privateKey->getPassPhrase(); + + $verificationKey = empty($privateKeyPassPhrase) ? InMemory::empty() : $privateKeyPassPhrase; + + $this->jwtConfiguration = Configuration::forAsymmetricSigner( + new Sha256(), + LocalFileReference::file($this->privateKey->getKeyPath()), + $verificationKey + ); + } + /** * Generate a JWT from the access token * @@ -40,17 +59,19 @@ public function setPrivateKey(CryptKey $privateKey) * * @return Token */ - private function convertToJWT(CryptKey $privateKey) + private function convertToJWT() { - return (new Builder()) + $this->initJwtConfiguration(); + + return $this->jwtConfiguration->builder() ->permittedFor($this->getClient()->getIdentifier()) ->identifiedBy($this->getIdentifier()) - ->issuedAt(\time()) - ->canOnlyBeUsedAfter(\time()) - ->expiresAt($this->getExpiryDateTime()->getTimestamp()) + ->issuedAt(new DateTimeImmutable()) + ->canOnlyBeUsedAfter(new DateTimeImmutable()) + ->expiresAt($this->getExpiryDateTime()) ->relatedTo((string) $this->getUserIdentifier()) ->withClaim('scopes', $this->getScopes()) - ->getToken(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase())); + ->getToken($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey()); } /** @@ -58,7 +79,7 @@ private function convertToJWT(CryptKey $privateKey) */ public function __toString() { - return (string) $this->convertToJWT($this->privateKey); + return $this->convertToJWT()->toString(); } /** From 32d7d7a283ec368adc74d6f0318c2fcf8fc0cfaa Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:26:25 +0000 Subject: [PATCH 07/33] Update tests to use version 4 of JWT package --- .../BearerTokenValidatorTest.php | 67 ++++++++++++++++--- tests/Grant/AuthCodeGrantTest.php | 25 +++++-- tests/Grant/ImplicitGrantTest.php | 13 +++- .../ResponseTypes/BearerResponseTypeTest.php | 4 +- 4 files changed, 92 insertions(+), 17 deletions(-) diff --git a/tests/AuthorizationValidators/BearerTokenValidatorTest.php b/tests/AuthorizationValidators/BearerTokenValidatorTest.php index c95c60531..e1e491a5a 100644 --- a/tests/AuthorizationValidators/BearerTokenValidatorTest.php +++ b/tests/AuthorizationValidators/BearerTokenValidatorTest.php @@ -2,33 +2,82 @@ namespace LeagueTests\AuthorizationValidators; +use DateInterval; +use DateTimeZone; +use Exception; +use DateTimeImmutable; use Laminas\Diactoros\ServerRequest; -use Lcobucci\JWT\Builder; +use Lcobucci\Clock\FrozenClock; +use Lcobucci\Clock\SystemClock; +use Lcobucci\JWT\Configuration; +use Lcobucci\JWT\Signer\Key\InMemory; +use Lcobucci\JWT\Signer\Key\LocalFileReference; +use Lcobucci\JWT\Signer\Rsa\Sha256; +use Lcobucci\JWT\Validation\Constraint\SignedWith; +use Lcobucci\JWT\Validation\Constraint\ValidAt; use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator; use League\OAuth2\Server\CryptKey; +use League\OAuth2\Server\Entities\AccessTokenEntityInterface; +use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use PHPUnit\Framework\TestCase; +use ReflectionClass; class BearerTokenValidatorTest extends TestCase { - public function testThrowExceptionWhenAccessTokenIsNotSigned() + + private $jwtConfiguration; + + public function testBearerTokenValidatorAcceptsValidToken() + { + $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); + + $bearerTokenValidator = new BearerTokenValidator($accessTokenRepositoryMock); + $bearerTokenValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key')); + + $bearerTokenValidatorReflection = new ReflectionClass(BearerTokenValidator::class); + $jwtConfiguration = $bearerTokenValidatorReflection->getProperty('jwtConfiguration'); + $jwtConfiguration->setAccessible(true); + + $validJwt = $jwtConfiguration->getValue($bearerTokenValidator)->builder() + ->permittedFor('client-id') + ->identifiedBy('token-id') + ->issuedAt(new DateTimeImmutable()) + ->canOnlyBeUsedAfter(new DateTimeImmutable()) + ->expiresAt((new DateTimeImmutable())->add(new DateInterval('PT1H'))) + ->relatedTo('user-id') + ->withClaim('scopes', 'scope1 scope2 scope3 scope4') + ->getToken(new Sha256(), LocalFileReference::file( __DIR__ . '/../Stubs/private.key')); + + $request = (new ServerRequest())->withHeader('authorization', \sprintf('Bearer %s', $validJwt->toString())); + + $response = $bearerTokenValidator->validateAuthorization($request); + + $this->assertArrayHasKey('authorization', $response->getHeaders()); + } + + public function testBearerTokenValidatorRejectsExpiredToken() { $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $bearerTokenValidator = new BearerTokenValidator($accessTokenRepositoryMock); $bearerTokenValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key')); - $unsignedJwt = (new Builder()) + $bearerTokenValidatorReflection = new ReflectionClass(BearerTokenValidator::class); + $jwtConfiguration = $bearerTokenValidatorReflection->getProperty('jwtConfiguration'); + $jwtConfiguration->setAccessible(true); + + $expiredJwt = $jwtConfiguration->getValue($bearerTokenValidator)->builder() ->permittedFor('client-id') - ->identifiedBy('token-id', true) - ->issuedAt(\time()) - ->canOnlyBeUsedAfter(\time()) - ->expiresAt(\time()) + ->identifiedBy('token-id') + ->issuedAt(new DateTimeImmutable()) + ->canOnlyBeUsedAfter(new DateTimeImmutable()) + ->expiresAt((new DateTimeImmutable())->sub(new DateInterval('PT1H'))) ->relatedTo('user-id') ->withClaim('scopes', 'scope1 scope2 scope3 scope4') - ->getToken(); + ->getToken(new Sha256(), LocalFileReference::file( __DIR__ . '/../Stubs/private.key')); - $request = (new ServerRequest())->withHeader('authorization', \sprintf('Bearer %s', $unsignedJwt)); + $request = (new ServerRequest())->withHeader('authorization', \sprintf('Bearer %s', $expiredJwt->toString())); $this->expectException(\League\OAuth2\Server\Exception\OAuthServerException::class); $this->expectExceptionCode(9); diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 28527aecf..a080da317 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1715,8 +1715,16 @@ public function testAuthCodeRepositoryUniqueConstraintCheck() $authCodeRepository = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(); $authCodeRepository->method('getNewAuthCode')->willReturn(new AuthCodeEntity()); - $authCodeRepository->expects($this->at(0))->method('persistNewAuthCode')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create()); - $authCodeRepository->expects($this->at(1))->method('persistNewAuthCode'); + $matcher = $this->exactly(2); + + $authCodeRepository + ->expects($matcher) + ->method('persistNewAuthCode') + ->willReturnCallback(function () use ($matcher) { + if ($matcher->getInvocationCount() === 1) { + throw UniqueTokenIdentifierConstraintViolationException::create(); + } + }); $grant = new AuthCodeGrant( $authCodeRepository, @@ -1797,8 +1805,17 @@ public function testRefreshTokenRepositoryUniqueConstraintCheck() $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); - $refreshTokenRepositoryMock->expects($this->at(0))->method('persistNewRefreshToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create()); - $refreshTokenRepositoryMock->expects($this->at(1))->method('persistNewRefreshToken'); + + $matcher = $this->exactly(2); + + $refreshTokenRepositoryMock + ->expects($matcher) + ->method('persistNewRefreshToken') + ->willReturnCallback(function () use ($matcher) { + if ($matcher->getInvocationCount() === 1) { + throw UniqueTokenIdentifierConstraintViolationException::create(); + } + }); $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), diff --git a/tests/Grant/ImplicitGrantTest.php b/tests/Grant/ImplicitGrantTest.php index 99fa3f57c..546450384 100644 --- a/tests/Grant/ImplicitGrantTest.php +++ b/tests/Grant/ImplicitGrantTest.php @@ -276,8 +276,17 @@ public function testAccessTokenRepositoryUniqueConstraintCheck() /** @var AccessTokenRepositoryInterface|\PHPUnit\Framework\MockObject\MockObject $accessTokenRepositoryMock */ $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock->method('getNewToken')->willReturn($accessToken); - $accessTokenRepositoryMock->expects($this->at(0))->method('persistNewAccessToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create()); - $accessTokenRepositoryMock->expects($this->at(1))->method('persistNewAccessToken')->willReturnSelf(); + + $matcher = $this->exactly(2); + + $accessTokenRepositoryMock + ->expects($matcher) + ->method('persistNewAccessToken') + ->willReturnCallback(function () use ($matcher) { + if ($matcher->getInvocationCount() === 1) { + throw UniqueTokenIdentifierConstraintViolationException::create(); + } + }); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); diff --git a/tests/ResponseTypes/BearerResponseTypeTest.php b/tests/ResponseTypes/BearerResponseTypeTest.php index 6dc24ff3b..a02b9a613 100644 --- a/tests/ResponseTypes/BearerResponseTypeTest.php +++ b/tests/ResponseTypes/BearerResponseTypeTest.php @@ -147,7 +147,7 @@ public function testDetermineAccessTokenInHeaderValidToken() $request = $authorizationValidator->validateAuthorization($request); $this->assertEquals('abcdef', $request->getAttribute('oauth_access_token_id')); - $this->assertEquals('clientName', $request->getAttribute('oauth_client_id')); + $this->assertContains('clientName', $request->getAttribute('oauth_client_id')); $this->assertEquals('123', $request->getAttribute('oauth_user_id')); $this->assertEquals([], $request->getAttribute('oauth_scopes')); } @@ -281,7 +281,7 @@ public function testDetermineMissingBearerInHeader() $authorizationValidator->validateAuthorization($request); } catch (OAuthServerException $e) { $this->assertEquals( - 'Error while decoding to JSON', + 'Error while decoding from JSON', $e->getHint() ); } From 6b6878b15e006d1f0d8b5b37c9877b8e4ff3f0ca Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:28:01 +0000 Subject: [PATCH 08/33] Temp removal of fail fast --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d82fe6203..4115fa99f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: php: [7.2, 7.3, 7.4, 8.0] stability: [prefer-lowest, prefer-stable] From ebd78d3fd5ad9fb929bbee18ff5d17b004193280 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 23 Nov 2020 23:31:20 +0000 Subject: [PATCH 09/33] Temp remove phpstan checks --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4115fa99f..1365facbd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,8 +32,8 @@ jobs: - name: Install dependencies run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress - - name: Run PHPStan - run: vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests + #- name: Run PHPStan + # run: vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests - name: Execute tests run: vendor/bin/phpunit --verbose --coverage-clover=coverage.clover From 109795b2a6c3f5fd9dccaeda39abf739e6ea7940 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 00:10:04 +0000 Subject: [PATCH 10/33] Fix config file for phpunit --- phpunit.xml.dist | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 92564086b..a3e34084d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,19 +6,9 @@ ./tests/ - - + + src - - src/ResponseTypes/DefaultTemplates - src/TemplateRenderer - - - - - - - + + From 9a581739f74148eb5c2ea1c96fee4c03a964c90e Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 00:14:28 +0000 Subject: [PATCH 11/33] Change to use plainText instead of empty --- src/AuthorizationValidators/BearerTokenValidator.php | 4 +--- src/Entities/Traits/AccessTokenTrait.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 46797b778..2b772d149 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -9,9 +9,7 @@ namespace League\OAuth2\Server\AuthorizationValidators; -use DateTimeImmutable; use DateTimeZone; -use Lcobucci\Clock\FrozenClock; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Encoding\CannotDecodeContent; @@ -72,7 +70,7 @@ private function initJwtConfiguration() { $this->jwtConfiguration = Configuration::forSymmetricSigner( new Sha256(), - InMemory::empty() + InMemory::plainText('') ); $this->jwtConfiguration->setValidationConstraints( diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php index 285e93909..fbb84eec8 100644 --- a/src/Entities/Traits/AccessTokenTrait.php +++ b/src/Entities/Traits/AccessTokenTrait.php @@ -43,7 +43,7 @@ public function initJwtConfiguration() { $privateKeyPassPhrase = $this->privateKey->getPassPhrase(); - $verificationKey = empty($privateKeyPassPhrase) ? InMemory::empty() : $privateKeyPassPhrase; + $verificationKey = empty($privateKeyPassPhrase) ? InMemory::plainText('') : $privateKeyPassPhrase; $this->jwtConfiguration = Configuration::forAsymmetricSigner( new Sha256(), From 7efa91cf486b7e9d6851818290654ad0b7356439 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 16:53:19 +0000 Subject: [PATCH 12/33] Fix backwards compatibility for aud --- .../BearerTokenValidator.php | 21 ++++++++++++------- .../ResponseTypes/BearerResponseTypeTest.php | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 2b772d149..4f6d93e7b 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -95,13 +95,6 @@ public function validateAuthorization(ServerRequestInterface $request) // Attempt to parse and validate the JWT $token = $this->jwtConfiguration->parser()->parse($jwt); - /*$this->jwtConfiguration->setValidationConstraints( - new SignedWith( - new Sha256(), - LocalFileReference::file($this->publicKey->getKeyPath()) - ) - );*/ - $constraints = $this->jwtConfiguration->validationConstraints(); try { @@ -123,8 +116,20 @@ public function validateAuthorization(ServerRequestInterface $request) // Return the request with additional attributes return $request ->withAttribute('oauth_access_token_id', $claims->get('jti')) - ->withAttribute('oauth_client_id', $claims->get('aud')) + ->withAttribute('oauth_client_id', $this->convertSingleRecordAudToString($claims->get('aud'))) ->withAttribute('oauth_user_id', $claims->get('sub')) ->withAttribute('oauth_scopes', $claims->get('scopes')); } + + /** + * Convert single record arrays into strings to ensure backwards compatibility between v4 and v3.x of lcobucci/jwt + * + * @param $aud + * + * @return array|string + */ + private function convertSingleRecordAudToString($aud) + { + return count($aud) === 1 ? $aud[0] : $aud; + } } diff --git a/tests/ResponseTypes/BearerResponseTypeTest.php b/tests/ResponseTypes/BearerResponseTypeTest.php index a02b9a613..a57820d00 100644 --- a/tests/ResponseTypes/BearerResponseTypeTest.php +++ b/tests/ResponseTypes/BearerResponseTypeTest.php @@ -147,7 +147,7 @@ public function testDetermineAccessTokenInHeaderValidToken() $request = $authorizationValidator->validateAuthorization($request); $this->assertEquals('abcdef', $request->getAttribute('oauth_access_token_id')); - $this->assertContains('clientName', $request->getAttribute('oauth_client_id')); + $this->assertEquals('clientName', $request->getAttribute('oauth_client_id')); $this->assertEquals('123', $request->getAttribute('oauth_user_id')); $this->assertEquals([], $request->getAttribute('oauth_scopes')); } From ad2a1be9dcc3b7c7ca2a4fa89eaabdc16e2a19ff Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 16:59:48 +0000 Subject: [PATCH 13/33] Drop support for PHP 7.2 --- composer.json | 4 ++-- src/AuthorizationValidators/BearerTokenValidator.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 238aad49f..d2ee11fce 100644 --- a/composer.json +++ b/composer.json @@ -4,10 +4,10 @@ "homepage": "https://oauth2.thephpleague.com/", "license": "MIT", "require": { - "php": ">=7.2.0", + "php": "^7.3 || ^8.0", "ext-openssl": "*", "league/event": "^2.2", - "lcobucci/jwt": "^3.4@dev || ^4.0@beta", + "lcobucci/jwt": "^3.4@dev || ^4.0@dev", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.2.1", "ext-json": "*" diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 4f6d93e7b..5c0e7e00d 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -130,6 +130,6 @@ public function validateAuthorization(ServerRequestInterface $request) */ private function convertSingleRecordAudToString($aud) { - return count($aud) === 1 ? $aud[0] : $aud; + return is_countable($aud) && count($aud) === 1 ? $aud[0] : $aud; } } From e85da747d5cc14983fb361959ec0d3f99b61729e Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:02:26 +0000 Subject: [PATCH 14/33] Fix style CI issues --- src/AuthorizationValidators/BearerTokenValidator.php | 4 ++-- .../BearerTokenValidatorTest.php | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 5c0e7e00d..a14cec494 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -74,7 +74,7 @@ private function initJwtConfiguration() ); $this->jwtConfiguration->setValidationConstraints( - new ValidAt(new SystemClock(new DateTimeZone(date_default_timezone_get()))), + new ValidAt(new SystemClock(new DateTimeZone(\date_default_timezone_get()))), new SignedWith(new Sha256(), LocalFileReference::file($this->publicKey->getKeyPath())) ); } @@ -130,6 +130,6 @@ public function validateAuthorization(ServerRequestInterface $request) */ private function convertSingleRecordAudToString($aud) { - return is_countable($aud) && count($aud) === 1 ? $aud[0] : $aud; + return \is_countable($aud) && \count($aud) === 1 ? $aud[0] : $aud; } } diff --git a/tests/AuthorizationValidators/BearerTokenValidatorTest.php b/tests/AuthorizationValidators/BearerTokenValidatorTest.php index e1e491a5a..0fafcbc5d 100644 --- a/tests/AuthorizationValidators/BearerTokenValidatorTest.php +++ b/tests/AuthorizationValidators/BearerTokenValidatorTest.php @@ -3,22 +3,12 @@ namespace LeagueTests\AuthorizationValidators; use DateInterval; -use DateTimeZone; -use Exception; use DateTimeImmutable; use Laminas\Diactoros\ServerRequest; -use Lcobucci\Clock\FrozenClock; -use Lcobucci\Clock\SystemClock; -use Lcobucci\JWT\Configuration; -use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\LocalFileReference; use Lcobucci\JWT\Signer\Rsa\Sha256; -use Lcobucci\JWT\Validation\Constraint\SignedWith; -use Lcobucci\JWT\Validation\Constraint\ValidAt; use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator; use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use PHPUnit\Framework\TestCase; use ReflectionClass; From 5dd01888056e9cbf5ebfa83427afc2d6b370eecc Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:05:49 +0000 Subject: [PATCH 15/33] Drop support for PHP 7.2 --- .github/workflows/tests.yml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1365facbd..18037949c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php: [7.2, 7.3, 7.4, 8.0] + php: [7.3, 7.4, 8.0] stability: [prefer-lowest, prefer-stable] name: PHP ${{ matrix.php }} - ${{ matrix.stability }} diff --git a/README.md b/README.md index c76cf45ef..6c886faaa 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ This library was created by Alex Bilbie. Find him on Twitter at [@alexbilbie](ht ## Requirements -The following versions of PHP are supported: +The latest version of this package supports the following versions of PHP: -* PHP 7.2 * PHP 7.3 * PHP 7.4 +* PHP 8.0 The `openssl` and `json` extensions are also required. From b6266f1e0576720d1e342fa2fa87037e8056df96 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:07:13 +0000 Subject: [PATCH 16/33] StyleCI fixes --- tests/AuthorizationValidators/BearerTokenValidatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/AuthorizationValidators/BearerTokenValidatorTest.php b/tests/AuthorizationValidators/BearerTokenValidatorTest.php index 0fafcbc5d..9cb8942e9 100644 --- a/tests/AuthorizationValidators/BearerTokenValidatorTest.php +++ b/tests/AuthorizationValidators/BearerTokenValidatorTest.php @@ -37,7 +37,7 @@ public function testBearerTokenValidatorAcceptsValidToken() ->expiresAt((new DateTimeImmutable())->add(new DateInterval('PT1H'))) ->relatedTo('user-id') ->withClaim('scopes', 'scope1 scope2 scope3 scope4') - ->getToken(new Sha256(), LocalFileReference::file( __DIR__ . '/../Stubs/private.key')); + ->getToken(new Sha256(), LocalFileReference::file(__DIR__ . '/../Stubs/private.key')); $request = (new ServerRequest())->withHeader('authorization', \sprintf('Bearer %s', $validJwt->toString())); @@ -65,7 +65,7 @@ public function testBearerTokenValidatorRejectsExpiredToken() ->expiresAt((new DateTimeImmutable())->sub(new DateInterval('PT1H'))) ->relatedTo('user-id') ->withClaim('scopes', 'scope1 scope2 scope3 scope4') - ->getToken(new Sha256(), LocalFileReference::file( __DIR__ . '/../Stubs/private.key')); + ->getToken(new Sha256(), LocalFileReference::file(__DIR__ . '/../Stubs/private.key')); $request = (new ServerRequest())->withHeader('authorization', \sprintf('Bearer %s', $expiredJwt->toString())); From 309cff6f2c01f57c3aca2bd9e66b2498cc088d89 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:09:22 +0000 Subject: [PATCH 17/33] StyleCI fixes --- tests/AuthorizationValidators/BearerTokenValidatorTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/AuthorizationValidators/BearerTokenValidatorTest.php b/tests/AuthorizationValidators/BearerTokenValidatorTest.php index 9cb8942e9..705368e4c 100644 --- a/tests/AuthorizationValidators/BearerTokenValidatorTest.php +++ b/tests/AuthorizationValidators/BearerTokenValidatorTest.php @@ -15,9 +15,6 @@ class BearerTokenValidatorTest extends TestCase { - - private $jwtConfiguration; - public function testBearerTokenValidatorAcceptsValidToken() { $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); From a29ccf7c03db22b22d787f0f42f68cd9d1227bd4 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:32:14 +0000 Subject: [PATCH 18/33] Set minimum stability to dev temporarily --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d2ee11fce..56d98e5da 100644 --- a/composer.json +++ b/composer.json @@ -68,5 +68,6 @@ "psr-4": { "LeagueTests\\": "tests/" } - } + }, + "minimum-stability": "dev" } From 89091b74185f5947e95ecd41412f60d98dfdabb0 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 17:39:29 +0000 Subject: [PATCH 19/33] remove minimum-stabiity --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 56d98e5da..d2ee11fce 100644 --- a/composer.json +++ b/composer.json @@ -68,6 +68,5 @@ "psr-4": { "LeagueTests\\": "tests/" } - }, - "minimum-stability": "dev" + } } From 4764e40611fe8355764f50b51cf669daea0282ea Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 20:48:00 +0000 Subject: [PATCH 20/33] Add BC check --- .github/workflows/backwards-compatibility.yml | 21 +++++++++++++++++++ composer.json | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/backwards-compatibility.yml diff --git a/.github/workflows/backwards-compatibility.yml b/.github/workflows/backwards-compatibility.yml new file mode 100644 index 000000000..e15e132b5 --- /dev/null +++ b/.github/workflows/backwards-compatibility.yml @@ -0,0 +1,21 @@ +name: "Backwards compatibility check" + +on: + pull_request: + +jobs: + bc-check: + name: "Backwards compatibility check" + + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 0 + + - name: "Backwards Compatibility Check" + uses: docker://nyholm/roave-bc-check-ga + with: + args: --from=${{ github.event.pull_request.base.sha }} \ No newline at end of file diff --git a/composer.json b/composer.json index d2ee11fce..a1074bff7 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "laminas/laminas-diactoros": "^2.3.0", "phpstan/phpstan": "^0.12.56", "phpstan/phpstan-phpunit": "^0.12.16", - "roave/security-advisories": "dev-master" + "roave/security-advisories": "dev-master", + "roave/backward-compatibility-check": "^5.0" }, "repositories": [ { From cb32154346206b637d82eccbe239667937c8950e Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 20:51:38 +0000 Subject: [PATCH 21/33] Update dependencies for BC check --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a1074bff7..b8c0f7304 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "phpstan/phpstan": "^0.12.56", "phpstan/phpstan-phpunit": "^0.12.16", "roave/security-advisories": "dev-master", - "roave/backward-compatibility-check": "^5.0" + "roave/backward-compatibility-check": "^4.4 || ^5.0" }, "repositories": [ { From d600718860ced495b34237cbfd8095722372d8ae Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 21:25:02 +0000 Subject: [PATCH 22/33] Make OAuthServerException constructor final --- src/AuthorizationValidators/BearerTokenValidator.php | 2 +- src/Entities/Traits/AccessTokenTrait.php | 2 -- src/Exception/OAuthServerException.php | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index a14cec494..2469a5cf7 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -124,7 +124,7 @@ public function validateAuthorization(ServerRequestInterface $request) /** * Convert single record arrays into strings to ensure backwards compatibility between v4 and v3.x of lcobucci/jwt * - * @param $aud + * @param mixed $aud * * @return array|string */ diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php index fbb84eec8..bf8069d21 100644 --- a/src/Entities/Traits/AccessTokenTrait.php +++ b/src/Entities/Traits/AccessTokenTrait.php @@ -55,8 +55,6 @@ public function initJwtConfiguration() /** * Generate a JWT from the access token * - * @param CryptKey $privateKey - * * @return Token */ private function convertToJWT() diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php index 31dcf2ea5..e55bf1548 100644 --- a/src/Exception/OAuthServerException.php +++ b/src/Exception/OAuthServerException.php @@ -57,7 +57,7 @@ class OAuthServerException extends Exception * @param null|string $redirectUri A HTTP URI to redirect the user back to * @param Throwable $previous Previous exception */ - public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null) + final public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->httpStatusCode = $httpStatusCode; From 9abc6b82be56195a49df339bda8e45ebb9d85539 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 21:27:52 +0000 Subject: [PATCH 23/33] Revert final for constructor --- src/Exception/OAuthServerException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php index e55bf1548..31dcf2ea5 100644 --- a/src/Exception/OAuthServerException.php +++ b/src/Exception/OAuthServerException.php @@ -57,7 +57,7 @@ class OAuthServerException extends Exception * @param null|string $redirectUri A HTTP URI to redirect the user back to * @param Throwable $previous Previous exception */ - final public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null) + public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->httpStatusCode = $httpStatusCode; From 89084a5abc12ab9864b1638f8201680911abeea0 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 21:30:04 +0000 Subject: [PATCH 24/33] Remove PHPStan --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 6c886faaa..0c8869c52 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server/code-structure) [![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server) [![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-server.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-server) -[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat-square)](https://github.com/phpstan/phpstan) `league/oauth2-server` is a standards compliant implementation of an [OAuth 2.0](https://tools.ietf.org/html/rfc6749) authorization server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them. @@ -52,11 +51,10 @@ You can contribute to the documentation in the [gh-pages branch](https://github. ## Testing -The library uses [PHPUnit](https://phpunit.de/) for unit tests and [PHPStan](https://github.com/phpstan/phpstan) for static analysis of the code. +The library uses [PHPUnit](https://phpunit.de/) for unit tests. ``` vendor/bin/phpunit -vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests ``` ## Continuous Integration From de7de426a5b70596735d4607504e31e20a4484e4 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 21:31:22 +0000 Subject: [PATCH 25/33] Remove commented phpstan from actions --- .github/workflows/tests.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 18037949c..14df99517 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,9 +32,6 @@ jobs: - name: Install dependencies run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress - #- name: Run PHPStan - # run: vendor/bin/phpstan analyse -l 7 -c phpstan.neon src tests - - name: Execute tests run: vendor/bin/phpunit --verbose --coverage-clover=coverage.clover From 85b8efb39d74ddb22e0f015e71c2e99fd954f549 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 24 Nov 2020 21:53:39 +0000 Subject: [PATCH 26/33] Remove backwards compatibility check --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b8c0f7304..d2ee11fce 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,7 @@ "laminas/laminas-diactoros": "^2.3.0", "phpstan/phpstan": "^0.12.56", "phpstan/phpstan-phpunit": "^0.12.16", - "roave/security-advisories": "dev-master", - "roave/backward-compatibility-check": "^4.4 || ^5.0" + "roave/security-advisories": "dev-master" }, "repositories": [ { From 3fcfe2c405c69ef376e3a63f0faf16b9f7f74b8d Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:05:29 +0000 Subject: [PATCH 27/33] Update dependencies --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d2ee11fce..cd06d578c 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": "^7.3 || ^8.0", "ext-openssl": "*", "league/event": "^2.2", - "lcobucci/jwt": "^3.4@dev || ^4.0@dev", + "lcobucci/jwt": "^3.4 || ^4.0", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.2.1", "ext-json": "*" From 51cf94e6b3fa3137ece90031f5cf7e1e7aba5bf2 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:07:23 +0000 Subject: [PATCH 28/33] Remove backwards compat test --- .github/workflows/backwards-compatibility.yml | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/workflows/backwards-compatibility.yml diff --git a/.github/workflows/backwards-compatibility.yml b/.github/workflows/backwards-compatibility.yml deleted file mode 100644 index e15e132b5..000000000 --- a/.github/workflows/backwards-compatibility.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: "Backwards compatibility check" - -on: - pull_request: - -jobs: - bc-check: - name: "Backwards compatibility check" - - runs-on: "ubuntu-latest" - - steps: - - name: "Checkout" - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - - name: "Backwards Compatibility Check" - uses: docker://nyholm/roave-bc-check-ga - with: - args: --from=${{ github.event.pull_request.base.sha }} \ No newline at end of file From c968b00bf1a0f67ec215d90cb5257be740ae8e4e Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:12:16 +0000 Subject: [PATCH 29/33] Reinstate BC checker --- .github/workflows/backwards-compatibility.yml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/backwards-compatibility.yml diff --git a/.github/workflows/backwards-compatibility.yml b/.github/workflows/backwards-compatibility.yml new file mode 100644 index 000000000..e15e132b5 --- /dev/null +++ b/.github/workflows/backwards-compatibility.yml @@ -0,0 +1,21 @@ +name: "Backwards compatibility check" + +on: + pull_request: + +jobs: + bc-check: + name: "Backwards compatibility check" + + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 0 + + - name: "Backwards Compatibility Check" + uses: docker://nyholm/roave-bc-check-ga + with: + args: --from=${{ github.event.pull_request.base.sha }} \ No newline at end of file From d50709c4234b43793b5bf5214ed835c821c48131 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:17:23 +0000 Subject: [PATCH 30/33] Update change log for version 8.2.0 --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbd2cbb69..f49eba4b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [8.2.0] - released 2020-11-25 ### Added - Add a `getRedirectUri` function to the `OAuthServerException` class (PR #1123) +- Support for PHP 8.0 (PR #1146) + +### Removed +- Removed support for PHP 7.2 (PR #1146) ### Fixed - Fix typo in parameter hint. `code_challenged` changed to `code_challenge`. Thrown by Auth Code Grant when the code challenge does not match the regex. (PR #1130) @@ -505,7 +511,8 @@ Version 5 is a complete code rewrite. - First major release -[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/8.1.1...HEAD +[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/8.2.0...HEAD +[8.2.0]: https://github.com/thephpleague/oauth2-server/compare/8.1.1...8.2.0 [8.1.1]: https://github.com/thephpleague/oauth2-server/compare/8.1.0...8.1.1 [8.1.0]: https://github.com/thephpleague/oauth2-server/compare/8.0.0...8.1.0 [8.0.0]: https://github.com/thephpleague/oauth2-server/compare/7.4.0...8.0.0 From 0419bf4a9cf584a3550077a840f608be3bc130be Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:23:14 +0000 Subject: [PATCH 31/33] Update dependencies --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index cd06d578c..e0617eb66 100644 --- a/composer.json +++ b/composer.json @@ -13,9 +13,9 @@ "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^8.5.4 || ^9.1.3", - "laminas/laminas-diactoros": "^2.3.0", - "phpstan/phpstan": "^0.12.56", + "phpunit/phpunit": "^9.4.3", + "laminas/laminas-diactoros": "^2.5.0", + "phpstan/phpstan": "^0.12.57", "phpstan/phpstan-phpunit": "^0.12.16", "roave/security-advisories": "dev-master" }, From 682dc07e6b4fbf43c8efe9cae2fb07a1b7340336 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 11:29:29 +0000 Subject: [PATCH 32/33] Update examples dependencies --- examples/composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/composer.json b/examples/composer.json index de2bd7162..d265472e6 100644 --- a/examples/composer.json +++ b/examples/composer.json @@ -1,13 +1,13 @@ { "require": { - "slim/slim": "^3.0.0" + "slim/slim": "^3.12.3" }, "require-dev": { "league/event": "^2.2", - "lcobucci/jwt": "^3.4@dev || ^4.0@beta", - "psr/http-message": "^1.0", - "defuse/php-encryption": "^2.2", - "laminas/laminas-diactoros": "^2.1.2" + "lcobucci/jwt": "^3.4 || ^4.0", + "psr/http-message": "^1.0.1", + "defuse/php-encryption": "^2.2.1", + "laminas/laminas-diactoros": "^2.5.0" }, "autoload": { "psr-4": { From 8e89f55945a31acb385a3ac8cb9e3c0bcd9e8c82 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 25 Nov 2020 23:23:25 +0000 Subject: [PATCH 33/33] Add docblocks for functions --- examples/composer.lock | 30 +++++++++---------- .../BearerTokenValidator.php | 3 ++ src/Entities/Traits/AccessTokenTrait.php | 3 ++ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/examples/composer.lock b/examples/composer.lock index d732e6f0b..f7affe0e9 100644 --- a/examples/composer.lock +++ b/examples/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": "afc9a862edd0bfe93a224a28b1abf75d", + "content-hash": "1f38bc4bb33ddc5527b3097d1118b227", "packages": [ { "name": "nikic/fast-route", @@ -54,24 +54,24 @@ }, { "name": "pimple/pimple", - "version": "v3.3.0", + "version": "v3.3.1", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", - "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930" + "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/e55d12f9d6a0e7f9c85992b73df1267f46279930", - "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/21e45061c3429b1e06233475cc0e1f6fc774d5b0", + "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0", "shasum": "" }, "require": { - "php": "^7.2.5", + "php": ">=7.2.5", "psr/container": "^1.0" }, "require-dev": { - "symfony/phpunit-bridge": "^3.4|^4.4|^5.0" + "symfony/phpunit-bridge": "^5.0" }, "type": "library", "extra": { @@ -100,7 +100,7 @@ "container", "dependency injection" ], - "time": "2020-03-03T09:12:48+00:00" + "time": "2020-11-24T20:35:42+00:00" }, { "name": "psr/container", @@ -522,16 +522,16 @@ }, { "name": "lcobucci/jwt", - "version": "dev-master", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "144de5ad99590cac0139a688c26bbf42539aeed9" + "reference": "6d8665ccd924dc076a9b65d1ea8abe21d68f6958" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/144de5ad99590cac0139a688c26bbf42539aeed9", - "reference": "144de5ad99590cac0139a688c26bbf42539aeed9", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/6d8665ccd924dc076a9b65d1ea8abe21d68f6958", + "reference": "6d8665ccd924dc076a9b65d1ea8abe21d68f6958", "shasum": "" }, "require": { @@ -580,7 +580,7 @@ "JWS", "jwt" ], - "time": "2020-11-23T04:40:16+00:00" + "time": "2020-11-25T02:06:12+00:00" }, { "name": "league/event", @@ -732,9 +732,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "lcobucci/jwt": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": [], diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php index 2469a5cf7..9a279de4f 100644 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ b/src/AuthorizationValidators/BearerTokenValidator.php @@ -66,6 +66,9 @@ public function setPublicKey(CryptKey $key) $this->initJwtConfiguration(); } + /** + * Initialise the JWT configuration. + */ private function initJwtConfiguration() { $this->jwtConfiguration = Configuration::forSymmetricSigner( diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php index bf8069d21..26007188f 100644 --- a/src/Entities/Traits/AccessTokenTrait.php +++ b/src/Entities/Traits/AccessTokenTrait.php @@ -39,6 +39,9 @@ public function setPrivateKey(CryptKey $privateKey) $this->privateKey = $privateKey; } + /** + * Initialise the JWT Configuration. + */ public function initJwtConfiguration() { $privateKeyPassPhrase = $this->privateKey->getPassPhrase();