From 032e2e4a7b5ed906106e9d23099c054f442a45c9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 26 Nov 2020 08:53:02 +0100 Subject: [PATCH] [8.x] PHP 8 Support (#1373) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * PHP 8 Support * Update JWT usage * Try out dev versions of jwt * Use vcs * Try composer token * Update phpunit xml * Fix test for JWT 3.4 * Try git url * Bind JWT Parser to container for 4.x * Add deprecation notice * Use configuration object * Use new token interface * Update composer.json * Update workflow Co-authored-by: Luís Cobucci --- .github/workflows/tests.yml | 2 +- composer.json | 5 +++-- phpunit.xml.dist | 5 ----- src/Http/Controllers/AccessTokenController.php | 2 ++ src/PassportServiceProvider.php | 15 +++++++++++++++ src/PersonalAccessTokenFactory.php | 4 +++- tests/Feature/AccessTokenControllerTest.php | 16 ++++++++-------- tests/Unit/PersonalAccessTokenFactoryTest.php | 13 +++++++++++-- 8 files changed, 43 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7acc16c95..ad2acaee8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: true matrix: - php: [7.3, 7.4] + php: [7.3, 7.4, 8.0] laravel: [^8.0] name: P${{ matrix.php }} - L${{ matrix.laravel }} diff --git a/composer.json b/composer.json index e04b5259c..319a8c4b8 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": "^7.3", + "php": "^7.3|^8.0", "ext-json": "*", "firebase/php-jwt": "^5.0", "illuminate/auth": "^8.2", @@ -26,7 +26,8 @@ "illuminate/encryption": "^8.2", "illuminate/http": "^8.2", "illuminate/support": "^8.2", - "league/oauth2-server": "^8.1", + "league/oauth2-server": "^8.2", + "lcobucci/jwt": "^3.4|^4.0", "nyholm/psr7": "^1.3", "phpseclib/phpseclib": "^2.0", "symfony/psr-http-message-bridge": "^2.0" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f22833f60..0ec92aebd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -18,11 +18,6 @@ ./tests/Feature - - - ./src/ - - diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index 03af02fd8..3667c2d92 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -30,6 +30,8 @@ class AccessTokenController * The JWT parser instance. * * @var \Lcobucci\JWT\Parser + * + * @deprecated This property will be removed in a future Passport version. */ protected $jwt; diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 3f4271285..a8a0b78ff 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -14,6 +14,8 @@ use Laravel\Passport\Bridge\PersonalAccessGrant; use Laravel\Passport\Bridge\RefreshTokenRepository; use Laravel\Passport\Guards\TokenGuard; +use Lcobucci\JWT\Configuration; +use Lcobucci\JWT\Parser; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Grant\AuthCodeGrant; @@ -86,6 +88,7 @@ public function register() $this->registerAuthorizationServer(); $this->registerClientRepository(); + $this->registerJWTParser(); $this->registerResourceServer(); $this->registerGuard(); } @@ -227,6 +230,18 @@ protected function registerClientRepository() }); } + /** + * Register the JWT Parser. + * + * @return void + */ + protected function registerJWTParser() + { + $this->app->singleton(Parser::class, function () { + return Configuration::forUnsecuredSigner()->parser(); + }); + } + /** * Register the resource server. * diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index ca157f7bc..b849d069f 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -35,6 +35,8 @@ class PersonalAccessTokenFactory * The JWT token parser instance. * * @var \Lcobucci\JWT\Parser + * + * @deprecated This property will be removed in a future Passport version. */ protected $jwt; @@ -127,7 +129,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ protected function findAccessToken(array $response) { return $this->tokens->find( - $this->jwt->parse($response['access_token'])->getClaim('jti') + $this->jwt->parse($response['access_token'])->claims()->get('jti') ); } } diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 2bca3459c..e5f4af83b 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -12,7 +12,7 @@ use Laravel\Passport\HasApiTokens; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; -use Lcobucci\JWT\Parser; +use Lcobucci\JWT\Configuration; class AccessTokenControllerTest extends PassportTestCase { @@ -77,10 +77,10 @@ public function testGettingAccessTokenWithClientCredentialsGrant() $expiresInSeconds = 31536000; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $jwtAccessToken = (new Parser())->parse($decodedResponse['access_token']); - $this->assertTrue($this->app->make(ClientRepository::class)->findActive($jwtAccessToken->getClaim('aud'))->is($client)); + $jwtAccessToken = Configuration::forUnsecuredSigner()->parser()->parse($decodedResponse['access_token']); + $this->assertTrue($this->app->make(ClientRepository::class)->findActive($jwtAccessToken->claims()->get('aud'))->is($client)); - $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->getClaim('jti')); + $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->claims()->get('jti')); $this->assertInstanceOf(Token::class, $token); $this->assertTrue($token->client->is($client)); $this->assertFalse($token->revoked); @@ -170,11 +170,11 @@ public function testGettingAccessTokenWithPasswordGrant() $expiresInSeconds = 31536000; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $jwtAccessToken = (new Parser())->parse($decodedResponse['access_token']); - $this->assertTrue($this->app->make(ClientRepository::class)->findActive($jwtAccessToken->getClaim('aud'))->is($client)); - $this->assertTrue($this->app->make('auth')->createUserProvider()->retrieveById($jwtAccessToken->getClaim('sub'))->is($user)); + $jwtAccessToken = Configuration::forUnsecuredSigner()->parser()->parse($decodedResponse['access_token']); + $this->assertTrue($this->app->make(ClientRepository::class)->findActive($jwtAccessToken->claims()->get('aud'))->is($client)); + $this->assertTrue($this->app->make('auth')->createUserProvider()->retrieveById($jwtAccessToken->claims()->get('sub'))->is($user)); - $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->getClaim('jti')); + $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->claims()->get('jti')); $this->assertInstanceOf(Token::class, $token); $this->assertFalse($token->revoked); $this->assertTrue($token->user->is($user)); diff --git a/tests/Unit/PersonalAccessTokenFactoryTest.php b/tests/Unit/PersonalAccessTokenFactoryTest.php index 18aaf9f93..f4731bd6b 100644 --- a/tests/Unit/PersonalAccessTokenFactoryTest.php +++ b/tests/Unit/PersonalAccessTokenFactoryTest.php @@ -8,6 +8,10 @@ use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Parser; +use Lcobucci\JWT\Token\DataSet; +use Lcobucci\JWT\Token\Plain as PlainToken; +use Lcobucci\JWT\Token\RegisteredClaims; +use Lcobucci\JWT\Token\Signature; use League\OAuth2\Server\AuthorizationServer; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -34,8 +38,13 @@ public function test_access_token_can_be_created() 'access_token' => 'foo', ])); - $jwt->shouldReceive('parse')->with('foo')->andReturn($parsedToken = m::mock()); - $parsedToken->shouldReceive('getClaim')->with('jti')->andReturn('token'); + $parsedToken = new PlainToken( + new DataSet([], ''), + new DataSet([RegisteredClaims::ID => 'token'], ''), + Signature::fromEmptyData() + ); + + $jwt->shouldReceive('parse')->with('foo')->andReturn($parsedToken); $tokens->shouldReceive('find') ->with('token') ->andReturn($foundToken = new PersonalAccessTokenFactoryTestModelStub);