From 821c1b1e098ffc0d8c5ac3f435067ea3adcc4da7 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 29 Oct 2019 16:13:03 +0100 Subject: [PATCH 001/353] Update branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c5fc88c63..09913471b 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "9.x-dev" }, "laravel": { "providers": [ From bad28d2f01eb43f842e3cfeafbe412258c42f4d2 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 29 Oct 2019 16:13:43 +0100 Subject: [PATCH 002/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 395d59113..c00076fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.0.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.0.0...master) ## [v8.0.0 (2019-10-29)](https://github.com/laravel/passport/compare/v7.5.1...v8.0.0) From 1d90eca73917aa5d8ad5f3109813cec327d8104c Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Thu, 7 Nov 2019 18:25:29 +0100 Subject: [PATCH 003/353] Update 'check client credentials (for any scopes)' middlewares Use 'oauth_scopes' and 'oauth_client_id' attributes in psr request --- src/Http/Middleware/CheckClientCredentials.php | 18 +++++++++--------- .../CheckClientCredentialsForAnyScope.php | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index 6cf006dda..bc4ca722c 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -5,7 +5,7 @@ use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; -use Laravel\Passport\TokenRepository; +use Laravel\Passport\ClientRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; @@ -24,9 +24,9 @@ class CheckClientCredentials protected $server; /** - * Token Repository. + * Client Repository. * - * @var \Laravel\Passport\TokenRepository + * @var \Laravel\Passport\ClientRepository */ protected $repository; @@ -34,10 +34,10 @@ class CheckClientCredentials * Create a new middleware instance. * * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\TokenRepository $repository + * @param \Laravel\Passport\ClientRepository $repository * @return void */ - public function __construct(ResourceServer $server, TokenRepository $repository) + public function __construct(ResourceServer $server, ClientRepository $repository) { $this->server = $server; $this->repository = $repository; @@ -82,18 +82,18 @@ public function handle($request, Closure $next, ...$scopes) */ protected function validate($psr, $scopes) { - $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); + $client = $this->repository->find($psr->getAttribute('oauth_client_id')); - if (! $token || $token->client->firstParty()) { + if (! $client || $client->firstParty()) { throw new AuthenticationException; } - if (in_array('*', $token->scopes)) { + if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) { return; } foreach ($scopes as $scope) { - if ($token->cant($scope)) { + if (! in_array($scope, $tokenScopes)) { throw new MissingScopeException($scope); } } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index 6c1337ce9..a8a7e50fc 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -5,7 +5,7 @@ use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; -use Laravel\Passport\TokenRepository; +use Laravel\Passport\ClientRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; @@ -24,9 +24,9 @@ class CheckClientCredentialsForAnyScope protected $server; /** - * Token Repository. + * Client Repository. * - * @var \Laravel\Passport\TokenRepository + * @var \Laravel\Passport\ClientRepository */ protected $repository; @@ -34,10 +34,10 @@ class CheckClientCredentialsForAnyScope * Create a new middleware instance. * * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\TokenRepository $repository + * @param \Laravel\Passport\ClientRepository $repository * @return void */ - public function __construct(ResourceServer $server, TokenRepository $repository) + public function __construct(ResourceServer $server, ClientRepository $repository) { $this->server = $server; $this->repository = $repository; @@ -84,18 +84,18 @@ public function handle($request, Closure $next, ...$scopes) */ protected function validate($psr, $scopes) { - $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); + $client = $this->repository->find($psr->getAttribute('oauth_client_id')); - if (! $token || $token->client->firstParty()) { + if (! $client || $client->firstParty()) { throw new AuthenticationException; } - if (in_array('*', $token->scopes)) { + if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) { return true; } foreach ($scopes as $scope) { - if ($token->can($scope)) { + if (in_array($scope, $tokenScopes)) { return true; } } From 88a349a535b70a4135349967bde8c5567c78404b Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Thu, 7 Nov 2019 18:25:55 +0100 Subject: [PATCH 004/353] Update tests of 'check client credentials (of any scope)' middlewares --- .../CheckClientCredentialsForAnyScopeTest.php | 58 ++++++------------- tests/CheckClientCredentialsTest.php | 55 ++++++------------ 2 files changed, 38 insertions(+), 75 deletions(-) diff --git a/tests/CheckClientCredentialsForAnyScopeTest.php b/tests/CheckClientCredentialsForAnyScopeTest.php index 96d9d646e..45bb7a4d6 100644 --- a/tests/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/CheckClientCredentialsForAnyScopeTest.php @@ -5,8 +5,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; -use Laravel\Passport\Token; -use Laravel\Passport\TokenRepository; +use Laravel\Passport\ClientRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; @@ -24,21 +23,17 @@ public function test_request_is_passed_along_if_token_is_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['*']); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -55,23 +50,17 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar', 'baz']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar', 'baz']); - $token->shouldReceive('can')->with('notfoo')->andReturnFalse(); - $token->shouldReceive('can')->with('bar')->andReturnTrue(); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -88,13 +77,13 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() */ public function test_exception_is_thrown_when_oauth_throws_exception() { - $tokenRepository = m::mock(TokenRepository::class); + $clientRepository = m::mock(ClientRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -112,23 +101,17 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar']); - $token->shouldReceive('can')->with('baz')->andReturnFalse(); - $token->shouldReceive('can')->with('notbar')->andReturnFalse(); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -146,20 +129,17 @@ public function test_exception_is_thrown_if_token_belongs_to_first_party_client( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnTrue(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); diff --git a/tests/CheckClientCredentialsTest.php b/tests/CheckClientCredentialsTest.php index 435ae9f7a..5ac89bac9 100644 --- a/tests/CheckClientCredentialsTest.php +++ b/tests/CheckClientCredentialsTest.php @@ -7,6 +7,7 @@ use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; +use Laravel\Passport\ClientRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; @@ -24,21 +25,17 @@ public function test_request_is_passed_along_if_token_is_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['*']); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentials($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -55,22 +52,17 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['see-profile']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['see-profile']); - $token->shouldReceive('cant')->with('see-profile')->andReturnFalse(); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentials($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -87,13 +79,13 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() */ public function test_exception_is_thrown_when_oauth_throws_exception() { - $tokenRepository = m::mock(TokenRepository::class); + $clientRepository = m::mock(ClientRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentials($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -111,23 +103,17 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scopes( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'notbar']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'notbar']); - $token->shouldReceive('cant')->with('foo')->andReturnFalse(); - $token->shouldReceive('cant')->with('bar')->andReturnTrue(); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentials($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -145,20 +131,17 @@ public function test_exception_is_thrown_if_token_belongs_to_first_party_client( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnTrue(); - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('find')->with(2)->andReturn($client); - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); + $middleware = new CheckClientCredentials($resourceServer, $clientRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); From c829d03c7fb240e966e66d63d2b1fae0db45d31f Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Fri, 8 Nov 2019 17:59:15 +0100 Subject: [PATCH 005/353] Fix StyleCI issues --- src/Http/Middleware/CheckClientCredentials.php | 2 +- src/Http/Middleware/CheckClientCredentialsForAnyScope.php | 2 +- tests/CheckClientCredentialsForAnyScopeTest.php | 2 +- tests/CheckClientCredentialsTest.php | 4 +--- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index bc4ca722c..1f667aa2e 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -4,8 +4,8 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laravel\Passport\Exceptions\MissingScopeException; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Exceptions\MissingScopeException; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index a8a7e50fc..43e888426 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -4,8 +4,8 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laravel\Passport\Exceptions\MissingScopeException; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Exceptions\MissingScopeException; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; diff --git a/tests/CheckClientCredentialsForAnyScopeTest.php b/tests/CheckClientCredentialsForAnyScopeTest.php index 45bb7a4d6..d14ccc4b7 100644 --- a/tests/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/CheckClientCredentialsForAnyScopeTest.php @@ -4,8 +4,8 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; diff --git a/tests/CheckClientCredentialsTest.php b/tests/CheckClientCredentialsTest.php index 5ac89bac9..08edd8e4f 100644 --- a/tests/CheckClientCredentialsTest.php +++ b/tests/CheckClientCredentialsTest.php @@ -4,10 +4,8 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\Http\Middleware\CheckClientCredentials; -use Laravel\Passport\Token; -use Laravel\Passport\TokenRepository; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Http\Middleware\CheckClientCredentials; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; From cc176a3d4cadc924469ab90a1e9cdf373cc2bb27 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 12 Nov 2019 08:59:01 -0600 Subject: [PATCH 006/353] Revert "[9.x] Use psr request attributes in 'check client credentials' middleware" --- .../Middleware/CheckClientCredentials.php | 18 +++--- .../CheckClientCredentialsForAnyScope.php | 18 +++--- .../CheckClientCredentialsForAnyScopeTest.php | 58 +++++++++++++------ tests/CheckClientCredentialsTest.php | 57 ++++++++++++------ 4 files changed, 95 insertions(+), 56 deletions(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index 1f667aa2e..6cf006dda 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -4,8 +4,8 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laravel\Passport\ClientRepository; use Laravel\Passport\Exceptions\MissingScopeException; +use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; @@ -24,9 +24,9 @@ class CheckClientCredentials protected $server; /** - * Client Repository. + * Token Repository. * - * @var \Laravel\Passport\ClientRepository + * @var \Laravel\Passport\TokenRepository */ protected $repository; @@ -34,10 +34,10 @@ class CheckClientCredentials * Create a new middleware instance. * * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\ClientRepository $repository + * @param \Laravel\Passport\TokenRepository $repository * @return void */ - public function __construct(ResourceServer $server, ClientRepository $repository) + public function __construct(ResourceServer $server, TokenRepository $repository) { $this->server = $server; $this->repository = $repository; @@ -82,18 +82,18 @@ public function handle($request, Closure $next, ...$scopes) */ protected function validate($psr, $scopes) { - $client = $this->repository->find($psr->getAttribute('oauth_client_id')); + $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); - if (! $client || $client->firstParty()) { + if (! $token || $token->client->firstParty()) { throw new AuthenticationException; } - if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) { + if (in_array('*', $token->scopes)) { return; } foreach ($scopes as $scope) { - if (! in_array($scope, $tokenScopes)) { + if ($token->cant($scope)) { throw new MissingScopeException($scope); } } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index 43e888426..6c1337ce9 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -4,8 +4,8 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laravel\Passport\ClientRepository; use Laravel\Passport\Exceptions\MissingScopeException; +use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; @@ -24,9 +24,9 @@ class CheckClientCredentialsForAnyScope protected $server; /** - * Client Repository. + * Token Repository. * - * @var \Laravel\Passport\ClientRepository + * @var \Laravel\Passport\TokenRepository */ protected $repository; @@ -34,10 +34,10 @@ class CheckClientCredentialsForAnyScope * Create a new middleware instance. * * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\ClientRepository $repository + * @param \Laravel\Passport\TokenRepository $repository * @return void */ - public function __construct(ResourceServer $server, ClientRepository $repository) + public function __construct(ResourceServer $server, TokenRepository $repository) { $this->server = $server; $this->repository = $repository; @@ -84,18 +84,18 @@ public function handle($request, Closure $next, ...$scopes) */ protected function validate($psr, $scopes) { - $client = $this->repository->find($psr->getAttribute('oauth_client_id')); + $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); - if (! $client || $client->firstParty()) { + if (! $token || $token->client->firstParty()) { throw new AuthenticationException; } - if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) { + if (in_array('*', $token->scopes)) { return true; } foreach ($scopes as $scope) { - if (in_array($scope, $tokenScopes)) { + if ($token->can($scope)) { return true; } } diff --git a/tests/CheckClientCredentialsForAnyScopeTest.php b/tests/CheckClientCredentialsForAnyScopeTest.php index d14ccc4b7..96d9d646e 100644 --- a/tests/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/CheckClientCredentialsForAnyScopeTest.php @@ -4,8 +4,9 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\ClientRepository; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; +use Laravel\Passport\Token; +use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; @@ -23,17 +24,21 @@ public function test_request_is_passed_along_if_token_is_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['*']); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -50,17 +55,23 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar', 'baz']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar', 'baz']); + $token->shouldReceive('can')->with('notfoo')->andReturnFalse(); + $token->shouldReceive('can')->with('bar')->andReturnTrue(); + + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -77,13 +88,13 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() */ public function test_exception_is_thrown_when_oauth_throws_exception() { - $clientRepository = m::mock(ClientRepository::class); + $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -101,17 +112,23 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar']); + $token->shouldReceive('can')->with('baz')->andReturnFalse(); + $token->shouldReceive('can')->with('notbar')->andReturnFalse(); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -129,17 +146,20 @@ public function test_exception_is_thrown_if_token_belongs_to_first_party_client( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnTrue(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $clientRepository); + $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); diff --git a/tests/CheckClientCredentialsTest.php b/tests/CheckClientCredentialsTest.php index 08edd8e4f..435ae9f7a 100644 --- a/tests/CheckClientCredentialsTest.php +++ b/tests/CheckClientCredentialsTest.php @@ -4,8 +4,9 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\ClientRepository; use Laravel\Passport\Http\Middleware\CheckClientCredentials; +use Laravel\Passport\Token; +use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Mockery as m; @@ -23,17 +24,21 @@ public function test_request_is_passed_along_if_token_is_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['*']); - $middleware = new CheckClientCredentials($resourceServer, $clientRepository); + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + + $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -50,17 +55,22 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['see-profile']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['see-profile']); + $token->shouldReceive('cant')->with('see-profile')->andReturnFalse(); + + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - $middleware = new CheckClientCredentials($resourceServer, $clientRepository); + $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -77,13 +87,13 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() */ public function test_exception_is_thrown_when_oauth_throws_exception() { - $clientRepository = m::mock(ClientRepository::class); + $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $middleware = new CheckClientCredentials($resourceServer, $clientRepository); + $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -101,17 +111,23 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scopes( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'notbar']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnFalse(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'notbar']); + $token->shouldReceive('cant')->with('foo')->andReturnFalse(); + $token->shouldReceive('cant')->with('bar')->andReturnTrue(); - $middleware = new CheckClientCredentials($resourceServer, $clientRepository); + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); + + $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); @@ -129,17 +145,20 @@ public function test_exception_is_thrown_if_token_belongs_to_first_party_client( $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(2); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); $client = m::mock(Client::class); $client->shouldReceive('firstParty')->andReturnTrue(); - $clientRepository = m::mock(ClientRepository::class); - $clientRepository->shouldReceive('find')->with(2)->andReturn($client); + $token = m::mock(Token::class); + $token->shouldReceive('getAttribute')->with('client')->andReturn($client); + + $tokenRepository = m::mock(TokenRepository::class); + $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - $middleware = new CheckClientCredentials($resourceServer, $clientRepository); + $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); From ae7989259bdfdfdbe896773815bd479e56049ac7 Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Sat, 16 Nov 2019 11:57:47 +0100 Subject: [PATCH 007/353] Mock 'TokenRepository' property in 'actingAsClient' testing method --- src/Passport.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index 2104eca28..a68546951 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -422,17 +422,25 @@ public static function actingAs($user, $scopes = [], $guard = 'api') */ public static function actingAsClient($client, $scopes = []) { - $mock = Mockery::mock(ResourceServer::class); + $token = app(self::tokenModel()); + $token->client = $client; + $token->scopes = $scopes; + $mock = Mockery::mock(ResourceServer::class); $mock->shouldReceive('validateAuthenticatedRequest') - ->andReturnUsing(function ($request) use ($client, $scopes) { - return $request - ->withAttribute('oauth_client_id', $client->id) - ->withAttribute('oauth_scopes', $scopes); + ->andReturnUsing(function ($request) use ($token) { + return $request->withAttribute('oauth_client_id', $token->client->id) + ->withAttribute('oauth_access_token_id', $token->id) + ->withAttribute('oauth_scopes', $token->scopes); }); app()->instance(ResourceServer::class, $mock); + $mock = Mockery::mock(TokenRepository::class); + $mock->shouldReceive('find')->andReturn($token); + + app()->instance(TokenRepository::class, $mock); + return $client; } From 8a6a45a901f6948cf5f0874b301230fb8bc27b32 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 19 Nov 2019 17:36:40 +0100 Subject: [PATCH 008/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 395d59113..56f1e4b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.0.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.0.1...8.x) + + +## [v8.0.1 (2019-11-19)](https://github.com/laravel/passport/compare/v8.0.0...v8.0.1) + +### Fixed +- Fix `actingAsClient` testing method ([#1119](https://github.com/laravel/passport/pull/1119)) ## [v8.0.0 (2019-10-29)](https://github.com/laravel/passport/compare/v7.5.1...v8.0.0) From 30ee4d23424e2d0844dd6b7163f7c3abeb3c3d3e Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Fri, 22 Nov 2019 18:17:21 +0100 Subject: [PATCH 009/353] Update 'upgrade' guide to remove mention of included upgrade migration --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index c4d7abd08..7df72a606 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -12,7 +12,7 @@ The minimum Laravel version is now v6.0 and the minimum PHP version is now 7.2. PR: https://github.com/laravel/passport/pull/1065 -Passport now supports public clients and PCKE. To leverage this feature, you should update the the `secret` column of the `oauth_clients` table to be `nullable`. If you use Passport migrations this will be done automatically for you upon the next migration. Otherwise, you'll need to create the following migration and migrate manually: +Passport now supports public clients and PCKE. To leverage this feature, you should update the the `secret` column of the `oauth_clients` table to be `nullable`: Schema::table('oauth_clients', function (Blueprint $table) { $table->string('secret', 100)->nullable()->change(); From 5ddd626d3a5eb22fef8562fa2b91c3d298ee4d6c Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Sun, 24 Nov 2019 15:06:37 +0800 Subject: [PATCH 010/353] [8.x] Add abstract CheckCredentials middleware and allows to create custom implementation of middleware if needed. Signed-off-by: Mior Muhammad Zaki --- .../Middleware/CheckClientCredentials.php | 76 ++---------- .../CheckClientCredentialsForAnyScope.php | 87 +++----------- src/Http/Middleware/CheckCredentials.php | 109 ++++++++++++++++++ 3 files changed, 133 insertions(+), 139 deletions(-) create mode 100644 src/Http/Middleware/CheckCredentials.php diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index 6cf006dda..d2567f525 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -2,92 +2,36 @@ namespace Laravel\Passport\Http\Middleware; -use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; -use Laravel\Passport\TokenRepository; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\ResourceServer; -use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -use Zend\Diactoros\ResponseFactory; -use Zend\Diactoros\ServerRequestFactory; -use Zend\Diactoros\StreamFactory; -use Zend\Diactoros\UploadedFileFactory; -class CheckClientCredentials +class CheckClientCredentials extends CheckCredentials { /** - * The Resource Server instance. + * Validate token credentials. * - * @var \League\OAuth2\Server\ResourceServer - */ - protected $server; - - /** - * Token Repository. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $repository; - - /** - * Create a new middleware instance. - * - * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\TokenRepository $repository + * @param \Laravel\Passport\Token $token * @return void - */ - public function __construct(ResourceServer $server, TokenRepository $repository) - { - $this->server = $server; - $this->repository = $repository; - } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param mixed ...$scopes - * @return mixed * @throws \Illuminate\Auth\AuthenticationException */ - public function handle($request, Closure $next, ...$scopes) + protected function validateCredentials($token) { - $psr = (new PsrHttpFactory( - new ServerRequestFactory, - new StreamFactory, - new UploadedFileFactory, - new ResponseFactory - ))->createRequest($request); - - try { - $psr = $this->server->validateAuthenticatedRequest($psr); - } catch (OAuthServerException $e) { + if (! $token || $token->client->firstParty()) { throw new AuthenticationException; } - - $this->validate($psr, $scopes); - - return $next($request); } + /** - * Validate the scopes and token on the incoming request. + * Validate token credentials. * - * @param \Psr\Http\Message\ServerRequestInterface $psr + * @param \Laravel\Passport\Token $token * @param array $scopes * @return void - * @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException + * @throws \Laravel\Passport\Exceptions\MissingScopeException */ - protected function validate($psr, $scopes) + protected function validateScopes($token, $scopes) { - $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); - - if (! $token || $token->client->firstParty()) { - throw new AuthenticationException; - } - if (in_array('*', $token->scopes)) { return; } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index 6c1337ce9..c047774f2 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -2,104 +2,45 @@ namespace Laravel\Passport\Http\Middleware; -use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; -use Laravel\Passport\TokenRepository; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\ResourceServer; -use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -use Zend\Diactoros\ResponseFactory; -use Zend\Diactoros\ServerRequestFactory; -use Zend\Diactoros\StreamFactory; -use Zend\Diactoros\UploadedFileFactory; -class CheckClientCredentialsForAnyScope +class CheckClientCredentialsForAnyScope extends CheckCredentials { /** - * The Resource Server instance. + * Validate token credentials. * - * @var \League\OAuth2\Server\ResourceServer - */ - protected $server; - - /** - * Token Repository. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $repository; - - /** - * Create a new middleware instance. - * - * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\TokenRepository $repository + * @param \Laravel\Passport\Token $token * @return void + * @throws \Illuminate\Auth\AuthenticationException */ - public function __construct(ResourceServer $server, TokenRepository $repository) - { - $this->server = $server; - $this->repository = $repository; - } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param mixed ...$scopes - * @return mixed - * @throws \Illuminate\Auth\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException - */ - public function handle($request, Closure $next, ...$scopes) + protected function validateCredentials($token) { - $psr = (new PsrHttpFactory( - new ServerRequestFactory, - new StreamFactory, - new UploadedFileFactory, - new ResponseFactory - ))->createRequest($request); - - try { - $psr = $this->server->validateAuthenticatedRequest($psr); - } catch (OAuthServerException $e) { + if (! $token || $token->client->firstParty()) { throw new AuthenticationException; } - - if ($this->validate($psr, $scopes)) { - return $next($request); - } - - throw new MissingScopeException($scopes); } /** - * Validate the scopes and token on the incoming request. + * Validate token credentials. * - * @param \Psr\Http\Message\ServerRequestInterface $psr + * @param \Laravel\Passport\Token $token * @param array $scopes - * @return bool - * @throws \Illuminate\Auth\AuthenticationException + * @return void + * @throws \Laravel\Passport\Exceptions\MissingScopeException */ - protected function validate($psr, $scopes) + protected function validateScopes($token, $scopes) { - $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); - - if (! $token || $token->client->firstParty()) { - throw new AuthenticationException; - } - if (in_array('*', $token->scopes)) { - return true; + return; } foreach ($scopes as $scope) { if ($token->can($scope)) { - return true; + return; } } - return false; + throw new MissingScopeException($scopes); } } diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php new file mode 100644 index 000000000..6c28b6563 --- /dev/null +++ b/src/Http/Middleware/CheckCredentials.php @@ -0,0 +1,109 @@ +server = $server; + $this->repository = $repository; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param mixed ...$scopes + * @return mixed + * @throws \Illuminate\Auth\AuthenticationException + */ + public function handle($request, Closure $next, ...$scopes) + { + $psr = (new PsrHttpFactory( + new ServerRequestFactory, + new StreamFactory, + new UploadedFileFactory, + new ResponseFactory + ))->createRequest($request); + + try { + $psr = $this->server->validateAuthenticatedRequest($psr); + } catch (OAuthServerException $e) { + throw new AuthenticationException; + } + + $this->validate($psr, $scopes); + + return $next($request); + } + + /** + * Validate the scopes and token on the incoming request. + * + * @param \Psr\Http\Message\ServerRequestInterface $psr + * @param array $scopes + * @return void + * @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException + */ + protected function validate($psr, $scopes) + { + $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); + + $this->validateCredentials($token); + + $this->validateScopes($token, $scopes); + } + + /** + * Validate token credentials. + * + * @param \Laravel\Passport\Token $token + * @return void + * @throws \Illuminate\Auth\AuthenticationException + */ + abstract protected function validateCredentials($token); + + /** + * Validate token credentials. + * + * @param \Laravel\Passport\Token $token + * @param array $scopes + * @return void + * @throws \Laravel\Passport\Exceptions\MissingScopeException + */ + abstract protected function validateScopes($token, $scopes); +} From 983f873aba1c3eeb88709cf5deda3407d593cb1a Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Sun, 24 Nov 2019 15:13:12 +0800 Subject: [PATCH 011/353] Fixes CS. Signed-off-by: Mior Muhammad Zaki --- src/Http/Middleware/CheckClientCredentials.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index d2567f525..ca1c621b3 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -21,7 +21,6 @@ protected function validateCredentials($token) } } - /** * Validate token credentials. * From 952722f4f1817485bd30190e45fe4dc87ba67441 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 26 Nov 2019 18:35:30 +0100 Subject: [PATCH 012/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56f1e4b09..f60aebeca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.0.1...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.0.2...8.x) + + +## [v8.0.2 (2019-11-26)](https://github.com/laravel/passport/compare/v8.0.1...v8.0.2) + +### Changed +- Add abstract CheckCredentials middleware and allows to create ([#1127](https://github.com/laravel/passport/pull/1127)) ## [v8.0.1 (2019-11-19)](https://github.com/laravel/passport/compare/v8.0.0...v8.0.1) From 13140455b8c6b0e9dc655154f0fae6b02145d65d Mon Sep 17 00:00:00 2001 From: JuanDMeGon Date: Mon, 2 Dec 2019 19:08:13 -0500 Subject: [PATCH 013/353] Client credentials middleware should allow any valid client (#1125) --- .../Middleware/CheckClientCredentials.php | 2 +- .../CheckClientCredentialsForAnyScope.php | 2 +- .../CheckClientCredentialsForAnyScopeTest.php | 31 ------------------- tests/CheckClientCredentialsTest.php | 31 ------------------- 4 files changed, 2 insertions(+), 64 deletions(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index ca1c621b3..50d6fd1e0 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -16,7 +16,7 @@ class CheckClientCredentials extends CheckCredentials */ protected function validateCredentials($token) { - if (! $token || $token->client->firstParty()) { + if (! $token) { throw new AuthenticationException; } } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index c047774f2..3a2ea6e78 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -16,7 +16,7 @@ class CheckClientCredentialsForAnyScope extends CheckCredentials */ protected function validateCredentials($token) { - if (! $token || $token->client->firstParty()) { + if (! $token) { throw new AuthenticationException; } } diff --git a/tests/CheckClientCredentialsForAnyScopeTest.php b/tests/CheckClientCredentialsForAnyScopeTest.php index 96d9d646e..a4770cec2 100644 --- a/tests/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/CheckClientCredentialsForAnyScopeTest.php @@ -137,35 +137,4 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope() return 'response'; }, 'baz', 'notbar'); } - - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ - public function test_exception_is_thrown_if_token_belongs_to_first_party_client() - { - $resourceServer = m::mock(ResourceServer::class); - $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); - $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); - $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); - - $client = m::mock(Client::class); - $client->shouldReceive('firstParty')->andReturnTrue(); - - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository); - - $request = Request::create('/'); - $request->headers->set('Authorization', 'Bearer token'); - - $response = $middleware->handle($request, function () { - return 'response'; - }); - } } diff --git a/tests/CheckClientCredentialsTest.php b/tests/CheckClientCredentialsTest.php index 435ae9f7a..5cec6997a 100644 --- a/tests/CheckClientCredentialsTest.php +++ b/tests/CheckClientCredentialsTest.php @@ -136,35 +136,4 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scopes( return 'response'; }, 'foo', 'bar'); } - - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ - public function test_exception_is_thrown_if_token_belongs_to_first_party_client() - { - $resourceServer = m::mock(ResourceServer::class); - $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); - $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); - $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); - $psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']); - - $client = m::mock(Client::class); - $client->shouldReceive('firstParty')->andReturnTrue(); - - $token = m::mock(Token::class); - $token->shouldReceive('getAttribute')->with('client')->andReturn($client); - - $tokenRepository = m::mock(TokenRepository::class); - $tokenRepository->shouldReceive('find')->with('token')->andReturn($token); - - $middleware = new CheckClientCredentials($resourceServer, $tokenRepository); - - $request = Request::create('/'); - $request->headers->set('Authorization', 'Bearer token'); - - $response = $middleware->handle($request, function () { - return 'response'; - }); - } } From 68bf6be358bfb823cbe6de2fea41100f65ee1e1e Mon Sep 17 00:00:00 2001 From: Andrew Niemantsverdriet Date: Wed, 4 Dec 2019 16:33:10 -0700 Subject: [PATCH 014/353] Switch from getKey() to getAuthIdentifier() to be match Laravel core --- .../Controllers/AuthorizedAccessTokenController.php | 4 ++-- src/Http/Controllers/ClientController.php | 8 ++++---- src/Http/Controllers/PersonalAccessTokenController.php | 4 ++-- .../Controllers/RetrievesAuthRequestFromSession.php | 2 +- src/Http/Controllers/TransientTokenController.php | 2 +- tests/ApproveAuthorizationControllerTest.php | 2 +- tests/AuthorizedAccessTokenControllerTest.php | 6 +++--- tests/ClientControllerTest.php | 10 +++++----- tests/DenyAuthorizationControllerTest.php | 2 +- tests/PersonalAccessTokenControllerTest.php | 6 +++--- tests/TransientTokenControllerTest.php | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index a2a26b20a..184cdf0d2 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -34,7 +34,7 @@ public function __construct(TokenRepository $tokenRepository) */ public function forUser(Request $request) { - $tokens = $this->tokenRepository->forUser($request->user()->getKey()); + $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); return $tokens->load('client')->filter(function ($token) { return ! $token->client->firstParty() && ! $token->revoked; @@ -51,7 +51,7 @@ public function forUser(Request $request) public function destroy(Request $request, $tokenId) { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getKey() + $tokenId, $request->user()->getAuthIdentifier() ); if (is_null($token)) { diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 86abf00a0..1ef17d852 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -57,7 +57,7 @@ public function __construct( */ public function forUser(Request $request) { - $userId = $request->user()->getKey(); + $userId = $request->user()->getAuthIdentifier(); return $this->clients->activeForUser($userId)->makeVisible('secret'); } @@ -77,7 +77,7 @@ public function store(Request $request) ])->validate(); return $this->clients->create( - $request->user()->getKey(), $request->name, $request->redirect, + $request->user()->getAuthIdentifier(), $request->name, $request->redirect, false, false, (bool) $request->input('confidential', true) )->makeVisible('secret'); } @@ -91,7 +91,7 @@ public function store(Request $request) */ public function update(Request $request, $clientId) { - $client = $this->clients->findForUser($clientId, $request->user()->getKey()); + $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); if (! $client) { return new Response('', 404); @@ -116,7 +116,7 @@ public function update(Request $request, $clientId) */ public function destroy(Request $request, $clientId) { - $client = $this->clients->findForUser($clientId, $request->user()->getKey()); + $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); if (! $client) { return new Response('', 404); diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index 6b0dddcdc..81797e8c3 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -45,7 +45,7 @@ public function __construct(TokenRepository $tokenRepository, ValidationFactory */ public function forUser(Request $request) { - $tokens = $this->tokenRepository->forUser($request->user()->getKey()); + $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); return $tokens->load('client')->filter(function ($token) { return $token->client->personal_access_client && ! $token->revoked; @@ -80,7 +80,7 @@ public function store(Request $request) public function destroy(Request $request, $tokenId) { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getKey() + $tokenId, $request->user()->getAuthIdentifier() ); if (is_null($token)) { diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index c1182eb5b..fa19bc2b7 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -22,7 +22,7 @@ protected function getAuthRequestFromSession(Request $request) throw new Exception('Authorization request was not present in the session.'); } - $authRequest->setUser(new User($request->user()->getKey())); + $authRequest->setUser(new User($request->user()->getAuthIdentifier())); $authRequest->setAuthorizationApproved(true); }); diff --git a/src/Http/Controllers/TransientTokenController.php b/src/Http/Controllers/TransientTokenController.php index 0f7b99ab6..2cb56ba3e 100644 --- a/src/Http/Controllers/TransientTokenController.php +++ b/src/Http/Controllers/TransientTokenController.php @@ -35,7 +35,7 @@ public function __construct(ApiTokenCookieFactory $cookieFactory) public function refresh(Request $request) { return (new Response('Refreshed.'))->withCookie($this->cookieFactory->make( - $request->user()->getKey(), $request->session()->token() + $request->user()->getAuthIdentifier(), $request->session()->token() )); } } diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index 843143a44..f05b89c6b 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -51,7 +51,7 @@ class ApproveAuthorizationControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/AuthorizedAccessTokenControllerTest.php b/tests/AuthorizedAccessTokenControllerTest.php index bf863c393..e8e71429a 100644 --- a/tests/AuthorizedAccessTokenControllerTest.php +++ b/tests/AuthorizedAccessTokenControllerTest.php @@ -58,7 +58,7 @@ public function test_tokens_can_be_retrieved_for_users() $request->setUserResolver(function () use ($token1, $token2) { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -81,7 +81,7 @@ public function test_tokens_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -99,7 +99,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); diff --git a/tests/ClientControllerTest.php b/tests/ClientControllerTest.php index a0de7d236..f1faf89bb 100644 --- a/tests/ClientControllerTest.php +++ b/tests/ClientControllerTest.php @@ -120,7 +120,7 @@ public function test_clients_can_be_updated() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -157,7 +157,7 @@ public function test_404_response_if_client_doesnt_belong_to_user() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -183,7 +183,7 @@ public function test_clients_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -212,7 +212,7 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -233,7 +233,7 @@ class ClientControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/DenyAuthorizationControllerTest.php b/tests/DenyAuthorizationControllerTest.php index 5401483b3..4d1df8210 100644 --- a/tests/DenyAuthorizationControllerTest.php +++ b/tests/DenyAuthorizationControllerTest.php @@ -160,7 +160,7 @@ class DenyAuthorizationControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/PersonalAccessTokenControllerTest.php b/tests/PersonalAccessTokenControllerTest.php index 81d78e01a..c1951b62c 100644 --- a/tests/PersonalAccessTokenControllerTest.php +++ b/tests/PersonalAccessTokenControllerTest.php @@ -38,7 +38,7 @@ public function test_tokens_can_be_retrieved_for_users() $request->setUserResolver(function () use ($token1, $token2) { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -98,7 +98,7 @@ public function test_tokens_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -120,7 +120,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); diff --git a/tests/TransientTokenControllerTest.php b/tests/TransientTokenControllerTest.php index cfa978694..6b952717c 100644 --- a/tests/TransientTokenControllerTest.php +++ b/tests/TransientTokenControllerTest.php @@ -23,7 +23,7 @@ public function test_token_can_be_refreshed() $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldReceive('session->token')->andReturn('token'); $controller = new TransientTokenController($cookieFactory); From 05e5c20b3ec01d457ded74fe5150bdebc96449c4 Mon Sep 17 00:00:00 2001 From: Andrew Niemantsverdriet Date: Wed, 4 Dec 2019 16:33:10 -0700 Subject: [PATCH 015/353] Switch from getKey() to getAuthIdentifier() to be match Laravel core --- src/Http/Controllers/AuthorizationController.php | 2 +- .../Controllers/AuthorizedAccessTokenController.php | 4 ++-- src/Http/Controllers/ClientController.php | 8 ++++---- src/Http/Controllers/PersonalAccessTokenController.php | 4 ++-- .../Controllers/RetrievesAuthRequestFromSession.php | 2 +- src/Http/Controllers/TransientTokenController.php | 2 +- src/Http/Middleware/CreateFreshApiToken.php | 2 +- src/TokenRepository.php | 4 ++-- tests/ApproveAuthorizationControllerTest.php | 2 +- tests/AuthorizationControllerTest.php | 4 ++-- tests/AuthorizedAccessTokenControllerTest.php | 6 +++--- tests/ClientControllerTest.php | 10 +++++----- tests/CreateFreshApiTokenTest.php | 4 ++-- tests/DenyAuthorizationControllerTest.php | 2 +- tests/PersonalAccessTokenControllerTest.php | 6 +++--- tests/TransientTokenControllerTest.php | 2 +- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index bfedb3e8c..fcbb19305 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -107,7 +107,7 @@ protected function parseScopes($authRequest) */ protected function approveRequest($authRequest, $user) { - $authRequest->setUser(new User($user->getKey())); + $authRequest->setUser(new User($user->getAuthIdentifier())); $authRequest->setAuthorizationApproved(true); diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index a2a26b20a..184cdf0d2 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -34,7 +34,7 @@ public function __construct(TokenRepository $tokenRepository) */ public function forUser(Request $request) { - $tokens = $this->tokenRepository->forUser($request->user()->getKey()); + $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); return $tokens->load('client')->filter(function ($token) { return ! $token->client->firstParty() && ! $token->revoked; @@ -51,7 +51,7 @@ public function forUser(Request $request) public function destroy(Request $request, $tokenId) { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getKey() + $tokenId, $request->user()->getAuthIdentifier() ); if (is_null($token)) { diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 86abf00a0..1ef17d852 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -57,7 +57,7 @@ public function __construct( */ public function forUser(Request $request) { - $userId = $request->user()->getKey(); + $userId = $request->user()->getAuthIdentifier(); return $this->clients->activeForUser($userId)->makeVisible('secret'); } @@ -77,7 +77,7 @@ public function store(Request $request) ])->validate(); return $this->clients->create( - $request->user()->getKey(), $request->name, $request->redirect, + $request->user()->getAuthIdentifier(), $request->name, $request->redirect, false, false, (bool) $request->input('confidential', true) )->makeVisible('secret'); } @@ -91,7 +91,7 @@ public function store(Request $request) */ public function update(Request $request, $clientId) { - $client = $this->clients->findForUser($clientId, $request->user()->getKey()); + $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); if (! $client) { return new Response('', 404); @@ -116,7 +116,7 @@ public function update(Request $request, $clientId) */ public function destroy(Request $request, $clientId) { - $client = $this->clients->findForUser($clientId, $request->user()->getKey()); + $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); if (! $client) { return new Response('', 404); diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index 6b0dddcdc..81797e8c3 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -45,7 +45,7 @@ public function __construct(TokenRepository $tokenRepository, ValidationFactory */ public function forUser(Request $request) { - $tokens = $this->tokenRepository->forUser($request->user()->getKey()); + $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); return $tokens->load('client')->filter(function ($token) { return $token->client->personal_access_client && ! $token->revoked; @@ -80,7 +80,7 @@ public function store(Request $request) public function destroy(Request $request, $tokenId) { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getKey() + $tokenId, $request->user()->getAuthIdentifier() ); if (is_null($token)) { diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index c1182eb5b..fa19bc2b7 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -22,7 +22,7 @@ protected function getAuthRequestFromSession(Request $request) throw new Exception('Authorization request was not present in the session.'); } - $authRequest->setUser(new User($request->user()->getKey())); + $authRequest->setUser(new User($request->user()->getAuthIdentifier())); $authRequest->setAuthorizationApproved(true); }); diff --git a/src/Http/Controllers/TransientTokenController.php b/src/Http/Controllers/TransientTokenController.php index 0f7b99ab6..2cb56ba3e 100644 --- a/src/Http/Controllers/TransientTokenController.php +++ b/src/Http/Controllers/TransientTokenController.php @@ -35,7 +35,7 @@ public function __construct(ApiTokenCookieFactory $cookieFactory) public function refresh(Request $request) { return (new Response('Refreshed.'))->withCookie($this->cookieFactory->make( - $request->user()->getKey(), $request->session()->token() + $request->user()->getAuthIdentifier(), $request->session()->token() )); } } diff --git a/src/Http/Middleware/CreateFreshApiToken.php b/src/Http/Middleware/CreateFreshApiToken.php index 64183d56d..4ad06b2ec 100644 --- a/src/Http/Middleware/CreateFreshApiToken.php +++ b/src/Http/Middleware/CreateFreshApiToken.php @@ -51,7 +51,7 @@ public function handle($request, Closure $next, $guard = null) if ($this->shouldReceiveFreshToken($request, $response)) { $response->withCookie($this->cookieFactory->make( - $request->user($this->guard)->getKey(), $request->session()->token() + $request->user($this->guard)->getAuthIdentifier(), $request->session()->token() )); } diff --git a/src/TokenRepository.php b/src/TokenRepository.php index 074be6037..81070903d 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -61,7 +61,7 @@ public function forUser($userId) public function getValidToken($user, $client) { return $client->tokens() - ->whereUserId($user->getKey()) + ->whereUserId($user->getAuthIdentifier()) ->where('revoked', 0) ->where('expires_at', '>', Carbon::now()) ->first(); @@ -115,7 +115,7 @@ public function isAccessTokenRevoked($id) public function findValidToken($user, $client) { return $client->tokens() - ->whereUserId($user->getKey()) + ->whereUserId($user->getAuthIdentifier()) ->where('revoked', 0) ->where('expires_at', '>', Carbon::now()) ->latest('expires_at') diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index 843143a44..f05b89c6b 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -51,7 +51,7 @@ class ApproveAuthorizationControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/AuthorizationControllerTest.php b/tests/AuthorizationControllerTest.php index e9f47e4e7..574013085 100644 --- a/tests/AuthorizationControllerTest.php +++ b/tests/AuthorizationControllerTest.php @@ -113,7 +113,7 @@ public function test_request_is_approved_if_valid_token_exists() $request = m::mock(Request::class); $request->shouldReceive('user')->once()->andReturn($user = m::mock()); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); @@ -155,7 +155,7 @@ public function test_request_is_approved_if_client_can_skip_authorization() $request = m::mock(Request::class); $request->shouldReceive('user')->once()->andReturn($user = m::mock()); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); diff --git a/tests/AuthorizedAccessTokenControllerTest.php b/tests/AuthorizedAccessTokenControllerTest.php index bf863c393..e8e71429a 100644 --- a/tests/AuthorizedAccessTokenControllerTest.php +++ b/tests/AuthorizedAccessTokenControllerTest.php @@ -58,7 +58,7 @@ public function test_tokens_can_be_retrieved_for_users() $request->setUserResolver(function () use ($token1, $token2) { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -81,7 +81,7 @@ public function test_tokens_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -99,7 +99,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); diff --git a/tests/ClientControllerTest.php b/tests/ClientControllerTest.php index a0de7d236..f1faf89bb 100644 --- a/tests/ClientControllerTest.php +++ b/tests/ClientControllerTest.php @@ -120,7 +120,7 @@ public function test_clients_can_be_updated() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -157,7 +157,7 @@ public function test_404_response_if_client_doesnt_belong_to_user() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -183,7 +183,7 @@ public function test_clients_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -212,7 +212,7 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -233,7 +233,7 @@ class ClientControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/CreateFreshApiTokenTest.php b/tests/CreateFreshApiTokenTest.php index 49df84089..837bd1e2a 100644 --- a/tests/CreateFreshApiTokenTest.php +++ b/tests/CreateFreshApiTokenTest.php @@ -29,7 +29,7 @@ public function testShouldReceiveAFreshToken() $guard = 'guard'; $user = m::mock() - ->shouldReceive('getKey') + ->shouldReceive('getAuthIdentifier') ->andReturn($userKey = 1) ->getMock(); @@ -99,7 +99,7 @@ public function testShouldNotReceiveAFreshTokenForResponseThatAlreadyHasToken() $request->setUserResolver(function () { return m::mock() - ->shouldReceive('getKey') + ->shouldReceive('getAuthIdentifier') ->andReturn(1) ->getMock(); }); diff --git a/tests/DenyAuthorizationControllerTest.php b/tests/DenyAuthorizationControllerTest.php index 5401483b3..4d1df8210 100644 --- a/tests/DenyAuthorizationControllerTest.php +++ b/tests/DenyAuthorizationControllerTest.php @@ -160,7 +160,7 @@ class DenyAuthorizationControllerFakeUser { public $id = 1; - public function getKey() + public function getAuthIdentifier() { return $this->id; } diff --git a/tests/PersonalAccessTokenControllerTest.php b/tests/PersonalAccessTokenControllerTest.php index 81d78e01a..c1951b62c 100644 --- a/tests/PersonalAccessTokenControllerTest.php +++ b/tests/PersonalAccessTokenControllerTest.php @@ -38,7 +38,7 @@ public function test_tokens_can_be_retrieved_for_users() $request->setUserResolver(function () use ($token1, $token2) { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -98,7 +98,7 @@ public function test_tokens_can_be_deleted() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); @@ -120,7 +120,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $request->setUserResolver(function () { $user = m::mock(); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); diff --git a/tests/TransientTokenControllerTest.php b/tests/TransientTokenControllerTest.php index cfa978694..6b952717c 100644 --- a/tests/TransientTokenControllerTest.php +++ b/tests/TransientTokenControllerTest.php @@ -23,7 +23,7 @@ public function test_token_can_be_refreshed() $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); - $user->shouldReceive('getKey')->andReturn(1); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldReceive('session->token')->andReturn('token'); $controller = new TransientTokenController($cookieFactory); From 1edb3e6103c05a9fc92efd378f4a91bc6f09482b Mon Sep 17 00:00:00 2001 From: Gege Date: Sat, 7 Dec 2019 10:20:09 +0100 Subject: [PATCH 016/353] Docs, remove unused import --- src/Bridge/AccessToken.php | 2 +- src/Bridge/AccessTokenRepository.php | 1 + src/Bridge/Client.php | 1 + src/Bridge/ClientRepository.php | 3 +++ src/Bridge/UserRepository.php | 1 - src/ClientRepository.php | 2 +- .../Controllers/RetrievesAuthRequestFromSession.php | 1 + src/Http/Middleware/CheckClientCredentials.php | 2 ++ .../Middleware/CheckClientCredentialsForAnyScope.php | 2 ++ src/Http/Middleware/CheckCredentials.php | 4 ++++ src/Http/Middleware/CheckForAnyScope.php | 1 + src/Http/Middleware/CheckScopes.php | 1 + src/Http/Rules/RedirectRule.php | 10 +++++++++- src/PassportServiceProvider.php | 2 +- src/PersonalAccessTokenFactory.php | 2 +- src/TokenRepository.php | 3 +-- 16 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Bridge/AccessToken.php b/src/Bridge/AccessToken.php index ba3625276..77d37c52b 100644 --- a/src/Bridge/AccessToken.php +++ b/src/Bridge/AccessToken.php @@ -17,7 +17,7 @@ class AccessToken implements AccessTokenEntityInterface * * @param string $userIdentifier * @param array $scopes - * @param ClientEntityInterface $client + * @param \League\OAuth2\Server\Entities\ClientEntityInterface $client * @return void */ public function __construct($userIdentifier, array $scopes, ClientEntityInterface $client) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index e1f892e7c..0fe2be49b 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -33,6 +33,7 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface * * @param \Laravel\Passport\TokenRepository $tokenRepository * @param \Illuminate\Contracts\Events\Dispatcher $events + * @return void */ public function __construct(TokenRepository $tokenRepository, Dispatcher $events) { diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index 18dac7c79..43eec2029 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -48,6 +48,7 @@ public function getIdentifier() * Set the client's identifier. * * @param string $identifier + * @return void */ public function setIdentifier($identifier) { diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 1f85ab6b1..9cd17762e 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -41,6 +41,9 @@ public function getClientEntity($clientIdentifier) ); } + /** + * {@inheritdoc} + */ public function validateClient($clientIdentifier, $clientSecret, $grantType) { // First, we will verify that the client exists and is authorized to create personal diff --git a/src/Bridge/UserRepository.php b/src/Bridge/UserRepository.php index 59b003095..ed16250c8 100644 --- a/src/Bridge/UserRepository.php +++ b/src/Bridge/UserRepository.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Contracts\Hashing\Hasher; use Illuminate\Hashing\HashManager; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\UserRepositoryInterface; diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 7a5d24e75..a8b9431ef 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -159,7 +159,7 @@ public function createPasswordGrantClient($userId, $name, $redirect) /** * Update the given client. * - * @param Client $client + * @param \Laravel\Passport\Client $client * @param string $name * @param string $redirect * @return \Laravel\Passport\Client diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index c1182eb5b..4ab67b36d 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -13,6 +13,7 @@ trait RetrievesAuthRequestFromSession * * @param \Illuminate\Http\Request $request * @return \League\OAuth2\Server\RequestTypes\AuthorizationRequest + * * @throws \Exception */ protected function getAuthRequestFromSession(Request $request) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index ca1c621b3..a24959dbe 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -12,6 +12,7 @@ class CheckClientCredentials extends CheckCredentials * * @param \Laravel\Passport\Token $token * @return void + * * @throws \Illuminate\Auth\AuthenticationException */ protected function validateCredentials($token) @@ -27,6 +28,7 @@ protected function validateCredentials($token) * @param \Laravel\Passport\Token $token * @param array $scopes * @return void + * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ protected function validateScopes($token, $scopes) diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index c047774f2..e1f7b23ff 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -12,6 +12,7 @@ class CheckClientCredentialsForAnyScope extends CheckCredentials * * @param \Laravel\Passport\Token $token * @return void + * * @throws \Illuminate\Auth\AuthenticationException */ protected function validateCredentials($token) @@ -27,6 +28,7 @@ protected function validateCredentials($token) * @param \Laravel\Passport\Token $token * @param array $scopes * @return void + * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ protected function validateScopes($token, $scopes) diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 6c28b6563..e35063ffc 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -49,6 +49,7 @@ public function __construct(ResourceServer $server, TokenRepository $repository) * @param \Closure $next * @param mixed ...$scopes * @return mixed + * * @throws \Illuminate\Auth\AuthenticationException */ public function handle($request, Closure $next, ...$scopes) @@ -77,6 +78,7 @@ public function handle($request, Closure $next, ...$scopes) * @param \Psr\Http\Message\ServerRequestInterface $psr * @param array $scopes * @return void + * * @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException */ protected function validate($psr, $scopes) @@ -93,6 +95,7 @@ protected function validate($psr, $scopes) * * @param \Laravel\Passport\Token $token * @return void + * * @throws \Illuminate\Auth\AuthenticationException */ abstract protected function validateCredentials($token); @@ -103,6 +106,7 @@ abstract protected function validateCredentials($token); * @param \Laravel\Passport\Token $token * @param array $scopes * @return void + * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ abstract protected function validateScopes($token, $scopes); diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index afd4f60cd..0bb9653f7 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -14,6 +14,7 @@ class CheckForAnyScope * @param \Closure $next * @param mixed ...$scopes * @return \Illuminate\Http\Response + * * @throws \Illuminate\Auth\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ public function handle($request, $next, ...$scopes) diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index de7898df0..e19f1097e 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -14,6 +14,7 @@ class CheckScopes * @param \Closure $next * @param mixed ...$scopes * @return \Illuminate\Http\Response + * * @throws \Illuminate\Auth\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ public function handle($request, $next, ...$scopes) diff --git a/src/Http/Rules/RedirectRule.php b/src/Http/Rules/RedirectRule.php index 885306ee5..dd8b99720 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -8,10 +8,18 @@ class RedirectRule implements Rule { /** + * The validator instance. + * * @var \Illuminate\Contracts\Validation\Factory */ - private $validator; + protected $validator; + /** + * Create a new rule instance. + * + * @param \Illuminate\Contracts\Validation\Factory $validator + * @return void + */ public function __construct(Factory $validator) { $this->validator = $validator; diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 70a24bf39..038202666 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -229,7 +229,7 @@ protected function registerResourceServer() /** * Create a CryptKey instance without permissions check. * - * @param string $key + * @param string $key * @return \League\OAuth2\Server\CryptKey */ protected function makeCryptKey($type) diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 0cc4b11cf..46a86f991 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -119,7 +119,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequest $request) * Get the access token instance for the parsed response. * * @param array $response - * @return Token + * @return \Laravel\Passport\Token */ protected function findAccessToken(array $response) { diff --git a/src/TokenRepository.php b/src/TokenRepository.php index 074be6037..dc5dc5f15 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -93,8 +93,7 @@ public function revokeAccessToken($id) * Check if the access token has been revoked. * * @param string $id - * - * @return bool Return true if this token has been revoked + * @return bool */ public function isAccessTokenRevoked($id) { From 19b7fb2c1206533ec3c8cd4ee0ec8ce226af8375 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 9 Dec 2019 18:40:39 +0100 Subject: [PATCH 017/353] Test on PHP 7.4 --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 576e92a75..e70bb8230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ +dist: bionic language: php -sudo: false - php: - 7.2 - 7.3 + - 7.4 env: matrix: @@ -22,4 +22,5 @@ before_install: install: - travis_retry composer require "illuminate/contracts=${LARAVEL}" --dev --prefer-dist --no-interaction --no-suggest -script: vendor/bin/phpunit --verbose +script: + - vendor/bin/phpunit --verbose From 048c7578cf4fd34237e85898a1282aff898e9440 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Sun, 15 Dec 2019 10:50:19 -0600 Subject: [PATCH 018/353] formatting --- src/Passport.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Passport.php b/src/Passport.php index a68546951..103ff3957 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -423,6 +423,7 @@ public static function actingAs($user, $scopes = [], $guard = 'api') public static function actingAsClient($client, $scopes = []) { $token = app(self::tokenModel()); + $token->client = $client; $token->scopes = $scopes; From 738cb3a297fdc362e325a70dcd816d026233a7ab Mon Sep 17 00:00:00 2001 From: GuntherDebrauwer <22586858+GuntherDebrauwer@users.noreply.github.com> Date: Sat, 21 Dec 2019 14:14:29 +0100 Subject: [PATCH 019/353] Update UserRepository to check/use 'findAndValidateForPassport' method on user model --- src/Bridge/UserRepository.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Bridge/UserRepository.php b/src/Bridge/UserRepository.php index ed16250c8..8b0f6237d 100644 --- a/src/Bridge/UserRepository.php +++ b/src/Bridge/UserRepository.php @@ -38,6 +38,16 @@ public function getUserEntityByUserCredentials($username, $password, $grantType, throw new RuntimeException('Unable to determine authentication model from configuration.'); } + if (method_exists($model, 'findAndValidateForPassport')) { + $user = (new $model)->findAndValidateForPassport($username, $password); + + if (! $user) { + return; + } + + return new User($user->getAuthIdentifier()); + } + if (method_exists($model, 'findForPassport')) { $user = (new $model)->findForPassport($username); } else { From e5a53c6d8ec23dac1c566d2c22dfc68f839db976 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 13:58:52 +0100 Subject: [PATCH 020/353] Enable the option of hashing client secrets --- ...6_01_000004_create_oauth_clients_table.php | 2 +- src/Bridge/ClientRepository.php | 27 ++++++++++++- src/Client.php | 38 +++++++++++++++++++ src/Passport.php | 19 ++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 2141e9973..cb1617d77 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -17,7 +17,7 @@ public function up() $table->increments('id'); $table->bigInteger('user_id')->index()->nullable(); $table->string('name'); - $table->string('secret', 100)->nullable(); + $table->string('secret')->nullable(); $table->text('redirect'); $table->boolean('personal_access_client'); $table->boolean('password_client'); diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 9cd17762e..b58b272bc 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -2,7 +2,9 @@ namespace Laravel\Passport\Bridge; +use Illuminate\Contracts\Hashing\Hasher; use Laravel\Passport\ClientRepository as ClientModelRepository; +use Laravel\Passport\Passport; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; class ClientRepository implements ClientRepositoryInterface @@ -14,15 +16,22 @@ class ClientRepository implements ClientRepositoryInterface */ protected $clients; + /** + * @var \Illuminate\Contracts\Hashing\Hasher + */ + protected $hasher; + /** * Create a new repository instance. * * @param \Laravel\Passport\ClientRepository $clients + * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return void */ - public function __construct(ClientModelRepository $clients) + public function __construct(ClientModelRepository $clients, Hasher $hasher) { $this->clients = $clients; + $this->hasher = $hasher; } /** @@ -55,7 +64,7 @@ public function validateClient($clientIdentifier, $clientSecret, $grantType) return false; } - return ! $record->confidential() || hash_equals($record->secret, (string) $clientSecret); + return ! $record->confidential() || $this->verifySecret($record->secret, (string) $clientSecret); } /** @@ -84,4 +93,18 @@ protected function handlesGrant($record, $grantType) return true; } } + + /** + * @param string $storedHash + * @param string $clientSecret + * @return bool + */ + protected function verifySecret($storedHash, $clientSecret) + { + if (Passport::$useHashedClientSecrets) { + return $this->hasher->check($clientSecret, $storedHash); + } + + return hash_equals($storedHash, $clientSecret); + } } diff --git a/src/Client.php b/src/Client.php index 51b2b7013..e62ead6ff 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,6 +2,7 @@ namespace Laravel\Passport; +use Illuminate\Contracts\Hashing\Hasher; use Illuminate\Database\Eloquent\Model; class Client extends Model @@ -41,6 +42,13 @@ class Client extends Model 'revoked' => 'bool', ]; + /** + * The temporary non-hashed client secret. + * + * @var string|null + */ + protected $plainSecret; + /** * Get the user that the client belongs to. * @@ -73,6 +81,36 @@ public function tokens() return $this->hasMany(Passport::tokenModel(), 'client_id'); } + /** + * @param string|null $value + */ + public function setSecretAttribute($value) + { + $this->plainSecret = $value; + + if ($value === null || ! Passport::$useHashedClientSecrets) { + $this->attributes['secret'] = $value; + + return; + } + + $this->attributes['secret'] = app(Hasher::class)->make($value); + } + + /** + * The temporary non-hashed client secret. + * + * If you're using hashed client secrets, this value will only be available + * once during the request the client was created. Afterwards, it cannot + * be retrieved or decrypted anymore. + * + * @return string|null + */ + public function plainSecret() + { + return $this->plainSecret; + } + /** * Determine if the client is a "first party" client. * diff --git a/src/Passport.php b/src/Passport.php index a68546951..6a26ea6b1 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -146,6 +146,13 @@ class Passport */ public static $unserializesCookies = false; + /** + * + * + * @var bool + */ + public static $useHashedClientSecrets = false; + /** * Indicates the scope should inherit its parent scope. * @@ -637,6 +644,18 @@ public static function ignoreMigrations() return new static; } + /** + * Configure Passport to hash client credential secrets. + * + * @return static + */ + public static function useHashedClientSecrets() + { + static::$useHashedClientSecrets = true; + + return new static; + } + /** * Instruct Passport to enable cookie serialization. * From 68bd83af45e01aaaf3da63e51d946b158bec0b99 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 14:03:43 +0100 Subject: [PATCH 021/353] Alias HasherContract --- src/Bridge/ClientRepository.php | 4 ++-- src/Client.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index b58b272bc..7ccf5d0f1 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Contracts\Hashing\Hasher; +use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Laravel\Passport\ClientRepository as ClientModelRepository; use Laravel\Passport\Passport; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; @@ -28,7 +28,7 @@ class ClientRepository implements ClientRepositoryInterface * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return void */ - public function __construct(ClientModelRepository $clients, Hasher $hasher) + public function __construct(ClientModelRepository $clients, HasherContract $hasher) { $this->clients = $clients; $this->hasher = $hasher; diff --git a/src/Client.php b/src/Client.php index e62ead6ff..efe0cc6d9 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,7 +2,7 @@ namespace Laravel\Passport; -use Illuminate\Contracts\Hashing\Hasher; +use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Illuminate\Database\Eloquent\Model; class Client extends Model @@ -94,7 +94,7 @@ public function setSecretAttribute($value) return; } - $this->attributes['secret'] = app(Hasher::class)->make($value); + $this->attributes['secret'] = app(HasherContract::class)->make($value); } /** From 4fe227de8b9b93e233064f23dcab9ba413017c1a Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 14:09:13 +0100 Subject: [PATCH 022/353] Provide hasher to constructor in test --- tests/BridgeClientRepositoryTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index 94a014323..fa5260946 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests; +use Illuminate\Contracts\Hashing\Hasher; use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\ClientRepository as BridgeClientRepository; use Laravel\Passport\ClientRepository; @@ -22,13 +23,15 @@ class BridgeClientRepositoryTest extends TestCase protected function setUp(): void { + $hasher = m::mock(Hasher::class); + $clientModelRepository = m::mock(ClientRepository::class); $clientModelRepository->shouldReceive('findActive') ->with(1) ->andReturn(new BridgeClientRepositoryTestClientStub); $this->clientModelRepository = $clientModelRepository; - $this->repository = new BridgeClientRepository($clientModelRepository); + $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); } protected function tearDown(): void From 04d952b9e370c0824644289907c6e02c1b188495 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 14:13:54 +0100 Subject: [PATCH 023/353] Use model attribute getter to return plain secret --- src/Client.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Client.php b/src/Client.php index efe0cc6d9..ca9a4cb0b 100644 --- a/src/Client.php +++ b/src/Client.php @@ -81,6 +81,20 @@ public function tokens() return $this->hasMany(Passport::tokenModel(), 'client_id'); } + /** + * The temporary non-hashed client secret. + * + * If you're using hashed client secrets, this value will only be available + * once during the request the client was created. Afterwards, it cannot + * be retrieved or decrypted anymore. + * + * @return string|null + */ + public function getPlainSecretAttribute() + { + return $this->plainSecret; + } + /** * @param string|null $value */ @@ -97,20 +111,6 @@ public function setSecretAttribute($value) $this->attributes['secret'] = app(HasherContract::class)->make($value); } - /** - * The temporary non-hashed client secret. - * - * If you're using hashed client secrets, this value will only be available - * once during the request the client was created. Afterwards, it cannot - * be retrieved or decrypted anymore. - * - * @return string|null - */ - public function plainSecret() - { - return $this->plainSecret; - } - /** * Determine if the client is a "first party" client. * From 6aa59b0982f4332c3642825d4c23856f2b9ae02c Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 16:51:56 +0100 Subject: [PATCH 024/353] Flip method parameters for convention --- src/Bridge/ClientRepository.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 7ccf5d0f1..536ccb37f 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -64,7 +64,7 @@ public function validateClient($clientIdentifier, $clientSecret, $grantType) return false; } - return ! $record->confidential() || $this->verifySecret($record->secret, (string) $clientSecret); + return ! $record->confidential() || $this->verifySecret((string) $clientSecret, $record->secret); } /** @@ -95,11 +95,11 @@ protected function handlesGrant($record, $grantType) } /** - * @param string $storedHash * @param string $clientSecret + * @param string $storedHash * @return bool */ - protected function verifySecret($storedHash, $clientSecret) + protected function verifySecret($clientSecret, $storedHash) { if (Passport::$useHashedClientSecrets) { return $this->hasher->check($clientSecret, $storedHash); From 6b23d3966f29c8484337ba653b1518d411878baf Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 16:59:15 +0100 Subject: [PATCH 025/353] Add hashed client secrets tests --- ...ridgeClientRepositoryHashedSecretsTest.php | 62 +++++++++++++++++++ tests/BridgeClientRepositoryTest.php | 4 +- 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/BridgeClientRepositoryHashedSecretsTest.php diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php new file mode 100644 index 000000000..db4b44d79 --- /dev/null +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -0,0 +1,62 @@ +shouldReceive('check') + ->with('secret', 'hashedsecret') + ->andReturnTrue(); + + $hasher->shouldReceive('check') + ->with('wrong-secret', 'hashedsecret') + ->andReturnFalse(); + + $clientModelRepository = m::mock(ClientRepository::class); + $clientModelRepository->shouldReceive('findActive') + ->with(1) + ->andReturn(new BridgeClientRepositoryHashedTestClientStub); + + $this->clientModelRepository = $clientModelRepository; + $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); + } +} + +class BridgeClientRepositoryHashedTestClientStub +{ + public $name = 'Client'; + + public $redirect = 'http://localhost'; + + public $secret = 'hashedsecret'; + + public $personal_access_client = false; + + public $password_client = false; + + public $grant_types; + + public function firstParty() + { + return $this->personal_access_client || $this->password_client; + } + + public function confidential() + { + return ! empty($this->secret); + } +} diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index fa5260946..b06f29a40 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -14,12 +14,12 @@ class BridgeClientRepositoryTest extends TestCase /** * @var \Laravel\Passport\ClientRepository */ - private $clientModelRepository; + protected $clientModelRepository; /** * @var \Laravel\Passport\Bridge\ClientRepository */ - private $repository; + protected $repository; protected function setUp(): void { From 1a73c40b634ecf35d7766de36c57d8fc76c9d9be Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 17:29:41 +0100 Subject: [PATCH 026/353] Format code --- src/Passport.php | 2 -- tests/BridgeClientRepositoryHashedSecretsTest.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index 6a26ea6b1..e9b04fdb8 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -147,8 +147,6 @@ class Passport public static $unserializesCookies = false; /** - * - * * @var bool */ public static $useHashedClientSecrets = false; diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index db4b44d79..0c0c21bf9 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -3,12 +3,10 @@ namespace Laravel\Passport\Tests; use Illuminate\Contracts\Hashing\Hasher; -use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\ClientRepository as BridgeClientRepository; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Mockery as m; -use PHPUnit\Framework\TestCase; class BridgeClientRepositoryHashedSecretsTest extends BridgeClientRepositoryTest { From 4b140ff02984874035954751ac966dca1080dec5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Sun, 22 Dec 2019 17:46:53 +0100 Subject: [PATCH 027/353] Fix tests Explicitly disable public static check to use hashed secrets when running all tests --- tests/BridgeClientRepositoryHashedSecretsTest.php | 2 ++ tests/BridgeClientRepositoryTest.php | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index 0c0c21bf9..5f1a78cfc 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -30,6 +30,8 @@ protected function setUp(): void ->andReturn(new BridgeClientRepositoryHashedTestClientStub); $this->clientModelRepository = $clientModelRepository; + $this->hasher = $hasher; + $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); } } diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index b06f29a40..9e4add185 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -6,6 +6,7 @@ use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\ClientRepository as BridgeClientRepository; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Passport; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -16,6 +17,11 @@ class BridgeClientRepositoryTest extends TestCase */ protected $clientModelRepository; + /** + * @var \Illuminate\Contracts\Hashing\Hasher + */ + protected $hasher; + /** * @var \Laravel\Passport\Bridge\ClientRepository */ @@ -23,6 +29,8 @@ class BridgeClientRepositoryTest extends TestCase protected function setUp(): void { + Passport::$useHashedClientSecrets = false; + $hasher = m::mock(Hasher::class); $clientModelRepository = m::mock(ClientRepository::class); @@ -31,6 +39,7 @@ protected function setUp(): void ->andReturn(new BridgeClientRepositoryTestClientStub); $this->clientModelRepository = $clientModelRepository; + $this->hasher = $hasher; $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); } From 91cbc05838757902581320b3d021fb5029479757 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Mon, 23 Dec 2019 21:43:13 +0100 Subject: [PATCH 028/353] Use SHA-256 hashing for client secrets --- ...6_01_000004_create_oauth_clients_table.php | 2 +- src/Bridge/ClientRepository.php | 12 +----- src/Client.php | 3 +- ...ridgeClientRepositoryHashedSecretsTest.php | 38 ++----------------- tests/BridgeClientRepositoryTest.php | 6 +-- 5 files changed, 8 insertions(+), 53 deletions(-) diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index cb1617d77..2141e9973 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -17,7 +17,7 @@ public function up() $table->increments('id'); $table->bigInteger('user_id')->index()->nullable(); $table->string('name'); - $table->string('secret')->nullable(); + $table->string('secret', 100)->nullable(); $table->text('redirect'); $table->boolean('personal_access_client'); $table->boolean('password_client'); diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 536ccb37f..07b0bbfea 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Laravel\Passport\ClientRepository as ClientModelRepository; use Laravel\Passport\Passport; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; @@ -16,22 +15,15 @@ class ClientRepository implements ClientRepositoryInterface */ protected $clients; - /** - * @var \Illuminate\Contracts\Hashing\Hasher - */ - protected $hasher; - /** * Create a new repository instance. * * @param \Laravel\Passport\ClientRepository $clients - * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return void */ - public function __construct(ClientModelRepository $clients, HasherContract $hasher) + public function __construct(ClientModelRepository $clients) { $this->clients = $clients; - $this->hasher = $hasher; } /** @@ -102,7 +94,7 @@ protected function handlesGrant($record, $grantType) protected function verifySecret($clientSecret, $storedHash) { if (Passport::$useHashedClientSecrets) { - return $this->hasher->check($clientSecret, $storedHash); + return password_verify($clientSecret, $storedHash); } return hash_equals($storedHash, $clientSecret); diff --git a/src/Client.php b/src/Client.php index ca9a4cb0b..d50847725 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,7 +2,6 @@ namespace Laravel\Passport; -use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Illuminate\Database\Eloquent\Model; class Client extends Model @@ -108,7 +107,7 @@ public function setSecretAttribute($value) return; } - $this->attributes['secret'] = app(HasherContract::class)->make($value); + $this->attributes['secret'] = password_hash($value, CRYPT_SHA256); } /** diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index 5f1a78cfc..b74de0b41 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests; -use Illuminate\Contracts\Hashing\Hasher; use Laravel\Passport\Bridge\ClientRepository as BridgeClientRepository; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; @@ -14,49 +13,18 @@ protected function setUp(): void { Passport::useHashedClientSecrets(); - $hasher = m::mock(Hasher::class); - - $hasher->shouldReceive('check') - ->with('secret', 'hashedsecret') - ->andReturnTrue(); - - $hasher->shouldReceive('check') - ->with('wrong-secret', 'hashedsecret') - ->andReturnFalse(); - $clientModelRepository = m::mock(ClientRepository::class); $clientModelRepository->shouldReceive('findActive') ->with(1) ->andReturn(new BridgeClientRepositoryHashedTestClientStub); $this->clientModelRepository = $clientModelRepository; - $this->hasher = $hasher; + $this->repository = new BridgeClientRepository($clientModelRepository); - $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); } } -class BridgeClientRepositoryHashedTestClientStub +class BridgeClientRepositoryHashedTestClientStub extends BridgeClientRepositoryTestClientStub { - public $name = 'Client'; - - public $redirect = 'http://localhost'; - - public $secret = 'hashedsecret'; - - public $personal_access_client = false; - - public $password_client = false; - - public $grant_types; - - public function firstParty() - { - return $this->personal_access_client || $this->password_client; - } - - public function confidential() - { - return ! empty($this->secret); - } + public $secret = '$2y$10$ILY9x.zBwltszjoU21a21.naD6oeN5eMWd00l7P8OMrK5US3ZYeP2'; } diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index 9e4add185..b2435b9c2 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests; -use Illuminate\Contracts\Hashing\Hasher; use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\ClientRepository as BridgeClientRepository; use Laravel\Passport\ClientRepository; @@ -31,16 +30,13 @@ protected function setUp(): void { Passport::$useHashedClientSecrets = false; - $hasher = m::mock(Hasher::class); - $clientModelRepository = m::mock(ClientRepository::class); $clientModelRepository->shouldReceive('findActive') ->with(1) ->andReturn(new BridgeClientRepositoryTestClientStub); $this->clientModelRepository = $clientModelRepository; - $this->hasher = $hasher; - $this->repository = new BridgeClientRepository($clientModelRepository, $hasher); + $this->repository = new BridgeClientRepository($clientModelRepository); } protected function tearDown(): void From 4d711419008fb71d4f398cc38fa1edb10d1ec3da Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Mon, 23 Dec 2019 21:44:06 +0100 Subject: [PATCH 029/353] Format code --- tests/BridgeClientRepositoryHashedSecretsTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index b74de0b41..4f58aa618 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -20,7 +20,6 @@ protected function setUp(): void $this->clientModelRepository = $clientModelRepository; $this->repository = new BridgeClientRepository($clientModelRepository); - } } From 6ab8f2670df981694bd66393b73828ec2bc4c5aa Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Mon, 23 Dec 2019 21:44:42 +0100 Subject: [PATCH 030/353] Remove deprecated variable --- tests/BridgeClientRepositoryTest.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index b2435b9c2..1f0868de6 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -16,11 +16,6 @@ class BridgeClientRepositoryTest extends TestCase */ protected $clientModelRepository; - /** - * @var \Illuminate\Contracts\Hashing\Hasher - */ - protected $hasher; - /** * @var \Laravel\Passport\Bridge\ClientRepository */ From 2d808a58c83bf14a10728774c8d76cd410a5d4cb Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 26 Dec 2019 15:01:31 +0800 Subject: [PATCH 031/353] Allow access to HTTP response status code. Signed-off-by: Mior Muhammad Zaki --- src/Exceptions/OAuthServerException.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Exceptions/OAuthServerException.php b/src/Exceptions/OAuthServerException.php index 2e3e473ae..27614b4ef 100644 --- a/src/Exceptions/OAuthServerException.php +++ b/src/Exceptions/OAuthServerException.php @@ -39,4 +39,14 @@ public function render($request) { return $this->response; } + + /** + * Get HTTP response status code. + * + * @return int + */ + public function getStatusCode() + { + return $this->response->getStatusCode(); + } } From 68fa55e80004152a1af636ac5d38bc80515ab983 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 26 Dec 2019 21:28:39 +0800 Subject: [PATCH 032/353] Use avoid using deprecated PHPUnit annotation. The @expectedException, @expectedExceptionCode, @expectedExceptionMessage, and @expectedExceptionMessageRegExp annotations are deprecated. They will be removed in PHPUnit 9. Refactor your test to use expectException(), expectExceptionCode(), expectExceptionMessage(), or expectExceptionMessageRegExp() instead. Signed-off-by: Mior Muhammad Zaki --- tests/CheckClientCredentialsForAnyScopeTest.php | 15 ++++++--------- tests/CheckClientCredentialsTest.php | 15 ++++++--------- tests/CheckForAnyScopeTest.php | 15 ++++++--------- tests/CheckScopesTest.php | 15 ++++++--------- tests/DenyAuthorizationControllerTest.php | 7 +++---- tests/PassportTest.php | 5 ++--- 6 files changed, 29 insertions(+), 43 deletions(-) diff --git a/tests/CheckClientCredentialsForAnyScopeTest.php b/tests/CheckClientCredentialsForAnyScopeTest.php index 96d9d646e..db53b474b 100644 --- a/tests/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/CheckClientCredentialsForAnyScopeTest.php @@ -83,11 +83,10 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() $this->assertEquals('response', $response); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_when_oauth_throws_exception() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( @@ -104,11 +103,10 @@ public function test_exception_is_thrown_when_oauth_throws_exception() }); } - /** - * @expectedException \Laravel\Passport\Exceptions\MissingScopeException - */ public function test_exception_is_thrown_if_token_does_not_have_required_scope() { + $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); + $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); @@ -138,11 +136,10 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope() }, 'baz', 'notbar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_token_belongs_to_first_party_client() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); diff --git a/tests/CheckClientCredentialsTest.php b/tests/CheckClientCredentialsTest.php index 435ae9f7a..3932d6914 100644 --- a/tests/CheckClientCredentialsTest.php +++ b/tests/CheckClientCredentialsTest.php @@ -82,11 +82,10 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() $this->assertEquals('response', $response); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_when_oauth_throws_exception() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( @@ -103,11 +102,10 @@ public function test_exception_is_thrown_when_oauth_throws_exception() }); } - /** - * @expectedException \Laravel\Passport\Exceptions\MissingScopeException - */ public function test_exception_is_thrown_if_token_does_not_have_required_scopes() { + $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); + $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); @@ -137,11 +135,10 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scopes( }, 'foo', 'bar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_token_belongs_to_first_party_client() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $resourceServer = m::mock(ResourceServer::class); $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); diff --git a/tests/CheckForAnyScopeTest.php b/tests/CheckForAnyScopeTest.php index 55b380dab..a6b3c1425 100644 --- a/tests/CheckForAnyScopeTest.php +++ b/tests/CheckForAnyScopeTest.php @@ -29,11 +29,10 @@ public function test_request_is_passed_along_if_scopes_are_present_on_token() $this->assertEquals('response', $response); } - /** - * @expectedException \Laravel\Passport\Exceptions\MissingScopeException - */ public function test_exception_is_thrown_if_token_doesnt_have_scope() { + $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->andReturn($user = m::mock()); @@ -46,11 +45,10 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() }, 'foo', 'bar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_no_authenticated_user() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->once()->andReturn(null); @@ -60,11 +58,10 @@ public function test_exception_is_thrown_if_no_authenticated_user() }, 'foo', 'bar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_no_token() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->andReturn($user = m::mock()); diff --git a/tests/CheckScopesTest.php b/tests/CheckScopesTest.php index 0e56ac4a3..ddf406cc7 100644 --- a/tests/CheckScopesTest.php +++ b/tests/CheckScopesTest.php @@ -29,11 +29,10 @@ public function test_request_is_passed_along_if_scopes_are_present_on_token() $this->assertEquals('response', $response); } - /** - * @expectedException \Laravel\Passport\Exceptions\MissingScopeException - */ public function test_exception_is_thrown_if_token_doesnt_have_scope() { + $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->andReturn($user = m::mock()); @@ -45,11 +44,10 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() }, 'foo', 'bar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_no_authenticated_user() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->once()->andReturn(null); @@ -59,11 +57,10 @@ public function test_exception_is_thrown_if_no_authenticated_user() }, 'foo', 'bar'); } - /** - * @expectedException \Illuminate\Auth\AuthenticationException - */ public function test_exception_is_thrown_if_no_token() { + $this->expectException('Illuminate\Auth\AuthenticationException'); + $middleware = new CheckScopes; $request = m::mock(); $request->shouldReceive('user')->andReturn($user = m::mock()); diff --git a/tests/DenyAuthorizationControllerTest.php b/tests/DenyAuthorizationControllerTest.php index 5401483b3..38362c77f 100644 --- a/tests/DenyAuthorizationControllerTest.php +++ b/tests/DenyAuthorizationControllerTest.php @@ -132,12 +132,11 @@ public function test_authorization_can_be_denied_with_existing_query_string() $this->assertEquals('http://localhost?action=some_action&error=access_denied&state=state', $controller->deny($request)); } - /** - * @expectedException \Exception - * @expectedExceptionMessage Authorization request was not present in the session. - */ public function test_auth_request_should_exist() { + $this->expectException('Exception'); + $this->expectExceptionMessage('Authorization request was not present in the session.'); + $response = m::mock(ResponseFactory::class); $controller = new DenyAuthorizationController($response); diff --git a/tests/PassportTest.php b/tests/PassportTest.php index e5f3c92bb..72b5fdfe5 100644 --- a/tests/PassportTest.php +++ b/tests/PassportTest.php @@ -48,11 +48,10 @@ public function test_personal_access_client_instance_can_be_created() $this->assertInstanceOf(Passport::personalAccessClientModel(), $client); } - /** - * @expectedException \RuntimeException - */ public function test_missing_personal_access_client_is_reported() { + $this->expectException('RuntimeException'); + Passport::usePersonalAccessClientModel(PersonalAccessClientStub::class); $clientRepository = new ClientRepository; From ac26b71661283b40392d8a648bfcf6c6e5cbae3a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 26 Dec 2019 08:31:28 -0600 Subject: [PATCH 033/353] Update OAuthServerException.php --- src/Exceptions/OAuthServerException.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exceptions/OAuthServerException.php b/src/Exceptions/OAuthServerException.php index 27614b4ef..c7ae79aff 100644 --- a/src/Exceptions/OAuthServerException.php +++ b/src/Exceptions/OAuthServerException.php @@ -41,11 +41,11 @@ public function render($request) } /** - * Get HTTP response status code. + * Get the HTTP response status code. * * @return int */ - public function getStatusCode() + public function statusCode() { return $this->response->getStatusCode(); } From 469fa7780d1d9e3a4cd4fdc31928d54ea59d841c Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 26 Dec 2019 08:31:40 -0600 Subject: [PATCH 034/353] Update OAuthServerException.php --- src/Exceptions/OAuthServerException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/OAuthServerException.php b/src/Exceptions/OAuthServerException.php index c7ae79aff..63502ff93 100644 --- a/src/Exceptions/OAuthServerException.php +++ b/src/Exceptions/OAuthServerException.php @@ -45,7 +45,7 @@ public function render($request) * * @return int */ - public function statusCode() + public function getStatusCode() { return $this->response->getStatusCode(); } From 6742fd32041852335c2c71a18a77ac06a6ae3ab8 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 26 Dec 2019 08:31:51 -0600 Subject: [PATCH 035/353] Update OAuthServerException.php --- src/Exceptions/OAuthServerException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/OAuthServerException.php b/src/Exceptions/OAuthServerException.php index 63502ff93..c7ae79aff 100644 --- a/src/Exceptions/OAuthServerException.php +++ b/src/Exceptions/OAuthServerException.php @@ -45,7 +45,7 @@ public function render($request) * * @return int */ - public function getStatusCode() + public function statusCode() { return $this->response->getStatusCode(); } From 3c553e4c0a5da0cc90e144928f79f94c2aa518a0 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 26 Dec 2019 17:52:57 +0100 Subject: [PATCH 036/353] Use non-salted SHA-256 hashing to store client secrets --- src/Bridge/ClientRepository.php | 2 +- src/Client.php | 2 +- tests/BridgeClientRepositoryHashedSecretsTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 07b0bbfea..204e6e270 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -94,7 +94,7 @@ protected function handlesGrant($record, $grantType) protected function verifySecret($clientSecret, $storedHash) { if (Passport::$useHashedClientSecrets) { - return password_verify($clientSecret, $storedHash); + $clientSecret = hash('sha256', $clientSecret); } return hash_equals($storedHash, $clientSecret); diff --git a/src/Client.php b/src/Client.php index d50847725..024bb1e1c 100644 --- a/src/Client.php +++ b/src/Client.php @@ -107,7 +107,7 @@ public function setSecretAttribute($value) return; } - $this->attributes['secret'] = password_hash($value, CRYPT_SHA256); + $this->attributes['secret'] = hash('sha256', $value); } /** diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index 4f58aa618..f834c79da 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -25,5 +25,5 @@ protected function setUp(): void class BridgeClientRepositoryHashedTestClientStub extends BridgeClientRepositoryTestClientStub { - public $secret = '$2y$10$ILY9x.zBwltszjoU21a21.naD6oeN5eMWd00l7P8OMrK5US3ZYeP2'; + public $secret = '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b'; } From ccbcfeb5301e8f757395ba0e43980615acf4385e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 27 Dec 2019 08:13:48 -0600 Subject: [PATCH 037/353] formatting --- src/Bridge/ClientRepository.php | 10 +++++----- src/Client.php | 13 +++++++------ src/Passport.php | 14 +++++++------- tests/BridgeClientRepositoryHashedSecretsTest.php | 2 +- tests/BridgeClientRepositoryTest.php | 2 +- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 204e6e270..d2015d583 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -87,16 +87,16 @@ protected function handlesGrant($record, $grantType) } /** + * Verify the client secret is valid. + * * @param string $clientSecret * @param string $storedHash * @return bool */ protected function verifySecret($clientSecret, $storedHash) { - if (Passport::$useHashedClientSecrets) { - $clientSecret = hash('sha256', $clientSecret); - } - - return hash_equals($storedHash, $clientSecret); + return Passport::$hashesClientSecrets + ? hash_equals($storedHash, hash('sha256', $clientSecret)) + : hash_equals($storedHash, $clientSecret); } } diff --git a/src/Client.php b/src/Client.php index 024bb1e1c..a901de637 100644 --- a/src/Client.php +++ b/src/Client.php @@ -42,7 +42,7 @@ class Client extends Model ]; /** - * The temporary non-hashed client secret. + * The temporary plain-text client secret. * * @var string|null */ @@ -83,9 +83,7 @@ public function tokens() /** * The temporary non-hashed client secret. * - * If you're using hashed client secrets, this value will only be available - * once during the request the client was created. Afterwards, it cannot - * be retrieved or decrypted anymore. + * This is only available once during the request that created the client. * * @return string|null */ @@ -95,13 +93,16 @@ public function getPlainSecretAttribute() } /** - * @param string|null $value + * Set the value of the secret attribute. + * + * @param string|null $value + * @return void */ public function setSecretAttribute($value) { $this->plainSecret = $value; - if ($value === null || ! Passport::$useHashedClientSecrets) { + if (is_null($value) || ! Passport::$hashesClientSecrets) { $this->attributes['secret'] = $value; return; diff --git a/src/Passport.php b/src/Passport.php index e9b04fdb8..1794b612f 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -149,7 +149,7 @@ class Passport /** * @var bool */ - public static $useHashedClientSecrets = false; + public static $hashesClientSecrets = false; /** * Indicates the scope should inherit its parent scope. @@ -631,25 +631,25 @@ public static function refreshToken() } /** - * Configure Passport to not register its migrations. + * Configure Passport to hash client credential secrets. * * @return static */ - public static function ignoreMigrations() + public static function hashClientSecrets() { - static::$runsMigrations = false; + static::$hashesClientSecrets = true; return new static; } /** - * Configure Passport to hash client credential secrets. + * Configure Passport to not register its migrations. * * @return static */ - public static function useHashedClientSecrets() + public static function ignoreMigrations() { - static::$useHashedClientSecrets = true; + static::$runsMigrations = false; return new static; } diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index f834c79da..a61c77b65 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -11,7 +11,7 @@ class BridgeClientRepositoryHashedSecretsTest extends BridgeClientRepositoryTest { protected function setUp(): void { - Passport::useHashedClientSecrets(); + Passport::hashClientSecrets(); $clientModelRepository = m::mock(ClientRepository::class); $clientModelRepository->shouldReceive('findActive') diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index 1f0868de6..3c9ba6391 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -23,7 +23,7 @@ class BridgeClientRepositoryTest extends TestCase protected function setUp(): void { - Passport::$useHashedClientSecrets = false; + Passport::$hashesClientSecrets = false; $clientModelRepository = m::mock(ClientRepository::class); $clientModelRepository->shouldReceive('findActive') From 1c40ae07503aeb23173d48f3a6e5757cafcfd71b Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 27 Dec 2019 08:24:33 -0600 Subject: [PATCH 038/353] use bcrypt --- src/Bridge/ClientRepository.php | 2 +- src/Client.php | 2 +- tests/BridgeClientRepositoryHashedSecretsTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index d2015d583..68e891363 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -96,7 +96,7 @@ protected function handlesGrant($record, $grantType) protected function verifySecret($clientSecret, $storedHash) { return Passport::$hashesClientSecrets - ? hash_equals($storedHash, hash('sha256', $clientSecret)) + ? password_verify($clientSecret, $storedHash) : hash_equals($storedHash, $clientSecret); } } diff --git a/src/Client.php b/src/Client.php index a901de637..d860d7a32 100644 --- a/src/Client.php +++ b/src/Client.php @@ -108,7 +108,7 @@ public function setSecretAttribute($value) return; } - $this->attributes['secret'] = hash('sha256', $value); + $this->attributes['secret'] = password_hash($value, PASSWORD_BCRYPT); } /** diff --git a/tests/BridgeClientRepositoryHashedSecretsTest.php b/tests/BridgeClientRepositoryHashedSecretsTest.php index a61c77b65..39aec9634 100644 --- a/tests/BridgeClientRepositoryHashedSecretsTest.php +++ b/tests/BridgeClientRepositoryHashedSecretsTest.php @@ -25,5 +25,5 @@ protected function setUp(): void class BridgeClientRepositoryHashedTestClientStub extends BridgeClientRepositoryTestClientStub { - public $secret = '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b'; + public $secret = '$2y$10$WgqU4wQpfsARCIQk.nPSOOiNkrMpPVxQiLCFUt8comvQwh1z6WFMG'; } From e45ac135c94f72ff77dbc61de97762b35cb76048 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 30 Dec 2019 23:20:25 +0100 Subject: [PATCH 039/353] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f60aebeca..2373c63f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ ## [Unreleased](https://github.com/laravel/passport/compare/v8.0.2...8.x) +## [v8.1.0 (2019-12-30)](https://github.com/laravel/passport/compare/v8.0.2...v8.1.0) + +### Added +- Allow access to HTTP response status code on OAuthServerException ([#1148](https://github.com/laravel/passport/pull/1148)) +- Modify UserRepository to check for 'findAndValidateForPassport' method ([#1144](https://github.com/laravel/passport/pull/1144)) + + ## [v8.0.2 (2019-11-26)](https://github.com/laravel/passport/compare/v8.0.1...v8.0.2) ### Changed From c5692a2f0b4c2cd3c8f782efa7d8d5a47df3f5be Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 30 Dec 2019 23:25:32 +0100 Subject: [PATCH 040/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2373c63f2..3cd35c1a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.0.2...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.1.0...8.x) ## [v8.1.0 (2019-12-30)](https://github.com/laravel/passport/compare/v8.0.2...v8.1.0) From e5a475b4514ba930a4bb7f1f1eb7f667db33fd2d Mon Sep 17 00:00:00 2001 From: Romario Chinloy Date: Wed, 1 Jan 2020 15:04:46 -0500 Subject: [PATCH 041/353] Update ClientCommand to support public clients --- src/Console/ClientCommand.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 4a20e30bc..5987ae8f1 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -19,7 +19,8 @@ class ClientCommand extends Command {--client : Create a client credentials grant client} {--name= : The name of the client} {--redirect_uri= : The URI to redirect to after authorization } - {--user_id= : The user ID the client should be assigned to }'; + {--user_id= : The user ID the client should be assigned to } + {--public : Set client type to public (Only for auth code grant type) }'; /** * The console command description. @@ -135,7 +136,8 @@ protected function createAuthCodeClient(ClientRepository $clients) ); $client = $clients->create( - $userId, $name, $redirect + $userId, $name, $redirect, false, false, + !$this->option('public') ); $this->info('New client created successfully.'); From 8a1bba6f36e14a76ad13233004141cb0705773a1 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 2 Jan 2020 12:37:46 +0100 Subject: [PATCH 042/353] Style fixes --- src/Console/ClientCommand.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 5987ae8f1..8efc0af4d 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -136,8 +136,7 @@ protected function createAuthCodeClient(ClientRepository $clients) ); $client = $clients->create( - $userId, $name, $redirect, false, false, - !$this->option('public') + $userId, $name, $redirect, false, false, ! $this->option('public') ); $this->info('New client created successfully.'); From e42c9809e4e9a9a13d2877c25d91b72d07fa8592 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 2 Jan 2020 08:52:18 -0600 Subject: [PATCH 043/353] Update ClientCommand.php --- src/Console/ClientCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 8efc0af4d..5ae9bd035 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -20,7 +20,7 @@ class ClientCommand extends Command {--name= : The name of the client} {--redirect_uri= : The URI to redirect to after authorization } {--user_id= : The user ID the client should be assigned to } - {--public : Set client type to public (Only for auth code grant type) }'; + {--public : Create a public client (Auth code grant type only) }'; /** * The console command description. From 699b997d36390972cb9a66debac2514932d8c5bf Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sat, 4 Jan 2020 23:04:19 +0100 Subject: [PATCH 044/353] Add Orchestra Testbench package --- composer.json | 1 + tests/Feature/ActingAsClientTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 tests/Feature/ActingAsClientTest.php diff --git a/composer.json b/composer.json index c5fc88c63..c5822ee45 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.4|^5.0", "phpunit/phpunit": "^8.0" }, "autoload": { diff --git a/tests/Feature/ActingAsClientTest.php b/tests/Feature/ActingAsClientTest.php new file mode 100644 index 000000000..37fa8f811 --- /dev/null +++ b/tests/Feature/ActingAsClientTest.php @@ -0,0 +1,10 @@ + Date: Sat, 4 Jan 2020 23:50:38 +0100 Subject: [PATCH 045/353] Add ActingAsClientTest and resolve storage_path function conflict --- tests/Feature/ActingAsClientTest.php | 43 ++++++++++++++++++++++++++-- tests/KeysCommandTest.php | 8 ++++++ tests/bootstrap.php | 5 ---- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tests/Feature/ActingAsClientTest.php b/tests/Feature/ActingAsClientTest.php index 37fa8f811..edba5440d 100644 --- a/tests/Feature/ActingAsClientTest.php +++ b/tests/Feature/ActingAsClientTest.php @@ -1,10 +1,49 @@ withoutExceptionHandling(); + + /** @var Registrar $router */ + $router = $this->app->make(Registrar::class); + + $router->get('/foo', function () { + return 'bar'; + })->middleware(CheckClientCredentials::class); + + Passport::actingAsClient(new Client()); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } + + public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredentialsForAnyScope() + { + $this->withoutExceptionHandling(); + + /** @var Registrar $router */ + $router = $this->app->make(Registrar::class); + + $router->get('/foo', function () { + return 'bar'; + })->middleware(CheckClientCredentialsForAnyScope::class . ':testFoo'); + + Passport::actingAsClient(new Client(), ['testFoo']); + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } } diff --git a/tests/KeysCommandTest.php b/tests/KeysCommandTest.php index 8199f6b4a..a738a92e4 100644 --- a/tests/KeysCommandTest.php +++ b/tests/KeysCommandTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests; +use Illuminate\Container\Container; use Laravel\Passport\Console\KeysCommand; use Laravel\Passport\Passport; use Mockery as m; @@ -13,6 +14,11 @@ function custom_path($file = null) return __DIR__.DIRECTORY_SEPARATOR.'files'.DIRECTORY_SEPARATOR.$file; } +function storage_path($file = null) +{ + return __DIR__.DIRECTORY_SEPARATOR.$file; +} + class KeysCommandTest extends TestCase { protected function tearDown(): void @@ -33,6 +39,8 @@ public function testPrivateAndPublicKeysAreGenerated() ->with('Encryption keys generated successfully.') ->getMock(); + Container::getInstance()->instance('path.storage', storage_path()); + $rsa = new RSA(); $command->handle($rsa); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 9914b328d..991ea4397 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,8 +1,3 @@ Date: Sun, 5 Jan 2020 01:17:00 +0100 Subject: [PATCH 046/353] Add ServerRequestInterface typehint --- src/Passport.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Passport.php b/src/Passport.php index 103ff3957..992f4333b 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Route; use League\OAuth2\Server\ResourceServer; use Mockery; +use Psr\Http\Message\ServerRequestInterface; class Passport { @@ -429,7 +430,7 @@ public static function actingAsClient($client, $scopes = []) $mock = Mockery::mock(ResourceServer::class); $mock->shouldReceive('validateAuthenticatedRequest') - ->andReturnUsing(function ($request) use ($token) { + ->andReturnUsing(function (ServerRequestInterface $request) use ($token) { return $request->withAttribute('oauth_client_id', $token->client->id) ->withAttribute('oauth_access_token_id', $token->id) ->withAttribute('oauth_scopes', $token->scopes); From e4046aa107020241bef0ab6608e9a0c6b6f3dbd0 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sun, 5 Jan 2020 01:17:34 +0100 Subject: [PATCH 047/353] Create PassportTestCase --- tests/Feature/PassportTestCase.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/Feature/PassportTestCase.php diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php new file mode 100644 index 000000000..cee7f1685 --- /dev/null +++ b/tests/Feature/PassportTestCase.php @@ -0,0 +1,27 @@ +artisan('passport:keys'); + } + + protected function getEnvironmentSetUp($app) + { + $app->make(Repository::class)->set('auth.guards.api', ['driver' => 'passport', 'provider' => 'users']); + } + + protected function getPackageProviders($app) + { + return [PassportServiceProvider::class]; + } +} From 5212c9ccabbeaefb33f2ff2176b03dfe2ec0e9f4 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sun, 5 Jan 2020 01:27:22 +0100 Subject: [PATCH 048/353] Add ActingAsTest --- tests/Feature/ActingAsTest.php | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/Feature/ActingAsTest.php diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php new file mode 100644 index 000000000..e50e5d941 --- /dev/null +++ b/tests/Feature/ActingAsTest.php @@ -0,0 +1,74 @@ +withoutExceptionHandling(); + + /** @var Registrar $router */ + $router = $this->app->make(Registrar::class); + + $router->get('/foo', function () { + return 'bar'; + })->middleware('auth:api'); + + Passport::actingAs(new PassportUser()); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } + + public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddleware() + { + $this->withoutExceptionHandling(); + + /** @var Registrar $router */ + $router = $this->app->make(Registrar::class); + + $router->get('/foo', function () { + return 'bar'; + })->middleware(CheckScopes::class . ':admin,footest'); + + Passport::actingAs(new PassportUser(), ['admin', 'footest']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } + + public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware() + { + $this->withoutExceptionHandling(); + + /** @var Registrar $router */ + $router = $this->app->make(Registrar::class); + + $router->get('/foo', function () { + return 'bar'; + })->middleware(CheckForAnyScope::class . ':admin,footest'); + + Passport::actingAs(new PassportUser(), ['footest']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } +} + +class PassportUser extends User +{ + use HasApiTokens; + + protected $table = 'users'; +} From feaa05104249f00a387e5d633554f3cf1b66b1fc Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sun, 5 Jan 2020 01:52:59 +0100 Subject: [PATCH 049/353] Fix lint issues --- tests/Feature/ActingAsClientTest.php | 2 +- tests/Feature/ActingAsTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Feature/ActingAsClientTest.php b/tests/Feature/ActingAsClientTest.php index edba5440d..8fc99b777 100644 --- a/tests/Feature/ActingAsClientTest.php +++ b/tests/Feature/ActingAsClientTest.php @@ -38,7 +38,7 @@ public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredential $router->get('/foo', function () { return 'bar'; - })->middleware(CheckClientCredentialsForAnyScope::class . ':testFoo'); + })->middleware(CheckClientCredentialsForAnyScope::class.':testFoo'); Passport::actingAsClient(new Client(), ['testFoo']); diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index e50e5d941..aa1b3ecea 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -38,7 +38,7 @@ public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddleware() $router->get('/foo', function () { return 'bar'; - })->middleware(CheckScopes::class . ':admin,footest'); + })->middleware(CheckScopes::class.':admin,footest'); Passport::actingAs(new PassportUser(), ['admin', 'footest']); @@ -56,7 +56,7 @@ public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware( $router->get('/foo', function () { return 'bar'; - })->middleware(CheckForAnyScope::class . ':admin,footest'); + })->middleware(CheckForAnyScope::class.':admin,footest'); Passport::actingAs(new PassportUser(), ['footest']); From 3d6deaaa5f502bed14ec8b2c85e64676d8842698 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sat, 4 Jan 2020 22:42:29 +0100 Subject: [PATCH 050/353] Use Hasher interface instead of HashManager --- src/Bridge/UserRepository.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Bridge/UserRepository.php b/src/Bridge/UserRepository.php index 8b0f6237d..332afbbf6 100644 --- a/src/Bridge/UserRepository.php +++ b/src/Bridge/UserRepository.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Hashing\HashManager; +use Illuminate\Contracts\Hashing\Hasher; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\UserRepositoryInterface; use RuntimeException; @@ -12,19 +12,19 @@ class UserRepository implements UserRepositoryInterface /** * The hasher implementation. * - * @var \Illuminate\Hashing\HashManager + * @var \Illuminate\Contracts\Hashing\Hasher */ protected $hasher; /** * Create a new repository instance. * - * @param \Illuminate\Hashing\HashManager $hasher + * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return void */ - public function __construct(HashManager $hasher) + public function __construct(Hasher $hasher) { - $this->hasher = $hasher->driver(); + $this->hasher = $hasher; } /** From 7ec6e58fa4f08a19dc04ea9abf206d87b9462f43 Mon Sep 17 00:00:00 2001 From: Michael Latham Date: Mon, 6 Jan 2020 12:28:33 +0000 Subject: [PATCH 051/353] Replace deprecated package and namespaces --- composer.json | 4 ++-- src/Guards/TokenGuard.php | 10 +++++----- src/Http/Controllers/AccessTokenController.php | 2 +- .../Controllers/ApproveAuthorizationController.php | 2 +- src/Http/Controllers/AuthorizationController.php | 2 +- src/Http/Controllers/HandlesOAuthErrors.php | 2 +- src/Http/Middleware/CheckCredentials.php | 8 ++++---- src/PersonalAccessTokenFactory.php | 8 ++++---- tests/AccessTokenControllerTest.php | 2 +- tests/ApproveAuthorizationControllerTest.php | 2 +- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index c5fc88c63..fb5d7bd44 100644 --- a/composer.json +++ b/composer.json @@ -27,10 +27,10 @@ "illuminate/encryption": "^6.0|^7.0", "illuminate/http": "^6.0|^7.0", "illuminate/support": "^6.0|^7.0", + "laminas/laminas-diactoros": "^2.2", "league/oauth2-server": "^8.0", "phpseclib/phpseclib": "^2.0", - "symfony/psr-http-message-bridge": "^1.0", - "zendframework/zend-diactoros": "^2.0" + "symfony/psr-http-message-bridge": "^1.0" }, "require-dev": { "mockery/mockery": "^1.0", diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 5a9f2e390..b391c706b 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -17,10 +17,10 @@ use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -use Zend\Diactoros\ResponseFactory; -use Zend\Diactoros\ServerRequestFactory; -use Zend\Diactoros\StreamFactory; -use Zend\Diactoros\UploadedFileFactory; +use Laminas\Diactoros\ResponseFactory; +use Laminas\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\StreamFactory; +use Laminas\Diactoros\UploadedFileFactory; class TokenGuard { @@ -172,7 +172,7 @@ protected function getPsrRequestViaBearerToken($request) { // First, we will convert the Symfony request to a PSR-7 implementation which will // be compatible with the base OAuth2 library. The Symfony bridge can perform a - // conversion for us to a Zend Diactoros implementation of the PSR-7 request. + // conversion for us to a Laminas Diactoros implementation of the PSR-7 request. $psr = (new PsrHttpFactory( new ServerRequestFactory, new StreamFactory, diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index fd7159e87..e392b234d 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -6,7 +6,7 @@ use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; use Psr\Http\Message\ServerRequestInterface; -use Zend\Diactoros\Response as Psr7Response; +use Laminas\Diactoros\Response as Psr7Response; class AccessTokenController { diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index 63de8dad4..b87851f7e 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -4,7 +4,7 @@ use Illuminate\Http\Request; use League\OAuth2\Server\AuthorizationServer; -use Zend\Diactoros\Response as Psr7Response; +use Laminas\Diactoros\Response as Psr7Response; class ApproveAuthorizationController { diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index bfedb3e8c..8bd602342 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -10,7 +10,7 @@ use Laravel\Passport\TokenRepository; use League\OAuth2\Server\AuthorizationServer; use Psr\Http\Message\ServerRequestInterface; -use Zend\Diactoros\Response as Psr7Response; +use Laminas\Diactoros\Response as Psr7Response; class AuthorizationController { diff --git a/src/Http/Controllers/HandlesOAuthErrors.php b/src/Http/Controllers/HandlesOAuthErrors.php index 0f71225fc..67aecb2d2 100644 --- a/src/Http/Controllers/HandlesOAuthErrors.php +++ b/src/Http/Controllers/HandlesOAuthErrors.php @@ -4,7 +4,7 @@ use Laravel\Passport\Exceptions\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; -use Zend\Diactoros\Response as Psr7Response; +use Laminas\Diactoros\Response as Psr7Response; trait HandlesOAuthErrors { diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index e35063ffc..f4412d45f 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -8,10 +8,10 @@ use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -use Zend\Diactoros\ResponseFactory; -use Zend\Diactoros\ServerRequestFactory; -use Zend\Diactoros\StreamFactory; -use Zend\Diactoros\UploadedFileFactory; +use Laminas\Diactoros\ResponseFactory; +use Laminas\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\StreamFactory; +use Laminas\Diactoros\UploadedFileFactory; abstract class CheckCredentials { diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 46a86f991..a3f2ca27a 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -4,8 +4,8 @@ use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; -use Zend\Diactoros\Response; -use Zend\Diactoros\ServerRequest; +use Laminas\Diactoros\Response; +use Laminas\Diactoros\ServerRequest; class PersonalAccessTokenFactory { @@ -89,7 +89,7 @@ public function make($userId, $name, array $scopes = []) * @param \Laravel\Passport\Client $client * @param mixed $userId * @param array $scopes - * @return \Zend\Diactoros\ServerRequest + * @return \Laminas\Diactoros\ServerRequest */ protected function createRequest($client, $userId, array $scopes) { @@ -105,7 +105,7 @@ protected function createRequest($client, $userId, array $scopes) /** * Dispatch the given request to the authorization server. * - * @param \Zend\Diactoros\ServerRequest $request + * @param \Laminas\Diactoros\ServerRequest $request * @return array */ protected function dispatchRequestToAuthorizationServer(ServerRequest $request) diff --git a/tests/AccessTokenControllerTest.php b/tests/AccessTokenControllerTest.php index 9d10cdfb6..f98a15e07 100644 --- a/tests/AccessTokenControllerTest.php +++ b/tests/AccessTokenControllerTest.php @@ -12,7 +12,7 @@ use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Zend\Diactoros\Response; +use Laminas\Diactoros\Response; class AccessTokenControllerTest extends TestCase { diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index 843143a44..e702f3f80 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -9,7 +9,7 @@ use Mockery as m; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; -use Zend\Diactoros\Response; +use Laminas\Diactoros\Response; class ApproveAuthorizationControllerTest extends TestCase { From 949de2190c189b5deda054863b5ad55944da4f21 Mon Sep 17 00:00:00 2001 From: Michael Latham Date: Mon, 6 Jan 2020 12:37:39 +0000 Subject: [PATCH 052/353] styleCI fixes --- src/Guards/TokenGuard.php | 8 ++++---- src/Http/Controllers/AccessTokenController.php | 2 +- src/Http/Controllers/AuthorizationController.php | 2 +- src/Http/Controllers/HandlesOAuthErrors.php | 2 +- src/Http/Middleware/CheckCredentials.php | 8 ++++---- src/PersonalAccessTokenFactory.php | 4 ++-- tests/AccessTokenControllerTest.php | 2 +- tests/ApproveAuthorizationControllerTest.php | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index b391c706b..503cc6636 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -10,6 +10,10 @@ use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Http\Request; +use Laminas\Diactoros\ResponseFactory; +use Laminas\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\StreamFactory; +use Laminas\Diactoros\UploadedFileFactory; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; @@ -17,10 +21,6 @@ use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -use Laminas\Diactoros\ResponseFactory; -use Laminas\Diactoros\ServerRequestFactory; -use Laminas\Diactoros\StreamFactory; -use Laminas\Diactoros\UploadedFileFactory; class TokenGuard { diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index e392b234d..730742831 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -4,9 +4,9 @@ use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Parser as JwtParser; -use League\OAuth2\Server\AuthorizationServer; use Psr\Http\Message\ServerRequestInterface; use Laminas\Diactoros\Response as Psr7Response; +use League\OAuth2\Server\AuthorizationServer; class AccessTokenController { diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 8bd602342..fe1c03258 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -4,13 +4,13 @@ use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; +use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\Bridge\User; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\AuthorizationServer; use Psr\Http\Message\ServerRequestInterface; -use Laminas\Diactoros\Response as Psr7Response; class AuthorizationController { diff --git a/src/Http/Controllers/HandlesOAuthErrors.php b/src/Http/Controllers/HandlesOAuthErrors.php index 67aecb2d2..3ec32e711 100644 --- a/src/Http/Controllers/HandlesOAuthErrors.php +++ b/src/Http/Controllers/HandlesOAuthErrors.php @@ -2,9 +2,9 @@ namespace Laravel\Passport\Http\Controllers; +use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\Exceptions\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; -use Laminas\Diactoros\Response as Psr7Response; trait HandlesOAuthErrors { diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index f4412d45f..8c2323c0d 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -4,14 +4,14 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laravel\Passport\TokenRepository; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\ResourceServer; -use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; use Laminas\Diactoros\ResponseFactory; use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\StreamFactory; use Laminas\Diactoros\UploadedFileFactory; +use Laravel\Passport\TokenRepository; +use League\OAuth2\Server\Exception\OAuthServerException; +use League\OAuth2\Server\ResourceServer; +use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; abstract class CheckCredentials { diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index a3f2ca27a..2ab665c6b 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -2,10 +2,10 @@ namespace Laravel\Passport; -use Lcobucci\JWT\Parser as JwtParser; -use League\OAuth2\Server\AuthorizationServer; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; +use Lcobucci\JWT\Parser as JwtParser; +use League\OAuth2\Server\AuthorizationServer; class PersonalAccessTokenFactory { diff --git a/tests/AccessTokenControllerTest.php b/tests/AccessTokenControllerTest.php index f98a15e07..967f003f6 100644 --- a/tests/AccessTokenControllerTest.php +++ b/tests/AccessTokenControllerTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests; +use Laminas\Diactoros\Response; use Laravel\Passport\Exceptions\OAuthServerException; use Laravel\Passport\Http\Controllers\AccessTokenController; use Laravel\Passport\TokenRepository; @@ -12,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Laminas\Diactoros\Response; class AccessTokenControllerTest extends TestCase { diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index e702f3f80..97f42b846 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -3,13 +3,13 @@ namespace Laravel\Passport\Tests; use Illuminate\Http\Request; +use Laminas\Diactoros\Response; use Laravel\Passport\Http\Controllers\ApproveAuthorizationController; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use Mockery as m; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; -use Laminas\Diactoros\Response; class ApproveAuthorizationControllerTest extends TestCase { From 5eacbf630269cd92d7c37bd60ea9aefb04df7872 Mon Sep 17 00:00:00 2001 From: Michael Latham Date: Mon, 6 Jan 2020 12:39:02 +0000 Subject: [PATCH 053/353] StyleCI fixes --- src/Http/Controllers/AccessTokenController.php | 4 ++-- src/Http/Controllers/ApproveAuthorizationController.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index 730742831..c6bb70af9 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -2,11 +2,11 @@ namespace Laravel\Passport\Http\Controllers; +use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Parser as JwtParser; -use Psr\Http\Message\ServerRequestInterface; -use Laminas\Diactoros\Response as Psr7Response; use League\OAuth2\Server\AuthorizationServer; +use Psr\Http\Message\ServerRequestInterface; class AccessTokenController { diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index b87851f7e..2ea90a7ee 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -3,8 +3,8 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Http\Request; -use League\OAuth2\Server\AuthorizationServer; use Laminas\Diactoros\Response as Psr7Response; +use League\OAuth2\Server\AuthorizationServer; class ApproveAuthorizationController { From 593fad7e82442bd80b05ca148710842d694b323a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 6 Jan 2020 08:21:31 -0600 Subject: [PATCH 054/353] Update TokenGuard.php --- src/Guards/TokenGuard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 503cc6636..23244366a 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -172,7 +172,7 @@ protected function getPsrRequestViaBearerToken($request) { // First, we will convert the Symfony request to a PSR-7 implementation which will // be compatible with the base OAuth2 library. The Symfony bridge can perform a - // conversion for us to a Laminas Diactoros implementation of the PSR-7 request. + // conversion for us to a new Diactoros implementation of this PSR-7 request. $psr = (new PsrHttpFactory( new ServerRequestFactory, new StreamFactory, From d930614b30129607f1ad3d7fc8eacd40a59220c4 Mon Sep 17 00:00:00 2001 From: MFlor Date: Mon, 6 Jan 2020 19:52:42 +0100 Subject: [PATCH 055/353] Feature: Adding Purge command In order to more easily purge expired or revoked access tokens, auth codes an refresh tokens, I've created a purge command. This command can then be scheduled to run on any given interval or run manually when needed. --- src/Console/PurgeCommand.php | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/Console/PurgeCommand.php diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php new file mode 100644 index 000000000..f3e40a1b2 --- /dev/null +++ b/src/Console/PurgeCommand.php @@ -0,0 +1,37 @@ +orWhereDate('expires_at', '<', $now)->delete(); + AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + } +} From 493127463e3e7614d7c7b766cf1f7dd682d41f76 Mon Sep 17 00:00:00 2001 From: MFlor Date: Mon, 6 Jan 2020 20:09:09 +0100 Subject: [PATCH 056/353] Registering purge command --- src/PassportServiceProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 038202666..44fe0f208 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -55,6 +55,7 @@ public function boot() Console\InstallCommand::class, Console\ClientCommand::class, Console\KeysCommand::class, + Console\PurgeCommand::class, ]); } } From a384f1fd4d039fb808c305800cdad1222df1dcca Mon Sep 17 00:00:00 2001 From: MFlor Date: Mon, 6 Jan 2020 21:02:25 +0100 Subject: [PATCH 057/353] Adding options --- src/Console/PurgeCommand.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index f3e40a1b2..890c311c7 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -15,23 +15,39 @@ class PurgeCommand extends Command * * @var string */ - protected $signature = 'passport:purge'; + protected $signature = 'passport:purge + {--revoked : Only purge revoked tokens and auth codes} + {--expired : Only purge expired tokens and auth codes}'; /** * The console command description. * * @var string */ - protected $description = 'Purges revoked and expired tokens from oauth_access_tokens, oauth_auth_codes and oauth_refresh_tokens'; + protected $description = 'Purges revoked and/or expired tokens and auth codes'; /** * Execute the console command. */ public function handle() { + $options = $this->options(); $now = Carbon::now(); - Token::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + if ( + ($options['revoked'] && $options['expired']) || + (!$options['revoked'] && !$options['expired']) + ) { + Token::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); + } else if ($options['revoked']) { + Token::where('revoked', 1)->delete(); + AuthCode::where('revoked', 1)->delete(); + RefreshToken::where('revoked', 1)->delete(); + } else if ($options['expired']) { + Token::whereDate('expires_at', '<', $now)->delete(); + AuthCode::whereDate('expires_at', '<', $now)->delete(); + RefreshToken::whereDate('expires_at', '<', $now)->delete(); + } } } From 30ffc91e275fb5caa6a8a3f2b12531c12395cd4e Mon Sep 17 00:00:00 2001 From: MFlor Date: Mon, 6 Jan 2020 21:13:53 +0100 Subject: [PATCH 058/353] Fixes from StyleCI --- src/Console/PurgeCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 890c311c7..a43dea3d6 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -35,16 +35,16 @@ public function handle() $now = Carbon::now(); if ( ($options['revoked'] && $options['expired']) || - (!$options['revoked'] && !$options['expired']) + (! $options['revoked'] && ! $options['expired']) ) { Token::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - } else if ($options['revoked']) { + } elseif ($options['revoked']) { Token::where('revoked', 1)->delete(); AuthCode::where('revoked', 1)->delete(); RefreshToken::where('revoked', 1)->delete(); - } else if ($options['expired']) { + } elseif ($options['expired']) { Token::whereDate('expires_at', '<', $now)->delete(); AuthCode::whereDate('expires_at', '<', $now)->delete(); RefreshToken::whereDate('expires_at', '<', $now)->delete(); From 6c1ea42e66100b15ecad89b0e1c5ccaa12b4331b Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 6 Jan 2020 15:32:54 -0600 Subject: [PATCH 059/353] formatting and commenting --- src/Console/PurgeCommand.php | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index a43dea3d6..f70064aa2 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -16,38 +16,42 @@ class PurgeCommand extends Command * @var string */ protected $signature = 'passport:purge - {--revoked : Only purge revoked tokens and auth codes} - {--expired : Only purge expired tokens and auth codes}'; + {--revoked : Only purge revoked tokens and authentication codes} + {--expired : Only purge expired tokens and authentication codes}'; /** * The console command description. * * @var string */ - protected $description = 'Purges revoked and/or expired tokens and auth codes'; + protected $description = 'Purge revoked and / or expired tokens and authentication codes'; /** * Execute the console command. */ public function handle() { - $options = $this->options(); - $now = Carbon::now(); - if ( - ($options['revoked'] && $options['expired']) || - (! $options['revoked'] && ! $options['expired']) - ) { - Token::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $now)->delete(); - } elseif ($options['revoked']) { + $expired = Carbon::now()->subDays(7); + + if (($this->option('revoked') && $this->option('expired')) || + (! $this->option('revoked') && ! $this->option('expired'))) { + Token::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + + $this->info('Purged revoked items and items expired for more than seven days.'); + } elseif ($this->option('revoked')) { Token::where('revoked', 1)->delete(); AuthCode::where('revoked', 1)->delete(); RefreshToken::where('revoked', 1)->delete(); - } elseif ($options['expired']) { - Token::whereDate('expires_at', '<', $now)->delete(); - AuthCode::whereDate('expires_at', '<', $now)->delete(); - RefreshToken::whereDate('expires_at', '<', $now)->delete(); + + $this->info('Purged revoked items.'); + } elseif ($this->option('expired')) { + Token::whereDate('expires_at', '<', $expired)->delete(); + AuthCode::whereDate('expires_at', '<', $expired)->delete(); + RefreshToken::whereDate('expires_at', '<', $expired)->delete(); + + $this->info('Purged items expired for more than seven days.'); } } } From 4c163b7821d29b6166fc2e93ad7649428b51c6db Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 7 Jan 2020 20:25:00 +0100 Subject: [PATCH 060/353] Update CHANGELOG.md --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cd35c1a4..5bbfc6026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.1.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.2.0...8.x) + + +## [v8.2.0 (2020-01-07)](https://github.com/laravel/passport/compare/v8.1.0...v8.2.0) + +### Added +- Update ClientCommand to support public clients ([#1151](https://github.com/laravel/passport/pull/1151)) +- Purge Command for revoked and/or expired tokens and auth codes ([#1159](https://github.com/laravel/passport/pull/1159), [6c1ea42](https://github.com/laravel/passport/commit/6c1ea42e66100b15ecad89b0e1c5ccaa12b4331b)) + +### Changed +- Replace deprecated package and namespaces ([#1158](https://github.com/laravel/passport/pull/1158)) ## [v8.1.0 (2019-12-30)](https://github.com/laravel/passport/compare/v8.0.2...v8.1.0) From 32d5d60d18532dd21335cbb829d051a92c67bb0a Mon Sep 17 00:00:00 2001 From: Kieron Wiltshire Date: Tue, 21 Jan 2020 15:41:16 +0000 Subject: [PATCH 061/353] Update 2016_06_01_000001_create_oauth_auth_codes_table.php --- .../2016_06_01_000001_create_oauth_auth_codes_table.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 77c8e6b07..8683148ea 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -15,8 +15,9 @@ public function up() { Schema::create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->bigInteger('user_id'); - $table->unsignedInteger('client_id'); + $table->bigInteger('user_id')->unsigned()->index(); + $table->bigInteger('client_id')->unsigned(); + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); $table->text('scopes')->nullable(); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); From 63db1d6260a81d971922c7a13cebd2699f002cff Mon Sep 17 00:00:00 2001 From: Kieron Wiltshire Date: Tue, 21 Jan 2020 15:41:41 +0000 Subject: [PATCH 062/353] Update 2016_06_01_000002_create_oauth_access_tokens_table.php --- .../2016_06_01_000002_create_oauth_access_tokens_table.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 04e2835b3..58ee1b0a0 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -15,8 +15,9 @@ public function up() { Schema::create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->bigInteger('user_id')->index()->nullable(); - $table->unsignedInteger('client_id'); + $table->bigInteger('user_id')->unsigned()->nullable()->index(); + $table->bigInteger('client_id')->unsigned(); + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); $table->string('name')->nullable(); $table->text('scopes')->nullable(); $table->boolean('revoked'); From 0eabb22ed4f7d8b1586ba039d0f437aded88375e Mon Sep 17 00:00:00 2001 From: Kieron Wiltshire Date: Tue, 21 Jan 2020 15:42:07 +0000 Subject: [PATCH 063/353] Update 2016_06_01_000003_create_oauth_refresh_tokens_table.php --- .../2016_06_01_000003_create_oauth_refresh_tokens_table.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 60c523489..74644fe40 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -15,7 +15,8 @@ public function up() { Schema::create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->string('access_token_id', 100)->index(); + $table->string('access_token_id', 100); + $table->foreign('access_token_id')->references('id')->on('oauth_access_tokens')->onDelete('cascade'); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); }); From 09003bfe79aa3feb6618353e36851c86cb547102 Mon Sep 17 00:00:00 2001 From: Kieron Wiltshire Date: Tue, 21 Jan 2020 15:42:33 +0000 Subject: [PATCH 064/353] Update 2016_06_01_000004_create_oauth_clients_table.php --- .../2016_06_01_000004_create_oauth_clients_table.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 2141e9973..942078af6 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -14,10 +14,10 @@ class CreateOauthClientsTable extends Migration public function up() { Schema::create('oauth_clients', function (Blueprint $table) { - $table->increments('id'); - $table->bigInteger('user_id')->index()->nullable(); + $table->bigIncrements('id'); + $table->bigInteger('user_id')->unsigned()->nullable()->index(); $table->string('name'); - $table->string('secret', 100)->nullable(); + $table->string('secret', 100); $table->text('redirect'); $table->boolean('personal_access_client'); $table->boolean('password_client'); From 46893d69e5811afbbb4618b714cb5a81dd17473f Mon Sep 17 00:00:00 2001 From: Kieron Wiltshire Date: Tue, 21 Jan 2020 15:43:06 +0000 Subject: [PATCH 065/353] Update 2016_06_01_000005_create_oauth_personal_access_clients_table.php --- ..._01_000005_create_oauth_personal_access_clients_table.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 2e3761f4f..0fa5b7c62 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -14,8 +14,9 @@ class CreateOauthPersonalAccessClientsTable extends Migration public function up() { Schema::create('oauth_personal_access_clients', function (Blueprint $table) { - $table->increments('id'); - $table->unsignedInteger('client_id')->index(); + $table->bigIncrements('id'); + $table->bigInteger('client_id')->unsigned(); + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); $table->timestamps(); }); } From 140a693a079f5611b3342360cde00b10e94162c1 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 21 Jan 2020 15:13:09 -0600 Subject: [PATCH 066/353] wip --- .../2016_06_01_000001_create_oauth_auth_codes_table.php | 7 ++++--- .../2016_06_01_000002_create_oauth_access_tokens_table.php | 7 ++++--- ...2016_06_01_000003_create_oauth_refresh_tokens_table.php | 3 ++- .../2016_06_01_000004_create_oauth_clients_table.php | 4 ++-- ...1_000005_create_oauth_personal_access_clients_table.php | 5 +++-- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 8683148ea..36fb7480b 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -15,12 +15,13 @@ public function up() { Schema::create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->bigInteger('user_id')->unsigned()->index(); - $table->bigInteger('client_id')->unsigned(); - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); + $table->unsignedBigInteger('user_id')->index(); + $table->unsignedBigInteger('client_id'); $table->text('scopes')->nullable(); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); + + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 58ee1b0a0..6e1e9abef 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -15,14 +15,15 @@ public function up() { Schema::create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->bigInteger('user_id')->unsigned()->nullable()->index(); - $table->bigInteger('client_id')->unsigned(); - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); + $table->unsignedBigInteger('user_id')->nullable()->index(); + $table->unsignedBigInteger('client_id'); $table->string('name')->nullable(); $table->text('scopes')->nullable(); $table->boolean('revoked'); $table->timestamps(); $table->dateTime('expires_at')->nullable(); + + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 74644fe40..708862bc7 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -16,9 +16,10 @@ public function up() Schema::create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->string('access_token_id', 100); - $table->foreign('access_token_id')->references('id')->on('oauth_access_tokens')->onDelete('cascade'); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); + + $table->foreign('access_token_id')->references('id')->on('oauth_access_tokens')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 942078af6..1dc541a31 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -15,9 +15,9 @@ public function up() { Schema::create('oauth_clients', function (Blueprint $table) { $table->bigIncrements('id'); - $table->bigInteger('user_id')->unsigned()->nullable()->index(); + $table->unsignedBigInteger('user_id')->nullable()->index(); $table->string('name'); - $table->string('secret', 100); + $table->string('secret', 100)->nullable(); $table->text('redirect'); $table->boolean('personal_access_client'); $table->boolean('password_client'); diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 0fa5b7c62..07e107054 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -15,9 +15,10 @@ public function up() { Schema::create('oauth_personal_access_clients', function (Blueprint $table) { $table->bigIncrements('id'); - $table->bigInteger('client_id')->unsigned(); - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); + $table->unsignedBigInteger('client_id'); $table->timestamps(); + + $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } From 53b8bbfd7aaef688afca617137bc9a2fa7528569 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 24 Jan 2020 14:29:37 -0800 Subject: [PATCH 067/353] Create the PassportClientFactory Signed-off-by: Kevin Ullyott --- database/factories/PassportClientFactory.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 database/factories/PassportClientFactory.php diff --git a/database/factories/PassportClientFactory.php b/database/factories/PassportClientFactory.php new file mode 100644 index 000000000..2b8189b70 --- /dev/null +++ b/database/factories/PassportClientFactory.php @@ -0,0 +1,18 @@ +define(Client::class, function (Faker $faker) { + return [ + 'user_id' => null, + 'name' => $faker->company, + 'secret' => Str::random(40), + 'redirect' => $faker->url, + 'personal_access_client' => 0, + 'password_client' => 0, + 'revoked' => 0, + ]; +}); From a4fe544e121169b8fd22d0f79c37b70494e52362 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 24 Jan 2020 14:29:51 -0800 Subject: [PATCH 068/353] Publish the passport-factories Signed-off-by: Kevin Ullyott --- src/PassportServiceProvider.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 44fe0f208..063984a18 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -51,6 +51,10 @@ public function boot() __DIR__.'/../resources/js/components' => base_path('resources/js/components/passport'), ], 'passport-components'); + $this->publishes([ + __DIR__.'/../database/factories' => database_path('factories'), + ], 'passport-factories'); + $this->commands([ Console\InstallCommand::class, Console\ClientCommand::class, From 72e4f0f2cbd02e46de73f6d0d7fcbde0805ec28d Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 27 Jan 2020 08:56:20 -0600 Subject: [PATCH 069/353] Update PassportClientFactory.php --- database/factories/PassportClientFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/database/factories/PassportClientFactory.php b/database/factories/PassportClientFactory.php index 2b8189b70..63e64864b 100644 --- a/database/factories/PassportClientFactory.php +++ b/database/factories/PassportClientFactory.php @@ -3,6 +3,7 @@ /** @var \Illuminate\Database\Eloquent\Factory $factory */ use Faker\Generator as Faker; +use Illuminate\Support\Str; use Laravel\Passport\Client; $factory->define(Client::class, function (Faker $faker) { From e3d3c867d696c95e1cda7817533924db0f988007 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 28 Jan 2020 22:17:01 +0100 Subject: [PATCH 070/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbfc6026..2751a0360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.2.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.3.0...8.x) + + +## [v8.3.0 (2020-01-07)](https://github.com/laravel/passport/compare/v8.2.0...v8.3.0) + +### Added +- Add a Passport Client factory to Passport publishing ([#1171](https://github.com/laravel/passport/pull/1171)) + +### Changed +- Use bigIncrements and indexes on relationships ([#1169](https://github.com/laravel/passport/pull/1169), [140a693](https://github.com/laravel/passport/commit/140a693a079f5611b3342360cde00b10e94162c1)) ## [v8.2.0 (2020-01-07)](https://github.com/laravel/passport/compare/v8.1.0...v8.2.0) From 80721e3fbc77950f3dd3b0e978a4ad727c78a0a7 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 29 Jan 2020 14:04:13 +0100 Subject: [PATCH 071/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2751a0360..4ada3455d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## [Unreleased](https://github.com/laravel/passport/compare/v8.3.0...8.x) -## [v8.3.0 (2020-01-07)](https://github.com/laravel/passport/compare/v8.2.0...v8.3.0) +## [v8.3.0 (2020-01-28)](https://github.com/laravel/passport/compare/v8.2.0...v8.3.0) ### Added - Add a Passport Client factory to Passport publishing ([#1171](https://github.com/laravel/passport/pull/1171)) From 20e9b66fcd003ba41301fc5de23b9892e307051a Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 29 Jan 2020 14:24:08 +0100 Subject: [PATCH 072/353] Remove foreign keys --- .../2016_06_01_000001_create_oauth_auth_codes_table.php | 2 -- .../2016_06_01_000002_create_oauth_access_tokens_table.php | 2 -- .../2016_06_01_000003_create_oauth_refresh_tokens_table.php | 2 -- ..._06_01_000005_create_oauth_personal_access_clients_table.php | 2 -- 4 files changed, 8 deletions(-) diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 36fb7480b..6c47d2473 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -20,8 +20,6 @@ public function up() $table->text('scopes')->nullable(); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); - - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 6e1e9abef..00f00633a 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -22,8 +22,6 @@ public function up() $table->boolean('revoked'); $table->timestamps(); $table->dateTime('expires_at')->nullable(); - - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 708862bc7..858d0f6db 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -18,8 +18,6 @@ public function up() $table->string('access_token_id', 100); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); - - $table->foreign('access_token_id')->references('id')->on('oauth_access_tokens')->onDelete('cascade'); }); } diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 07e107054..4b56435ce 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -17,8 +17,6 @@ public function up() $table->bigIncrements('id'); $table->unsignedBigInteger('client_id'); $table->timestamps(); - - $table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade'); }); } From 98456cb16efd2ef7b41797e0a8559c9d8b4112f8 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 29 Jan 2020 14:25:24 +0100 Subject: [PATCH 073/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ada3455d..a719d964b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.3.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.3.1...8.x) + + +## [v8.3.1 (2020-01-29)](https://github.com/laravel/passport/compare/v8.3.0...v8.3.1) + +### Fixed +- Remove foreign keys ([20e9b66](https://github.com/laravel/passport/commit/20e9b66fcd003ba41301fc5de23b9892e307051a)) ## [v8.3.0 (2020-01-28)](https://github.com/laravel/passport/compare/v8.2.0...v8.3.0) From d5f7cdc164f55c319a712108473d4e70608d24d2 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Sat, 8 Feb 2020 22:17:42 +0100 Subject: [PATCH 074/353] Add password grant feature tests --- .travis.yml | 4 + database/factories/PassportClientFactory.php | 13 +- phpunit.xml.dist | 4 + tests/Feature/AccessTokenControllerTest.php | 189 +++++++++++++++++++ tests/Feature/PassportTestCase.php | 41 +++- 5 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 tests/Feature/AccessTokenControllerTest.php diff --git a/.travis.yml b/.travis.yml index e70bb8230..fa0f865b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,12 @@ matrix: allow_failures: - env: LARAVEL=^7.0 +services: + - mysql + before_install: - phpenv config-rm xdebug.ini || true + - mysql -e 'CREATE DATABASE forge;' install: - travis_retry composer require "illuminate/contracts=${LARAVEL}" --dev --prefer-dist --no-interaction --no-suggest diff --git a/database/factories/PassportClientFactory.php b/database/factories/PassportClientFactory.php index 63e64864b..a84c4c6ab 100644 --- a/database/factories/PassportClientFactory.php +++ b/database/factories/PassportClientFactory.php @@ -12,8 +12,15 @@ 'name' => $faker->company, 'secret' => Str::random(40), 'redirect' => $faker->url, - 'personal_access_client' => 0, - 'password_client' => 0, - 'revoked' => 0, + 'personal_access_client' => false, + 'password_client' => false, + 'revoked' => false, + ]; +}); + +$factory->state(Client::class, 'password_client', function (Faker $faker) { + return [ + 'personal_access_client' => false, + 'password_client' => true, ]; }); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 84a11d922..fed4d834b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,4 +20,8 @@ ./src/ + + + + diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php new file mode 100644 index 000000000..c23ad5134 --- /dev/null +++ b/tests/Feature/AccessTokenControllerTest.php @@ -0,0 +1,189 @@ +increments('id'); + $table->string('email')->unique(); + $table->string('password'); + $table->dateTime('created_at'); + $table->dateTime('updated_at'); + }); + } + + protected function tearDown(): void + { + Schema::dropIfExists('users'); + + parent::tearDown(); + } + + protected function getUserClass(): ?string + { + return User::class; + } + + public function testGettingAccessTokenWithPasswordGrant() + { + $this->withoutExceptionHandling(); + + $password = 'foobar123'; + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make($password); + $user->save(); + + /** @var Client $client */ + $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'password', + 'client_id' => $client->id, + 'client_secret' => $client->secret, + 'username' => $user->email, + 'password' => $password, + ] + ); + + $response->assertOk(); + + $response->assertHeader('pragma', 'no-cache'); + $response->assertHeader('cache-control', 'no-store, private'); + $response->assertHeader('content-type', 'application/json; charset=UTF-8'); + + $decodedResponse = $response->decodeResponseJson(); + + $this->assertArrayHasKey('token_type', $decodedResponse); + $this->assertArrayHasKey('expires_in', $decodedResponse); + $this->assertArrayHasKey('access_token', $decodedResponse); + $this->assertArrayHasKey('refresh_token', $decodedResponse); + $this->assertSame('Bearer', $decodedResponse['token_type']); + $expiresInSeconds = 31622400; + $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)); + + $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->getClaim('jti')); + $this->assertInstanceOf(Token::class, $token); + $this->assertFalse($token->revoked); + $this->assertTrue($token->user->is($user)); + $this->assertTrue($token->client->is($client)); + $this->assertNull($token->name); + $this->assertLessThanOrEqual(5, CarbonImmutable::now()->addSeconds($expiresInSeconds)->diffInSeconds($token->expires_at)); + } + + public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() + { + $password = 'foobar123'; + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make($password); + $user->save(); + + /** @var Client $client */ + $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'password', + 'client_id' => $client->id, + 'client_secret' => $client->secret, + 'username' => $user->email, + 'password' => $password.'foo', + ] + ); + + $response->assertStatus(400); + + $response->assertHeader('cache-control', 'no-cache, private'); + $response->assertHeader('content-type', 'application/json'); + + $decodedResponse = $response->decodeResponseJson(); + + $this->assertArrayNotHasKey('token_type', $decodedResponse); + $this->assertArrayNotHasKey('expires_in', $decodedResponse); + $this->assertArrayNotHasKey('access_token', $decodedResponse); + $this->assertArrayNotHasKey('refresh_token', $decodedResponse); + + $this->assertArrayHasKey('error', $decodedResponse); + $this->assertSame('invalid_grant', $decodedResponse['error']); + $this->assertArrayHasKey('error_description', $decodedResponse); + $this->assertArrayHasKey('hint', $decodedResponse); + $this->assertArrayHasKey('message', $decodedResponse); + + $this->assertSame(0, Token::count()); + } + + public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() + { + $password = 'foobar123'; + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make($password); + $user->save(); + + /** @var Client $client */ + $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'password', + 'client_id' => $client->id, + 'client_secret' => $client->secret.'foo', + 'username' => $user->email, + 'password' => $password, + ] + ); + + $response->assertStatus(401); + + $response->assertHeader('cache-control', 'no-cache, private'); + $response->assertHeader('content-type', 'application/json'); + + $decodedResponse = $response->decodeResponseJson(); + + $this->assertArrayNotHasKey('token_type', $decodedResponse); + $this->assertArrayNotHasKey('expires_in', $decodedResponse); + $this->assertArrayNotHasKey('access_token', $decodedResponse); + $this->assertArrayNotHasKey('refresh_token', $decodedResponse); + + $this->assertArrayHasKey('error', $decodedResponse); + $this->assertSame('invalid_client', $decodedResponse['error']); + $this->assertArrayHasKey('error_description', $decodedResponse); + $this->assertSame('Client authentication failed', $decodedResponse['error_description']); + $this->assertArrayNotHasKey('hint', $decodedResponse); + $this->assertArrayHasKey('message', $decodedResponse); + $this->assertSame('Client authentication failed', $decodedResponse['message']); + + $this->assertSame(0, Token::count()); + } +} + +class User extends \Illuminate\Foundation\Auth\User +{ + use HasApiTokens; +} diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index cee7f1685..2ed52e6a5 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -3,25 +3,64 @@ namespace Laravel\Passport\Tests\Feature; use Illuminate\Contracts\Config\Repository; +use Illuminate\Foundation\Testing\DatabaseTransactions; +use Laravel\Passport\Passport; use Laravel\Passport\PassportServiceProvider; use Orchestra\Testbench\TestCase; abstract class PassportTestCase extends TestCase { + use DatabaseTransactions; + protected function setUp(): void { parent::setUp(); + $this->withFactories(__DIR__.'/../../database/factories'); + + $this->artisan('migrate:fresh'); + + Passport::routes(); + $this->artisan('passport:keys'); } protected function getEnvironmentSetUp($app) { - $app->make(Repository::class)->set('auth.guards.api', ['driver' => 'passport', 'provider' => 'users']); + $config = $app->make(Repository::class); + + $config->set('auth.defaults.provider', 'users'); + + if (null !== ($userClass = $this->getUserClass())) { + $config->set('auth.providers.users.model', $userClass); + } + + $config->set('auth.guards.api', ['driver' => 'passport', 'provider' => 'users']); + + $config->set('database.default', 'forge'); + + $config->set('database.connections.forge', [ + 'driver' => 'mysql', + 'host' => env('DB_HOST', '127.0.0.1'), + 'username' => 'root', + 'password' => '', + 'database' => 'forge', + 'prefix' => '', + ]); } protected function getPackageProviders($app) { return [PassportServiceProvider::class]; } + + /** + * Get the Eloquent user model class name. + * + * @return string|null + */ + protected function getUserClass(): ?string + { + return null; + } } From e7876c6201ffbd4c35e0d772ca58dae9f7696b80 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 11 Feb 2020 18:03:04 +0100 Subject: [PATCH 075/353] Revoke refresh tokens as well --- .../AuthorizedAccessTokenController.php | 14 +++++++++++++- src/RefreshTokenRepository.php | 11 +++++++++++ tests/AuthorizedAccessTokenControllerTest.php | 10 +++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index a2a26b20a..47be85dba 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; +use Laravel\Passport\RefreshTokenRepository; use Laravel\Passport\TokenRepository; class AuthorizedAccessTokenController @@ -15,15 +16,24 @@ class AuthorizedAccessTokenController */ protected $tokenRepository; + /** + * The refresh token repository implementation. + * + * @var \Laravel\Passport\RefreshTokenRepository + */ + protected $refreshTokenRepository; + /** * Create a new controller instance. * * @param \Laravel\Passport\TokenRepository $tokenRepository + * @param \Laravel\Passport\RefreshTokenRepository $refreshTokenRepository * @return void */ - public function __construct(TokenRepository $tokenRepository) + public function __construct(TokenRepository $tokenRepository, RefreshTokenRepository $refreshTokenRepository) { $this->tokenRepository = $tokenRepository; + $this->refreshTokenRepository = $refreshTokenRepository; } /** @@ -60,6 +70,8 @@ public function destroy(Request $request, $tokenId) $token->revoke(); + $this->refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId); + return new Response('', Response::HTTP_NO_CONTENT); } } diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php index b06d519b5..ded3b0a85 100644 --- a/src/RefreshTokenRepository.php +++ b/src/RefreshTokenRepository.php @@ -48,6 +48,17 @@ public function revokeRefreshToken($id) return Passport::refreshToken()->where('id', $id)->update(['revoked' => true]); } + /** + * Revokes refresh tokens by access token id. + * + * @param string $tokenId + * @return void + */ + public function revokeRefreshTokensByAccessTokenId($tokenId) + { + Passport::refreshToken()->where('access_token_id', $tokenId)->update(['revoked' => true]); + } + /** * Checks if the refresh token has been revoked. * diff --git a/tests/AuthorizedAccessTokenControllerTest.php b/tests/AuthorizedAccessTokenControllerTest.php index bf863c393..786f6335e 100644 --- a/tests/AuthorizedAccessTokenControllerTest.php +++ b/tests/AuthorizedAccessTokenControllerTest.php @@ -5,6 +5,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; use Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController; +use Laravel\Passport\RefreshTokenRepository; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Mockery as m; @@ -18,6 +19,11 @@ class AuthorizedAccessTokenControllerTest extends TestCase */ protected $tokenRepository; + /** + * @var \Mockery\Mock|\Laravel\Passport\RefreshTokenRepository + */ + protected $refreshTokenRepository; + /** * @var AuthorizedAccessTokenController */ @@ -26,7 +32,8 @@ class AuthorizedAccessTokenControllerTest extends TestCase protected function setUp(): void { $this->tokenRepository = m::mock(TokenRepository::class); - $this->controller = new AuthorizedAccessTokenController($this->tokenRepository); + $this->refreshTokenRepository = m::mock(RefreshTokenRepository::class); + $this->controller = new AuthorizedAccessTokenController($this->tokenRepository, $this->refreshTokenRepository); } protected function tearDown(): void @@ -78,6 +85,7 @@ public function test_tokens_can_be_deleted() $token1->shouldReceive('revoke')->once(); $this->tokenRepository->shouldReceive('findForUser')->andReturn($token1); + $this->refreshTokenRepository->shouldReceive('revokeRefreshTokensByAccessTokenId')->once(); $request->setUserResolver(function () { $user = m::mock(); From adb02ff8408719d9818920b772f91e74c27c44dc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 11 Feb 2020 19:54:40 +0100 Subject: [PATCH 076/353] Implement auth token for access requests --- resources/views/authorize.blade.php | 2 ++ src/Exceptions/InvalidAuthTokenException.php | 18 ++++++++++++++++++ .../ApproveAuthorizationController.php | 2 ++ .../Controllers/AuthorizationController.php | 3 +++ .../DenyAuthorizationController.php | 2 ++ .../RetrievesAuthRequestFromSession.php | 16 ++++++++++++++++ tests/ApproveAuthorizationControllerTest.php | 5 +++++ tests/AuthorizationControllerTest.php | 1 + tests/DenyAuthorizationControllerTest.php | 10 ++++++++++ 9 files changed, 59 insertions(+) create mode 100644 src/Exceptions/InvalidAuthTokenException.php diff --git a/resources/views/authorize.blade.php b/resources/views/authorize.blade.php index ab0d4fb31..ecbdcaa58 100644 --- a/resources/views/authorize.blade.php +++ b/resources/views/authorize.blade.php @@ -69,6 +69,7 @@ + @@ -79,6 +80,7 @@ + diff --git a/src/Exceptions/InvalidAuthTokenException.php b/src/Exceptions/InvalidAuthTokenException.php new file mode 100644 index 000000000..6427929e4 --- /dev/null +++ b/src/Exceptions/InvalidAuthTokenException.php @@ -0,0 +1,18 @@ +assertValidAuthToken($request); + $authRequest = $this->getAuthRequestFromSession($request); return $this->convertResponse( diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index fe1c03258..df3eede8d 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; +use Illuminate\Support\Str; use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\Bridge\User; use Laravel\Passport\ClientRepository; @@ -73,6 +74,7 @@ public function authorize(ServerRequestInterface $psrRequest, return $this->approveRequest($authRequest, $user); } + $request->session()->put('authToken', $authToken = Str::random()); $request->session()->put('authRequest', $authRequest); return $this->response->view('passport::authorize', [ @@ -80,6 +82,7 @@ public function authorize(ServerRequestInterface $psrRequest, 'user' => $user, 'scopes' => $scopes, 'request' => $request, + 'authToken' => $authToken, ]); } diff --git a/src/Http/Controllers/DenyAuthorizationController.php b/src/Http/Controllers/DenyAuthorizationController.php index bf35c77a2..613dfd465 100644 --- a/src/Http/Controllers/DenyAuthorizationController.php +++ b/src/Http/Controllers/DenyAuthorizationController.php @@ -36,6 +36,8 @@ public function __construct(ResponseFactory $response) */ public function deny(Request $request) { + $this->assertValidAuthToken($request); + $authRequest = $this->getAuthRequestFromSession($request); $clientUris = Arr::wrap($authRequest->getClient()->getRedirectUri()); diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index 4ab67b36d..e5f31ffb3 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -5,9 +5,25 @@ use Exception; use Illuminate\Http\Request; use Laravel\Passport\Bridge\User; +use Laravel\Passport\Exceptions\InvalidAuthTokenException; trait RetrievesAuthRequestFromSession { + /** + * Make sure the auth token matches the one in the session. + * + * @param \Illuminate\Http\Request $request + * @return void + * + * @throws \Laravel\Passport\Exceptions\InvalidAuthTokenException + */ + protected function assertValidAuthToken(Request $request) + { + if ($request->session()->get('authToken') !== $request->get('auth_token')) { + throw InvalidAuthTokenException::different(); + } + } + /** * Get the authorization request from the session. * diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index 97f42b846..357f7bfd6 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -26,11 +26,16 @@ public function test_complete_authorization_request() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); + + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get') ->once() ->with('authRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + $request->shouldReceive('user')->andReturn(new ApproveAuthorizationControllerFakeUser); + $authRequest->shouldReceive('getClient->getIdentifier')->andReturn(1); $authRequest->shouldReceive('getUser->getIdentifier')->andReturn(2); $authRequest->shouldReceive('setUser')->once(); diff --git a/tests/AuthorizationControllerTest.php b/tests/AuthorizationControllerTest.php index e9f47e4e7..ab5a14287 100644 --- a/tests/AuthorizationControllerTest.php +++ b/tests/AuthorizationControllerTest.php @@ -43,6 +43,7 @@ public function test_authorization_view_is_presented() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); $request->shouldReceive('user')->andReturn($user = m::mock()); diff --git a/tests/DenyAuthorizationControllerTest.php b/tests/DenyAuthorizationControllerTest.php index 38362c77f..bcb8ed4d9 100644 --- a/tests/DenyAuthorizationControllerTest.php +++ b/tests/DenyAuthorizationControllerTest.php @@ -27,7 +27,9 @@ public function test_authorization_can_be_denied() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( AuthorizationRequest::class )); @@ -56,6 +58,7 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( AuthorizationRequest::class @@ -67,6 +70,7 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris() $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn(['http://localhost.localdomain', 'http://localhost']); + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { return $url; }); @@ -85,7 +89,9 @@ public function test_authorization_can_be_denied_implicit() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( AuthorizationRequest::class )); @@ -114,7 +120,9 @@ public function test_authorization_can_be_denied_with_existing_query_string() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( AuthorizationRequest::class )); @@ -146,7 +154,9 @@ public function test_auth_request_should_exist() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->never(); $request->shouldReceive('input')->never(); + $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); + $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturnNull(); $response->shouldReceive('redirectTo')->never(); From bf6b57ddd572490f04bfd11bf729f1c3ab4ffe76 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 11 Feb 2020 20:28:20 +0100 Subject: [PATCH 077/353] Optionally skip if no auth_token is provided --- src/Http/Controllers/RetrievesAuthRequestFromSession.php | 2 +- tests/ApproveAuthorizationControllerTest.php | 1 + tests/DenyAuthorizationControllerTest.php | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index e5f31ffb3..06fec9d14 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -19,7 +19,7 @@ trait RetrievesAuthRequestFromSession */ protected function assertValidAuthToken(Request $request) { - if ($request->session()->get('authToken') !== $request->get('auth_token')) { + if ($request->has('auth_token') && $request->session()->get('authToken') !== $request->get('auth_token')) { throw InvalidAuthTokenException::different(); } } diff --git a/tests/ApproveAuthorizationControllerTest.php b/tests/ApproveAuthorizationControllerTest.php index 357f7bfd6..88a8c5c56 100644 --- a/tests/ApproveAuthorizationControllerTest.php +++ b/tests/ApproveAuthorizationControllerTest.php @@ -26,6 +26,7 @@ public function test_complete_authorization_request() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); diff --git a/tests/DenyAuthorizationControllerTest.php b/tests/DenyAuthorizationControllerTest.php index bcb8ed4d9..095609a6e 100644 --- a/tests/DenyAuthorizationControllerTest.php +++ b/tests/DenyAuthorizationControllerTest.php @@ -27,6 +27,7 @@ public function test_authorization_can_be_denied() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); @@ -58,6 +59,7 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( @@ -89,6 +91,7 @@ public function test_authorization_can_be_denied_implicit() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); @@ -120,6 +123,7 @@ public function test_authorization_can_be_denied_with_existing_query_string() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); $request->shouldReceive('input')->with('state')->andReturn('state'); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); @@ -154,6 +158,7 @@ public function test_auth_request_should_exist() $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->never(); $request->shouldReceive('input')->never(); + $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); From c1be259ff85109416e9e81c80fa4d3d611d6398a Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 12 Feb 2020 15:34:02 +0100 Subject: [PATCH 078/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a719d964b..58537d600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.3.1...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.4.0...8.x) + + +## [v8.4.0 (2020-02-12)](https://github.com/laravel/passport/compare/v8.3.1...v8.4.0) + +### Changed +- Implement auth token for access requests ([#1188](https://github.com/laravel/passport/pull/1188)) + +### Fixed +- Revoke refresh tokens when auth tokens get revoked ([#1186](https://github.com/laravel/passport/pull/1186)) ## [v8.3.1 (2020-01-29)](https://github.com/laravel/passport/compare/v8.3.0...v8.3.1) From b5c5093a4cfc253d2fa4da1237bfc8e417a35792 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 13 Feb 2020 14:15:09 +0100 Subject: [PATCH 079/353] Forget session keys on invalid match --- src/Http/Controllers/RetrievesAuthRequestFromSession.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index 06fec9d14..bb704d8f1 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -20,6 +20,8 @@ trait RetrievesAuthRequestFromSession protected function assertValidAuthToken(Request $request) { if ($request->has('auth_token') && $request->session()->get('authToken') !== $request->get('auth_token')) { + $request->session()->forget(['authToken', 'authRequest']); + throw InvalidAuthTokenException::different(); } } From 0fa684fa955ece4e61ef3b1979a1a299b56bb4fe Mon Sep 17 00:00:00 2001 From: Ilyes512 Date: Sat, 15 Feb 2020 16:24:55 +0100 Subject: [PATCH 080/353] Joined config publish registering with the rest of the publish registries --- src/PassportServiceProvider.php | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 063984a18..9c81acafb 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -55,6 +55,10 @@ public function boot() __DIR__.'/../database/factories' => database_path('factories'), ], 'passport-factories'); + $this->publishes([ + __DIR__.'/../config/passport.php' => config_path('passport.php'), + ], 'passport-config'); + $this->commands([ Console\InstallCommand::class, Console\ClientCommand::class, @@ -90,7 +94,6 @@ public function register() $this->registerAuthorizationServer(); $this->registerResourceServer(); $this->registerGuard(); - $this->offerPublishing(); } /** @@ -296,18 +299,4 @@ protected function deleteCookieOnLogout() } }); } - - /** - * Setup the resource publishing groups for Passport. - * - * @return void - */ - protected function offerPublishing() - { - if ($this->app->runningInConsole()) { - $this->publishes([ - __DIR__.'/../config/passport.php' => config_path('passport.php'), - ], 'passport-config'); - } - } } From 51a04848007cd7e17977b6507d1633c6eff3b556 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 20 Feb 2020 17:07:57 +0100 Subject: [PATCH 081/353] Refactor to sqlite tests --- .travis.yml | 4 ---- phpunit.xml.dist | 1 - tests/Feature/AccessTokenControllerTest.php | 2 +- tests/Feature/PassportTestCase.php | 21 +++++++++------------ 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa0f865b3..e70bb8230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,8 @@ matrix: allow_failures: - env: LARAVEL=^7.0 -services: - - mysql - before_install: - phpenv config-rm xdebug.ini || true - - mysql -e 'CREATE DATABASE forge;' install: - travis_retry composer require "illuminate/contracts=${LARAVEL}" --dev --prefer-dist --no-interaction --no-suggest diff --git a/phpunit.xml.dist b/phpunit.xml.dist index fed4d834b..f313b78a5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,7 +20,6 @@ ./src/ - diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index c23ad5134..8f0f7f1ab 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -36,7 +36,7 @@ protected function tearDown(): void parent::tearDown(); } - protected function getUserClass(): ?string + protected function getUserClass() { return User::class; } diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 2ed52e6a5..d919eb5d1 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -3,14 +3,14 @@ namespace Laravel\Passport\Tests\Feature; use Illuminate\Contracts\Config\Repository; -use Illuminate\Foundation\Testing\DatabaseTransactions; +use Illuminate\Foundation\Testing\RefreshDatabase; use Laravel\Passport\Passport; use Laravel\Passport\PassportServiceProvider; use Orchestra\Testbench\TestCase; abstract class PassportTestCase extends TestCase { - use DatabaseTransactions; + use RefreshDatabase; protected function setUp(): void { @@ -31,21 +31,18 @@ protected function getEnvironmentSetUp($app) $config->set('auth.defaults.provider', 'users'); - if (null !== ($userClass = $this->getUserClass())) { + if (($userClass = $this->getUserClass()) !== null) { $config->set('auth.providers.users.model', $userClass); } $config->set('auth.guards.api', ['driver' => 'passport', 'provider' => 'users']); - $config->set('database.default', 'forge'); + $app['config']->set('database.default', 'testbench'); - $config->set('database.connections.forge', [ - 'driver' => 'mysql', - 'host' => env('DB_HOST', '127.0.0.1'), - 'username' => 'root', - 'password' => '', - 'database' => 'forge', - 'prefix' => '', + $app['config']->set('database.connections.testbench', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '', ]); } @@ -59,7 +56,7 @@ protected function getPackageProviders($app) * * @return string|null */ - protected function getUserClass(): ?string + protected function getUserClass() { return null; } From a35da9541790bb8f156e4cb0c6c6336ead705c4b Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 20 Feb 2020 17:08:22 +0100 Subject: [PATCH 082/353] Apply fixes from StyleCI (#1198) --- tests/Feature/PassportTestCase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index d919eb5d1..74f1a0bb7 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -58,6 +58,5 @@ protected function getPackageProviders($app) */ protected function getUserClass() { - return null; } } From 18e33ab3c63939ea183b4801ecba086bee060370 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 20 Feb 2020 17:11:03 +0100 Subject: [PATCH 083/353] Implement Github Actions --- .gitattributes | 1 - .github/workflows/tests.yml | 42 +++++++++++++++++++++++++++++++++++++ .travis.yml | 26 ----------------------- README.md | 2 +- 4 files changed, 43 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/tests.yml delete mode 100644 .travis.yml diff --git a/.gitattributes b/.gitattributes index ab9a2cea0..9f9414b4c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,7 +6,6 @@ .gitattributes export-ignore .gitignore export-ignore .styleci.yml export-ignore -.travis.yml export-ignore CHANGELOG.md export-ignore phpunit.xml.dist export-ignore UPGRADE.md diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..0b24cf9e3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,42 @@ +name: tests + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + tests: + + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: [7.2, 7.3, 7.4] + laravel: [6.*, 7.*] + + name: P${{ matrix.php }} - L${{ matrix.laravel }} + + steps: + - name: Checkout code + uses: actions/checkout@v1 + + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ~/.composer/cache/files + key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v1 + with: + php-version: ${{ matrix.php }} + extension-csv: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick + coverage: none + + - name: Install dependencies + run: composer require "illuminate/contracts=${{ matrix.laravel }}" --prefer-dist --no-interaction --no-suggest + + - name: Execute tests + run: vendor/bin/phpunit --verbose diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e70bb8230..000000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -dist: bionic -language: php - -php: - - 7.2 - - 7.3 - - 7.4 - -env: - matrix: - - LARAVEL=^6.0 - - LARAVEL=^7.0 - -matrix: - fast_finish: true - allow_failures: - - env: LARAVEL=^7.0 - -before_install: - - phpenv config-rm xdebug.ini || true - -install: - - travis_retry composer require "illuminate/contracts=${LARAVEL}" --dev --prefer-dist --no-interaction --no-suggest - -script: - - vendor/bin/phpunit --verbose diff --git a/README.md b/README.md index af6c766f9..927b5d810 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

-Build Status +Build Status Total Downloads Latest Stable Version License From 0d9a007cbb814b8b6052200a969f209388fd3b04 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 20 Feb 2020 17:43:12 +0100 Subject: [PATCH 084/353] Bump dependencies --- .github/workflows/tests.yml | 4 ++-- composer.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0b24cf9e3..a68f3a3c2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: fail-fast: true matrix: php: [7.2, 7.3, 7.4] - laravel: [6.*, 7.*] + laravel: [^6.0, ^7.0] name: P${{ matrix.php }} - L${{ matrix.laravel }} @@ -32,7 +32,7 @@ jobs: uses: shivammathur/setup-php@v1 with: php-version: ${{ matrix.php }} - extension-csv: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick coverage: none - name: Install dependencies diff --git a/composer.json b/composer.json index ecb79c8c9..231d4439f 100644 --- a/composer.json +++ b/composer.json @@ -29,8 +29,9 @@ "illuminate/support": "^6.0|^7.0", "laminas/laminas-diactoros": "^2.2", "league/oauth2-server": "^8.0", + "nyholm/psr7": "^1.0", "phpseclib/phpseclib": "^2.0", - "symfony/psr-http-message-bridge": "^1.0" + "symfony/psr-http-message-bridge": "^2.0" }, "require-dev": { "mockery/mockery": "^1.0", From ded0ccde2d0ba9d54d5edde4810535ae258a5661 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 2 Mar 2020 14:10:46 +0100 Subject: [PATCH 085/353] Fix tests --- tests/Feature/AccessTokenControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 8f0f7f1ab..48697da62 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -78,7 +78,7 @@ public function testGettingAccessTokenWithPasswordGrant() $this->assertArrayHasKey('access_token', $decodedResponse); $this->assertArrayHasKey('refresh_token', $decodedResponse); $this->assertSame('Bearer', $decodedResponse['token_type']); - $expiresInSeconds = 31622400; + $expiresInSeconds = 31536000; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); $jwtAccessToken = (new Parser())->parse($decodedResponse['access_token']); From 4088cdf174d25ccf3fb79d234b94b2a90785fa69 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 4 Mar 2020 14:55:07 +0100 Subject: [PATCH 086/353] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58537d600..03d8f41a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.4.0...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.4.1...8.x) + + +## [v8.4.1 (2020-03-04)](https://github.com/laravel/passport/compare/v8.4.0...v8.4.1) + +### Fixed +- Forget session keys on invalid match ([#1192](https://github.com/laravel/passport/pull/1192)) +- Update dependencies for PSR request ([#1201](https://github.com/laravel/passport/pull/1201)) ## [v8.4.0 (2020-02-12)](https://github.com/laravel/passport/compare/v8.3.1...v8.4.0) From d95d252c471915ee2a48a4d27fe5c67adb0f7ca2 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 20 Mar 2020 12:37:46 +0800 Subject: [PATCH 087/353] [8.x] mergeConfigFrom() already check if app is running with config cached. https://github.com/illuminate/support/blob/6.x/ServiceProvider.php#L60-L67 --- src/PassportServiceProvider.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 9c81acafb..1f3bd4040 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -87,9 +87,7 @@ protected function registerMigrations() */ public function register() { - if (! $this->app->configurationIsCached()) { - $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); - } + $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); $this->registerAuthorizationServer(); $this->registerResourceServer(); From 0420dc294ce2fbf92bb3a2d18505053f552b70b1 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 24 Mar 2020 17:31:27 +0100 Subject: [PATCH 088/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03d8f41a8..b08ec1dc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.4.1...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.4.2...8.x) + + +## [v8.4.2 (2020-03-24)](https://github.com/laravel/passport/compare/v8.4.1...v8.4.2) + +### Fixed +- `mergeConfigFrom` already checked if app is running with config cached ([#1205](https://github.com/laravel/passport/pull/1205)) ## [v8.4.1 (2020-03-04)](https://github.com/laravel/passport/compare/v8.4.0...v8.4.1) From 21d2ec33c26c0948e8d9dda6da730a633e9fc086 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 24 Mar 2020 18:13:01 +0100 Subject: [PATCH 089/353] Update 1_Bug_report.md --- .github/ISSUE_TEMPLATE/1_Bug_report.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md index c8615c502..5d665d723 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.md @@ -1,8 +1,11 @@ --- name: "Bug report" -about: 'Report a general library issue. Please ensure your version is still supported: https://laravel.com/docs/releases#support-policy' +about: "Report something that's broken. Please ensure your Laravel version is still supported: https://laravel.com/docs/releases#support-policy" --- + + + - Passport Version: #.#.# - Laravel Version: #.#.# - PHP Version: #.#.# From 86a2cd83cd341149c7ff8d64af2be71b11504fed Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 24 Mar 2020 18:13:14 +0100 Subject: [PATCH 090/353] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0f039119b..6253bb2d4 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - - name: Support question + - name: Support Questions & Other url: https://laravel.com/docs/contributions#support-questions - about: 'This repository is only for reporting bugs. If you need help using the library, click:' + about: 'This repository is only for reporting bugs. If you have a question or need help using the library, click:' - name: Documentation issue url: https://github.com/laravel/docs about: For documentation issues, open a pull request at the laravel/docs repository From 2af64529adaf65f650b373f683116cdd42e3d738 Mon Sep 17 00:00:00 2001 From: Lucas Michot Date: Thu, 26 Mar 2020 17:54:47 +0100 Subject: [PATCH 091/353] Fix resolveInheritedScopes. --- src/Token.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Token.php b/src/Token.php index 15193a427..5a803bdcd 100644 --- a/src/Token.php +++ b/src/Token.php @@ -116,10 +116,11 @@ public function can($scope) protected function resolveInheritedScopes($scope) { $parts = explode(':', $scope); + $partsCount = count($parts); $scopes = []; - for ($i = 0; $i <= count($parts); $i++) { + for ($i = 1; $i <= $partsCount; $i++) { $scopes[] = implode(':', array_slice($parts, 0, $i)); } From 92f729ff68490a3f2483d6686f900f8c3c109663 Mon Sep 17 00:00:00 2001 From: Lucas Michot Date: Thu, 26 Mar 2020 18:55:37 +0100 Subject: [PATCH 092/353] Add an extra test. --- tests/TokenTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/TokenTest.php b/tests/TokenTest.php index 00e7c64e1..c749b00f3 100644 --- a/tests/TokenTest.php +++ b/tests/TokenTest.php @@ -5,6 +5,7 @@ use Laravel\Passport\Passport; use Laravel\Passport\Token; use PHPUnit\Framework\TestCase; +use ReflectionObject; class TokenTest extends TestCase { @@ -58,4 +59,20 @@ public function test_token_can_determine_if_it_has_inherited_scopes() $this->assertTrue($token->can('something')); $this->assertTrue($token->can('admin:webhooks:write')); } + + public function test_token_resolves_inherited_scopes() + { + $token = new Token; + + $reflector = new ReflectionObject($token); + $method = $reflector->getMethod('resolveInheritedScopes'); + $method->setAccessible(true); + $inheritedScopes = $method->invoke($token, 'admin:webhooks:read'); + + $this->assertSame([ + 'admin', + 'admin:webhooks', + 'admin:webhooks:read', + ], $inheritedScopes); + } } From 0319409bbd93e0c265117344a02ac7dd033a822a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 26 Mar 2020 14:53:54 -0500 Subject: [PATCH 093/353] Update Token.php --- src/Token.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Token.php b/src/Token.php index 5a803bdcd..aa1790098 100644 --- a/src/Token.php +++ b/src/Token.php @@ -116,6 +116,7 @@ public function can($scope) protected function resolveInheritedScopes($scope) { $parts = explode(':', $scope); + $partsCount = count($parts); $scopes = []; From edb9ccb9993ca98c7347da2fae20e1b8b4895f31 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 31 Mar 2020 17:48:43 +0200 Subject: [PATCH 094/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b08ec1dc8..59f558cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.4.2...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.4.3...8.x) + + +## [v8.4.3 (2020-03-31)](https://github.com/laravel/passport/compare/v8.4.2...v8.4.3) + +### Fixed +- Fix resolveInheritedScopes ([#1207](https://github.com/laravel/passport/pull/1207)) ## [v8.4.2 (2020-03-24)](https://github.com/laravel/passport/compare/v8.4.1...v8.4.2) From 02e2d8332bc24dbf17dfcb8278cdddf2d6734529 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Apr 2020 11:19:25 +0200 Subject: [PATCH 095/353] Update tests.yml --- .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 a68f3a3c2..2d7e7eb41 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -36,7 +36,7 @@ jobs: coverage: none - name: Install dependencies - run: composer require "illuminate/contracts=${{ matrix.laravel }}" --prefer-dist --no-interaction --no-suggest + run: composer require "illuminate/contracts=${{ matrix.laravel }}" --prefer-dist --no-interaction - name: Execute tests run: vendor/bin/phpunit --verbose From 639788bfebe87529b916d853482f9e5753e02af8 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Fri, 17 Apr 2020 03:05:21 -0400 Subject: [PATCH 096/353] Initial support for multiple providers --- ...16_06_01_000004_create_oauth_clients_table.php | 1 + src/Bridge/Client.php | 5 ++++- src/Bridge/ClientRepository.php | 2 +- src/Bridge/UserRepository.php | 2 +- src/Client.php | 13 ++++++++++++- src/ClientRepository.php | 9 +++++---- src/Console/ClientCommand.php | 13 +++++++++++-- src/Console/InstallCommand.php | 2 +- src/Guards/TokenGuard.php | 15 +++++++++++++++ src/Http/Middleware/CheckCredentials.php | 2 +- 10 files changed, 52 insertions(+), 12 deletions(-) diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 1dc541a31..f0884ee7b 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -18,6 +18,7 @@ public function up() $table->unsignedBigInteger('user_id')->nullable()->index(); $table->string('name'); $table->string('secret', 100)->nullable(); + $table->string('provider')->nullable(); $table->text('redirect'); $table->boolean('personal_access_client'); $table->boolean('password_client'); diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index 43eec2029..22298d3ab 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -16,6 +16,8 @@ class Client implements ClientEntityInterface */ protected $identifier; + public $provider; + /** * Create a new client instance. * @@ -25,13 +27,14 @@ class Client implements ClientEntityInterface * @param bool $isConfidential * @return void */ - public function __construct($identifier, $name, $redirectUri, $isConfidential = false) + public function __construct($identifier, $name, $redirectUri, $isConfidential = false, $provider = null) { $this->setIdentifier((string) $identifier); $this->name = $name; $this->isConfidential = $isConfidential; $this->redirectUri = explode(',', $redirectUri); + $this->provider = $provider; } /** diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index 9cd17762e..e9fb4b0d0 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -37,7 +37,7 @@ public function getClientEntity($clientIdentifier) } return new Client( - $clientIdentifier, $record->name, $record->redirect, $record->confidential() + $clientIdentifier, $record->name, $record->redirect, $record->confidential(), $record->provider ); } diff --git a/src/Bridge/UserRepository.php b/src/Bridge/UserRepository.php index 8b0f6237d..bd4706d53 100644 --- a/src/Bridge/UserRepository.php +++ b/src/Bridge/UserRepository.php @@ -32,7 +32,7 @@ public function __construct(HashManager $hasher) */ public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity) { - $provider = config('auth.guards.api.provider'); + $provider = $clientEntity->provider ?: config('auth.guards.api.provider'); if (is_null($model = config('auth.providers.'.$provider.'.model'))) { throw new RuntimeException('Unable to determine authentication model from configuration.'); diff --git a/src/Client.php b/src/Client.php index 51b2b7013..7adca9993 100644 --- a/src/Client.php +++ b/src/Client.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Auth; class Client extends Model { @@ -49,7 +50,7 @@ class Client extends Model public function user() { return $this->belongsTo( - config('auth.providers.'.config('auth.guards.api.provider').'.model') + config('auth.providers.'.$this->provider ?: config('auth.guards.api.provider').'.model') ); } @@ -102,4 +103,14 @@ public function confidential() { return ! empty($this->secret); } + + /** + * Get the client's provider. + * + * @return mixed + */ + public function getProvider() + { + return $this->provider ? Auth::createUserProvider($this->provider) : null; + } } diff --git a/src/ClientRepository.php b/src/ClientRepository.php index a8b9431ef..398a71575 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -109,13 +109,14 @@ public function personalAccessClient() * @param bool $confidential * @return \Laravel\Passport\Client */ - public function create($userId, $name, $redirect, $personalAccess = false, $password = false, $confidential = true) + public function create($userId, $name, $redirect, $provider = null, $personalAccess = false, $password = false, $confidential = true) { $client = Passport::client()->forceFill([ 'user_id' => $userId, 'name' => $name, 'secret' => ($confidential || $personalAccess) ? Str::random(40) : null, 'redirect' => $redirect, + 'provider' => $provider, 'personal_access_client' => $personalAccess, 'password_client' => $password, 'revoked' => false, @@ -136,7 +137,7 @@ public function create($userId, $name, $redirect, $personalAccess = false, $pass */ public function createPersonalAccessClient($userId, $name, $redirect) { - return tap($this->create($userId, $name, $redirect, true), function ($client) { + return tap($this->create($userId, $name, $redirect, null, true), function ($client) { $accessClient = Passport::personalAccessClient(); $accessClient->client_id = $client->id; $accessClient->save(); @@ -151,9 +152,9 @@ public function createPersonalAccessClient($userId, $name, $redirect) * @param string $redirect * @return \Laravel\Passport\Client */ - public function createPasswordGrantClient($userId, $name, $redirect) + public function createPasswordGrantClient($userId, $name, $redirect, $provider = null) { - return $this->create($userId, $name, $redirect, false, true); + return $this->create($userId, $name, $redirect, $provider, false, true); } /** diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 5ae9bd035..8771d1616 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -18,6 +18,7 @@ class ClientCommand extends Command {--password : Create a password grant client} {--client : Create a client credentials grant client} {--name= : The name of the client} + {--provider= : The name of the provider} {--redirect_uri= : The URI to redirect to after authorization } {--user_id= : The user ID the client should be assigned to } {--public : Create a public client (Auth code grant type only) }'; @@ -83,8 +84,16 @@ protected function createPasswordClient(ClientRepository $clients) config('app.name').' Password Grant Client' ); + $providers = array_keys(config('auth.providers')); + + $provider = $this->option('provider') ?: $this->choice( + 'What provider should be used?', + $providers, + $providers[0] + ); + $client = $clients->createPasswordGrantClient( - null, $name, 'http://localhost' + null, $name, 'http://localhost', $provider ); $this->info('Password grant client created successfully.'); @@ -136,7 +145,7 @@ protected function createAuthCodeClient(ClientRepository $clients) ); $client = $clients->create( - $userId, $name, $redirect, false, false, ! $this->option('public') + $userId, $name, $redirect, null, false, false, ! $this->option('public') ); $this->info('New client created successfully.'); diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 89b80440d..9a40d2874 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -31,6 +31,6 @@ public function handle() { $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); - $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client']); + $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => array_keys(config('auth.providers'))[0]]); } } diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 23244366a..4ebd237f4 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -82,6 +82,17 @@ public function __construct(ResourceServer $server, $this->encrypter = $encrypter; } + /** + * Determine if the requested provider matches the client's provider. + * + * @param \Illuminate\Http\Request $request + * @return bool + */ + protected function validateProvider(Request $request) + { + return $this->provider == $this->client($request)->getProvider(); + } + /** * Get the user for the incoming request. * @@ -90,6 +101,10 @@ public function __construct(ResourceServer $server, */ public function user(Request $request) { + if (!$this->validateProvider($request)) { + return; + } + if ($request->bearerToken()) { return $this->authenticateViaBearerToken($request); } elseif ($request->cookie(Passport::cookie())) { diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 8c2323c0d..c2efdb8e5 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -101,7 +101,7 @@ protected function validate($psr, $scopes) abstract protected function validateCredentials($token); /** - * Validate token credentials. + * Validate token scopes. * * @param \Laravel\Passport\Token $token * @param array $scopes From 83dbcd3be1b491af623c7c289a74ec49ebd8e52e Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Fri, 17 Apr 2020 04:18:57 -0400 Subject: [PATCH 097/353] DocBlocks --- src/Bridge/Client.php | 15 ++++++++++----- src/ClientRepository.php | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index 22298d3ab..9f2a05517 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -16,16 +16,21 @@ class Client implements ClientEntityInterface */ protected $identifier; + /** + * The client's provider. + * + * @var string + */ public $provider; /** * Create a new client instance. * - * @param string $identifier - * @param string $name - * @param string $redirectUri - * @param bool $isConfidential - * @return void + * @param string $identifier + * @param string $name + * @param string $redirectUri + * @param bool $isConfidential + * @param string|null $provider */ public function __construct($identifier, $name, $redirectUri, $isConfidential = false, $provider = null) { diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 398a71575..8a825735b 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -101,12 +101,13 @@ public function personalAccessClient() /** * Store a new client. * - * @param int $userId - * @param string $name - * @param string $redirect - * @param bool $personalAccess - * @param bool $password - * @param bool $confidential + * @param int $userId + * @param string $name + * @param string $redirect + * @param string|null $provider + * @param bool $personalAccess + * @param bool $password + * @param bool $confidential * @return \Laravel\Passport\Client */ public function create($userId, $name, $redirect, $provider = null, $personalAccess = false, $password = false, $confidential = true) @@ -147,9 +148,10 @@ public function createPersonalAccessClient($userId, $name, $redirect) /** * Store a new password grant client. * - * @param int $userId - * @param string $name - * @param string $redirect + * @param int $userId + * @param string $name + * @param string $redirect + * @param string|null $provider * @return \Laravel\Passport\Client */ public function createPasswordGrantClient($userId, $name, $redirect, $provider = null) From edd3713991343d175647e6f4e2de026772c68ece Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Fri, 17 Apr 2020 04:19:27 -0400 Subject: [PATCH 098/353] Default provider to users if exists otherwise null --- src/Console/ClientCommand.php | 2 +- src/Console/InstallCommand.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 8771d1616..5f46f9f0f 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -89,7 +89,7 @@ protected function createPasswordClient(ClientRepository $clients) $provider = $this->option('provider') ?: $this->choice( 'What provider should be used?', $providers, - $providers[0] + in_array('users', $providers) ? 'users' : null ); $client = $clients->createPasswordGrantClient( diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 9a40d2874..dda3cd8f5 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -29,8 +29,9 @@ class InstallCommand extends Command */ public function handle() { + $provider = in_array('users', array_keys(config('auth.providers'))) ? 'users' : null; $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); - $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => array_keys(config('auth.providers'))[0]]); + $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => $provider]); } } From ff788805a012bb35f7b17b9e37e5f84ad66240a9 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Fri, 17 Apr 2020 04:21:59 -0400 Subject: [PATCH 099/353] StyleCI suggestion Co-Authored-By: Dries Vints --- src/Guards/TokenGuard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 4ebd237f4..89f4c3865 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -101,7 +101,7 @@ protected function validateProvider(Request $request) */ public function user(Request $request) { - if (!$this->validateProvider($request)) { + if (! $this->validateProvider($request)) { return; } From 687b12a76aac92df22f294f2133930e6732140f5 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Fri, 17 Apr 2020 15:43:27 -0400 Subject: [PATCH 100/353] Check if client is set when validating --- src/Guards/TokenGuard.php | 2 +- tests/BridgeClientRepositoryTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 89f4c3865..0822a55a7 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -90,7 +90,7 @@ public function __construct(ResourceServer $server, */ protected function validateProvider(Request $request) { - return $this->provider == $this->client($request)->getProvider(); + return $this->client($request) && $this->client($request)->getProvider() == $this->provider; } /** diff --git a/tests/BridgeClientRepositoryTest.php b/tests/BridgeClientRepositoryTest.php index 94a014323..a2aa9ee2e 100644 --- a/tests/BridgeClientRepositoryTest.php +++ b/tests/BridgeClientRepositoryTest.php @@ -191,6 +191,8 @@ class BridgeClientRepositoryTestClientStub public $password_client = false; + public $provider = null; + public $grant_types; public function firstParty() From 339abf70d09c5501260db5259c7a265fd927b58d Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Sat, 18 Apr 2020 00:09:36 -0400 Subject: [PATCH 101/353] Fixed validation to fallback if provider is not defined --- src/Guards/TokenGuard.php | 9 ++++++++- tests/TokenGuardTest.php | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 0822a55a7..e15e97a5a 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -90,7 +90,14 @@ public function __construct(ResourceServer $server, */ protected function validateProvider(Request $request) { - return $this->client($request) && $this->client($request)->getProvider() == $this->provider; + $client = $this->client($request); + + // If not client provider is defined, fallback to old behavior. + if ($client && empty($client->getProvider())) { + return true; + } + + return $client && $this->provider == $client->getProvider(); } /** diff --git a/tests/TokenGuardTest.php b/tests/TokenGuardTest.php index 3940c9a84..62431b6f8 100644 --- a/tests/TokenGuardTest.php +++ b/tests/TokenGuardTest.php @@ -47,6 +47,7 @@ public function test_user_can_be_pulled_via_bearer_token() $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); $tokens->shouldReceive('find')->once()->with('token')->andReturn($token = m::mock()); $clients->shouldReceive('revoked')->with(1)->andReturn(false); + $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); $user = $guard->user($request); @@ -90,6 +91,10 @@ public function test_null_is_returned_if_no_user_is_found() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); $request = Request::create('/'); @@ -97,6 +102,7 @@ public function test_null_is_returned_if_no_user_is_found() $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(null); $this->assertNull($guard->user($request)); @@ -110,6 +116,10 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); $request = Request::create('/'); @@ -138,6 +148,10 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); $request = Request::create('/'); @@ -270,6 +284,10 @@ public function test_csrf_check_can_be_disabled() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); Passport::ignoreCsrfToken(); @@ -396,4 +414,8 @@ class TokenGuardTestUser class TokenGuardTestClient { + public function getProvider() + { + return null; + } } From 95eb3b354b0c571ffd46ee729c196c0abacc62c3 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Sat, 18 Apr 2020 00:12:57 -0400 Subject: [PATCH 102/353] StyleCI suggestion --- tests/TokenGuardTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TokenGuardTest.php b/tests/TokenGuardTest.php index 62431b6f8..a29f4a5a6 100644 --- a/tests/TokenGuardTest.php +++ b/tests/TokenGuardTest.php @@ -416,6 +416,5 @@ class TokenGuardTestClient { public function getProvider() { - return null; } } From e8b12f229b116c4b5332874c6f74ac32edf724c6 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Mon, 20 Apr 2020 11:00:35 -0400 Subject: [PATCH 103/353] DocBlocks and formatting --- src/Bridge/Client.php | 11 ++++++----- src/Client.php | 6 ++++-- src/ClientRepository.php | 22 +++++++++++----------- src/Console/InstallCommand.php | 1 + src/Guards/TokenGuard.php | 6 +++--- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index 9f2a05517..70539ac80 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -26,11 +26,12 @@ class Client implements ClientEntityInterface /** * Create a new client instance. * - * @param string $identifier - * @param string $name - * @param string $redirectUri - * @param bool $isConfidential - * @param string|null $provider + * @param string $identifier + * @param string $name + * @param string $redirectUri + * @param bool $isConfidential + * @param string|null $provider + * @return void */ public function __construct($identifier, $name, $redirectUri, $isConfidential = false, $provider = null) { diff --git a/src/Client.php b/src/Client.php index 7adca9993..219297f40 100644 --- a/src/Client.php +++ b/src/Client.php @@ -49,8 +49,10 @@ class Client extends Model */ public function user() { + $provider = $this->provider ?: config('auth.guards.api.provider'); + return $this->belongsTo( - config('auth.providers.'.$this->provider ?: config('auth.guards.api.provider').'.model') + config("auth.providers.$provider.model") ); } @@ -107,7 +109,7 @@ public function confidential() /** * Get the client's provider. * - * @return mixed + * @return \Illuminate\Contracts\Auth\UserProvider|null */ public function getProvider() { diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 8a825735b..119cb0812 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -101,13 +101,13 @@ public function personalAccessClient() /** * Store a new client. * - * @param int $userId - * @param string $name - * @param string $redirect - * @param string|null $provider - * @param bool $personalAccess - * @param bool $password - * @param bool $confidential + * @param int $userId + * @param string $name + * @param string $redirect + * @param string|null $provider + * @param bool $personalAccess + * @param bool $password + * @param bool $confidential * @return \Laravel\Passport\Client */ public function create($userId, $name, $redirect, $provider = null, $personalAccess = false, $password = false, $confidential = true) @@ -148,10 +148,10 @@ public function createPersonalAccessClient($userId, $name, $redirect) /** * Store a new password grant client. * - * @param int $userId - * @param string $name - * @param string $redirect - * @param string|null $provider + * @param int $userId + * @param string $name + * @param string $redirect + * @param string|null $provider * @return \Laravel\Passport\Client */ public function createPasswordGrantClient($userId, $name, $redirect, $provider = null) diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index dda3cd8f5..3498cb986 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -30,6 +30,7 @@ class InstallCommand extends Command public function handle() { $provider = in_array('users', array_keys(config('auth.providers'))) ? 'users' : null; + $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => $provider]); diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index e15e97a5a..e4091e65d 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -88,11 +88,11 @@ public function __construct(ResourceServer $server, * @param \Illuminate\Http\Request $request * @return bool */ - protected function validateProvider(Request $request) + protected function hasValidProvider(Request $request) { $client = $this->client($request); - // If not client provider is defined, fallback to old behavior. + // If no client provider is defined, fallback to old behavior. if ($client && empty($client->getProvider())) { return true; } @@ -108,7 +108,7 @@ protected function validateProvider(Request $request) */ public function user(Request $request) { - if (! $this->validateProvider($request)) { + if (! $this->hasValidProvider($request)) { return; } From 010b807bcb64038f97858b980ed5c97b4d15bf47 Mon Sep 17 00:00:00 2001 From: Predarg Kostic Date: Mon, 20 Apr 2020 20:41:56 +0200 Subject: [PATCH 104/353] Fix exception on deleted client auth --- src/Http/Middleware/CheckClientCredentials.php | 2 +- src/Http/Middleware/CheckClientCredentialsForAnyScope.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index a24959dbe..b666c2c57 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -17,7 +17,7 @@ class CheckClientCredentials extends CheckCredentials */ protected function validateCredentials($token) { - if (! $token || $token->client->firstParty()) { + if (! $token || ! $token->client || $token->client->firstParty()) { throw new AuthenticationException; } } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index e1f7b23ff..8576183d7 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -17,7 +17,7 @@ class CheckClientCredentialsForAnyScope extends CheckCredentials */ protected function validateCredentials($token) { - if (! $token || $token->client->firstParty()) { + if (! $token || ! $token->client || $token->client->firstParty()) { throw new AuthenticationException; } } From dd4b1d96eb1fe556a6eb2c55c942360364aa02c1 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 21 Apr 2020 21:24:59 +0200 Subject: [PATCH 105/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f558cc1..013d1c461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.4.3...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.4.4...8.x) + + +## [v8.4.4 (2020-04-21)](https://github.com/laravel/passport/compare/v8.4.3...v8.4.4) + +### Fixed +- Fix 500 Internal Server Error response ([#1222](https://github.com/laravel/passport/pull/1222)) ## [v8.4.3 (2020-03-31)](https://github.com/laravel/passport/compare/v8.4.2...v8.4.3) From 06f6cbd855caa76c07e566c48bdc389a3d7b6424 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Sun, 26 Apr 2020 23:39:22 -0400 Subject: [PATCH 106/353] Compare models directly on providers. --- src/Guards/TokenGuard.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index e4091e65d..28e547952 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -97,7 +97,8 @@ protected function hasValidProvider(Request $request) return true; } - return $client && $this->provider == $client->getProvider(); + // Determine if the client's provider and the request's provider have matching models. + return $client && $client->getProvider()->getModel() === $this->provider->getModel(); } /** @@ -108,10 +109,6 @@ protected function hasValidProvider(Request $request) */ public function user(Request $request) { - if (! $this->hasValidProvider($request)) { - return; - } - if ($request->bearerToken()) { return $this->authenticateViaBearerToken($request); } elseif ($request->cookie(Passport::cookie())) { @@ -154,6 +151,13 @@ protected function authenticateViaBearerToken($request) return; } + $client = $this->client($request); + + if ($client && $model = class_exists(config('auth.providers'.$this->client($request)->provider.'.model'))) { + $this->provider->setModel($model); + } + + // If the access token is valid we will retrieve the user according to the user ID // associated with the token. We will use the provider implementation which may // be used to retrieve users from Eloquent. Next, we'll be ready to continue. From 834f9a5384163b2e98af1ec9de8e6b0d6f3e4eea Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Sun, 26 Apr 2020 23:43:33 -0400 Subject: [PATCH 107/353] Cleaned up returns, removed redundant code --- src/Guards/TokenGuard.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 28e547952..895bf1acb 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -98,7 +98,7 @@ protected function hasValidProvider(Request $request) } // Determine if the client's provider and the request's provider have matching models. - return $client && $client->getProvider()->getModel() === $this->provider->getModel(); + return $client->getProvider()->getModel() === $this->provider->getModel(); } /** @@ -151,13 +151,6 @@ protected function authenticateViaBearerToken($request) return; } - $client = $this->client($request); - - if ($client && $model = class_exists(config('auth.providers'.$this->client($request)->provider.'.model'))) { - $this->provider->setModel($model); - } - - // If the access token is valid we will retrieve the user according to the user ID // associated with the token. We will use the provider implementation which may // be used to retrieve users from Eloquent. Next, we'll be ready to continue. From 7904a36f4001a1b308200bf0c0f123213c8e348e Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Sun, 26 Apr 2020 23:47:54 -0400 Subject: [PATCH 108/353] Call the validation... --- src/Guards/TokenGuard.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 895bf1acb..cb2634da3 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -98,7 +98,7 @@ protected function hasValidProvider(Request $request) } // Determine if the client's provider and the request's provider have matching models. - return $client->getProvider()->getModel() === $this->provider->getModel(); + return $client && $client->getProvider()->getModel() === $this->provider->getModel(); } /** @@ -109,6 +109,10 @@ protected function hasValidProvider(Request $request) */ public function user(Request $request) { + if (! $this->hasValidProvider($request)) { + return; + } + if ($request->bearerToken()) { return $this->authenticateViaBearerToken($request); } elseif ($request->cookie(Passport::cookie())) { From 10d09fe63bc582115e247d32a8fed5ceaca25b12 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 27 Apr 2020 10:23:05 +0200 Subject: [PATCH 109/353] Decorate UserProvider with custom class --- src/Client.php | 10 ---- src/Guards/TokenGuard.php | 24 ++++----- src/PassportServiceProvider.php | 2 +- src/PassportUserProvider.php | 86 +++++++++++++++++++++++++++++++++ tests/TokenGuardTest.php | 3 -- 5 files changed, 99 insertions(+), 26 deletions(-) create mode 100644 src/PassportUserProvider.php diff --git a/src/Client.php b/src/Client.php index 219297f40..22643638b 100644 --- a/src/Client.php +++ b/src/Client.php @@ -105,14 +105,4 @@ public function confidential() { return ! empty($this->secret); } - - /** - * Get the client's provider. - * - * @return \Illuminate\Contracts\Auth\UserProvider|null - */ - public function getProvider() - { - return $this->provider ? Auth::createUserProvider($this->provider) : null; - } } diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index cb2634da3..147b75b14 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -5,7 +5,6 @@ use Exception; use Firebase\JWT\JWT; use Illuminate\Container\Container; -use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Cookie\Middleware\EncryptCookies; @@ -16,6 +15,7 @@ use Laminas\Diactoros\UploadedFileFactory; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; +use Laravel\Passport\PassportUserProvider; use Laravel\Passport\TokenRepository; use Laravel\Passport\TransientToken; use League\OAuth2\Server\Exception\OAuthServerException; @@ -34,7 +34,7 @@ class TokenGuard /** * The user provider implementation. * - * @var \Illuminate\Contracts\Auth\UserProvider + * @var \Laravel\Passport\PassportUserProvider */ protected $provider; @@ -63,18 +63,19 @@ class TokenGuard * Create a new token guard instance. * * @param \League\OAuth2\Server\ResourceServer $server - * @param \Illuminate\Contracts\Auth\UserProvider $provider + * @param \Laravel\Passport\PassportUserProvider $provider * @param \Laravel\Passport\TokenRepository $tokens * @param \Laravel\Passport\ClientRepository $clients * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter * @return void */ - public function __construct(ResourceServer $server, - UserProvider $provider, - TokenRepository $tokens, - ClientRepository $clients, - Encrypter $encrypter) - { + public function __construct( + ResourceServer $server, + PassportUserProvider $provider, + TokenRepository $tokens, + ClientRepository $clients, + Encrypter $encrypter + ) { $this->server = $server; $this->tokens = $tokens; $this->clients = $clients; @@ -93,12 +94,11 @@ protected function hasValidProvider(Request $request) $client = $this->client($request); // If no client provider is defined, fallback to old behavior. - if ($client && empty($client->getProvider())) { + if ($client && ! is_null($client->provider)) { return true; } - // Determine if the client's provider and the request's provider have matching models. - return $client && $client->getProvider()->getModel() === $this->provider->getModel(); + return $client && $client->provider === $this->provider->getProviderName(); } /** diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 1f3bd4040..4f1b34dc5 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -276,7 +276,7 @@ protected function makeGuard(array $config) return new RequestGuard(function ($request) use ($config) { return (new TokenGuard( $this->app->make(ResourceServer::class), - Auth::createUserProvider($config['provider']), + new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']), $this->app->make(TokenRepository::class), $this->app->make(ClientRepository::class), $this->app->make('encrypter') diff --git a/src/PassportUserProvider.php b/src/PassportUserProvider.php new file mode 100644 index 000000000..ccde8dc38 --- /dev/null +++ b/src/PassportUserProvider.php @@ -0,0 +1,86 @@ +provider = $provider; + $this->providerName = $providerName; + } + + /** + * Get the UserProvider name. + * + * @return string + */ + public function getProviderName() + { + return $this->providerName; + } + + /** + * {@inheritDoc} + */ + public function retrieveById($identifier) + { + return $this->provider->retrieveById($identifier); + } + + /** + * {@inheritDoc} + */ + public function retrieveByToken($identifier, $token) + { + return $this->provider->retrieveByToken($identifier, $token); + } + + /** + * {@inheritDoc} + */ + public function updateRememberToken(Authenticatable $user, $token) + { + $this->provider->updateRememberToken($user, $token); + } + + /** + * {@inheritDoc} + */ + public function retrieveByCredentials(array $credentials) + { + return $this->provider->retrieveByCredentials($credentials); + } + + /** + * {@inheritDoc} + */ + public function validateCredentials(Authenticatable $user, array $credentials) + { + return $this->provider->validateCredentials($user, $credentials); + } +} diff --git a/tests/TokenGuardTest.php b/tests/TokenGuardTest.php index a29f4a5a6..9d8f9327d 100644 --- a/tests/TokenGuardTest.php +++ b/tests/TokenGuardTest.php @@ -414,7 +414,4 @@ class TokenGuardTestUser class TokenGuardTestClient { - public function getProvider() - { - } } From 7569525d6da44402148359cc0329d2397f9d3195 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Mon, 27 Apr 2020 06:14:05 -0400 Subject: [PATCH 110/353] Fixed tests --- tests/TokenGuardTest.php | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tests/TokenGuardTest.php b/tests/TokenGuardTest.php index 9d8f9327d..2b679a558 100644 --- a/tests/TokenGuardTest.php +++ b/tests/TokenGuardTest.php @@ -5,7 +5,6 @@ use Carbon\Carbon; use Firebase\JWT\JWT; use Illuminate\Container\Container; -use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Encryption\Encrypter; use Illuminate\Http\Request; @@ -13,6 +12,7 @@ use Laravel\Passport\Guards\TokenGuard; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Passport; +use Laravel\Passport\PassportUserProvider; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; @@ -30,7 +30,7 @@ protected function tearDown(): void public function test_user_can_be_pulled_via_bearer_token() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -45,6 +45,7 @@ public function test_user_can_be_pulled_via_bearer_token() $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); $tokens->shouldReceive('find')->once()->with('token')->andReturn($token = m::mock()); $clients->shouldReceive('revoked')->with(1)->andReturn(false); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); @@ -63,7 +64,7 @@ public function test_no_user_is_returned_when_oauth_throws_exception() $handler->shouldReceive('report')->once()->with(m::type(OAuthServerException::class)); $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -86,7 +87,7 @@ public function test_no_user_is_returned_when_oauth_throws_exception() public function test_null_is_returned_if_no_user_is_found() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -104,6 +105,7 @@ public function test_null_is_returned_if_no_user_is_found() $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(null); + $userProvider->shouldReceive('getProviderName')->andReturn(null); $this->assertNull($guard->user($request)); } @@ -111,7 +113,7 @@ public function test_null_is_returned_if_no_user_is_found() public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -134,6 +136,7 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); $user = $guard->user($request); @@ -143,7 +146,7 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -166,6 +169,7 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); $user = $guard->user($request); @@ -175,7 +179,7 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( public function test_cookie_xsrf_is_verified_against_csrf_token_header() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -201,7 +205,7 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() public function test_cookie_xsrf_is_verified_against_xsrf_token_header() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -227,7 +231,7 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -253,7 +257,7 @@ public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() public function test_expired_cookies_may_not_be_used() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -279,7 +283,7 @@ public function test_expired_cookies_may_not_be_used() public function test_csrf_check_can_be_disabled() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -302,6 +306,7 @@ public function test_csrf_check_can_be_disabled() ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); $user = $guard->user($request); @@ -311,7 +316,7 @@ public function test_csrf_check_can_be_disabled() public function test_client_can_be_pulled_via_bearer_token() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -338,7 +343,7 @@ public function test_no_client_is_returned_when_oauth_throws_exception() $handler->shouldReceive('report')->once()->with(m::type(OAuthServerException::class)); $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -361,7 +366,7 @@ public function test_no_client_is_returned_when_oauth_throws_exception() public function test_null_is_returned_if_no_client_is_found() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); @@ -381,7 +386,7 @@ public function test_null_is_returned_if_no_client_is_found() public function test_clients_may_be_retrieved_from_cookies() { $resourceServer = m::mock(ResourceServer::class); - $userProvider = m::mock(UserProvider::class); + $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); @@ -414,4 +419,5 @@ class TokenGuardTestUser class TokenGuardTestClient { + public $provider; } From 3e46d5918c871adda54842bc359fcf42d7550856 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Mon, 27 Apr 2020 06:19:37 -0400 Subject: [PATCH 111/353] StyleCI + validation tweak --- src/Client.php | 1 - src/Guards/TokenGuard.php | 2 +- src/PassportUserProvider.php | 10 +++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Client.php b/src/Client.php index 22643638b..0039115d8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -3,7 +3,6 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Facades\Auth; class Client extends Model { diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 147b75b14..b81b13fcf 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -94,7 +94,7 @@ protected function hasValidProvider(Request $request) $client = $this->client($request); // If no client provider is defined, fallback to old behavior. - if ($client && ! is_null($client->provider)) { + if ($client && ! $client->provider) { return true; } diff --git a/src/PassportUserProvider.php b/src/PassportUserProvider.php index ccde8dc38..c62768d6c 100644 --- a/src/PassportUserProvider.php +++ b/src/PassportUserProvider.php @@ -45,7 +45,7 @@ public function getProviderName() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function retrieveById($identifier) { @@ -53,7 +53,7 @@ public function retrieveById($identifier) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function retrieveByToken($identifier, $token) { @@ -61,7 +61,7 @@ public function retrieveByToken($identifier, $token) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function updateRememberToken(Authenticatable $user, $token) { @@ -69,7 +69,7 @@ public function updateRememberToken(Authenticatable $user, $token) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function retrieveByCredentials(array $credentials) { @@ -77,7 +77,7 @@ public function retrieveByCredentials(array $credentials) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function validateCredentials(Authenticatable $user, array $credentials) { From e52ceba1d3e9791d387935c2cd57e3eb7be10cee Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 28 Apr 2020 15:14:30 -0500 Subject: [PATCH 112/353] Update Client.php --- src/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index 0039115d8..6952d5783 100644 --- a/src/Client.php +++ b/src/Client.php @@ -51,7 +51,7 @@ public function user() $provider = $this->provider ?: config('auth.guards.api.provider'); return $this->belongsTo( - config("auth.providers.$provider.model") + config("auth.providers.{$provider}.model") ); } From cdc37f06b592e4349fcf4c473e2c6b2ef91c5abc Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 28 Apr 2020 16:06:28 -0500 Subject: [PATCH 113/353] formatting --- src/Bridge/ClientRepository.php | 6 +++++- src/ClientRepository.php | 2 +- src/Console/ClientCommand.php | 4 ++-- src/Guards/TokenGuard.php | 1 - src/PassportUserProvider.php | 24 ++++++++++++------------ 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index e9fb4b0d0..35168731e 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -37,7 +37,11 @@ public function getClientEntity($clientIdentifier) } return new Client( - $clientIdentifier, $record->name, $record->redirect, $record->confidential(), $record->provider + $clientIdentifier, + $record->name, + $record->redirect, + $record->confidential(), + $record->provider ); } diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 119cb0812..e04dfc0d8 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -116,8 +116,8 @@ public function create($userId, $name, $redirect, $provider = null, $personalAcc 'user_id' => $userId, 'name' => $name, 'secret' => ($confidential || $personalAccess) ? Str::random(40) : null, - 'redirect' => $redirect, 'provider' => $provider, + 'redirect' => $redirect, 'personal_access_client' => $personalAccess, 'password_client' => $password, 'revoked' => false, diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 5f46f9f0f..a312a401e 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -18,7 +18,7 @@ class ClientCommand extends Command {--password : Create a password grant client} {--client : Create a client credentials grant client} {--name= : The name of the client} - {--provider= : The name of the provider} + {--provider= : The name of the user provider} {--redirect_uri= : The URI to redirect to after authorization } {--user_id= : The user ID the client should be assigned to } {--public : Create a public client (Auth code grant type only) }'; @@ -87,7 +87,7 @@ protected function createPasswordClient(ClientRepository $clients) $providers = array_keys(config('auth.providers')); $provider = $this->option('provider') ?: $this->choice( - 'What provider should be used?', + 'Which user provider should this client use to retrieve users?', $providers, in_array('users', $providers) ? 'users' : null ); diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index b81b13fcf..f30468310 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -93,7 +93,6 @@ protected function hasValidProvider(Request $request) { $client = $this->client($request); - // If no client provider is defined, fallback to old behavior. if ($client && ! $client->provider) { return true; } diff --git a/src/PassportUserProvider.php b/src/PassportUserProvider.php index c62768d6c..b94d82fa0 100644 --- a/src/PassportUserProvider.php +++ b/src/PassportUserProvider.php @@ -8,14 +8,14 @@ class PassportUserProvider implements UserProvider { /** - * The Application UserProvider instance. + * The user provider instance. * * @var \Illuminate\Contracts\Auth\UserProvider */ protected $provider; /** - * The Application UserProvider name. + * The user provider name. * * @var string */ @@ -34,16 +34,6 @@ public function __construct(UserProvider $provider, $providerName) $this->providerName = $providerName; } - /** - * Get the UserProvider name. - * - * @return string - */ - public function getProviderName() - { - return $this->providerName; - } - /** * {@inheritdoc} */ @@ -83,4 +73,14 @@ public function validateCredentials(Authenticatable $user, array $credentials) { return $this->provider->validateCredentials($user, $credentials); } + + /** + * Get the name of the user provider. + * + * @return string + */ + public function getProviderName() + { + return $this->providerName; + } } From 6896a17f6db29ae4f928e2bbc350bd30e8ae5014 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 4 May 2020 10:58:12 -0500 Subject: [PATCH 114/353] [8.x] Automatic configuration of client uuids (#1231) Automatic configuration of client UUIDs via passport:install --uuids --- config/passport.php | 13 +++++++++ src/Client.php | 37 +++++++++++++++++++++++++ src/Console/InstallCommand.php | 49 +++++++++++++++++++++++++++++++++ src/Passport.php | 28 +++++++++++++++++++ src/PassportServiceProvider.php | 4 ++- 5 files changed, 130 insertions(+), 1 deletion(-) diff --git a/config/passport.php b/config/passport.php index a4565f372..95a48923d 100644 --- a/config/passport.php +++ b/config/passport.php @@ -17,4 +17,17 @@ 'public_key' => env('PASSPORT_PUBLIC_KEY'), + /* + |-------------------------------------------------------------------------- + | Client UUIDs + |-------------------------------------------------------------------------- + | + | By default, Passport uses auto-incrementing primary keys when assigning + | IDs to clients. However, if Passport is installed using the provided + | --uuids switch, this will be set to "true" and UUIDs will be used. + | + */ + + 'client_uuids' => false, + ]; diff --git a/src/Client.php b/src/Client.php index 51b2b7013..baa92acc3 100644 --- a/src/Client.php +++ b/src/Client.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Str; class Client extends Model { @@ -41,6 +42,22 @@ class Client extends Model 'revoked' => 'bool', ]; + /** + * Bootstrap the model and its traits. + * + * @return void + */ + public static function boot() + { + parent::boot(); + + static::creating(function ($model) { + if (config('passport.client_uuids')) { + $model->{$model->getKeyName()} = $model->{$model->getKeyName()} ?: (string) Str::orderedUuid(); + } + }); + } + /** * Get the user that the client belongs to. * @@ -102,4 +119,24 @@ public function confidential() { return ! empty($this->secret); } + + /** + * Get the auto-incrementing key type. + * + * @return string + */ + public function getKeyType() + { + return Passport::clientUuids() ? 'string' : $this->keyType; + } + + /** + * Get the value indicating whether the IDs are incrementing. + * + * @return bool + */ + public function getIncrementing() + { + return Passport::clientUuids() ? false : $this->incrementing; + } } diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 89b80440d..e8eb2f588 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Console; use Illuminate\Console\Command; +use Laravel\Passport\Passport; class InstallCommand extends Command { @@ -12,6 +13,7 @@ class InstallCommand extends Command * @var string */ protected $signature = 'passport:install + {--uuids : Use UUIDs for all client IDs} {--force : Overwrite keys they already exist} {--length=4096 : The length of the private key}'; @@ -30,7 +32,54 @@ class InstallCommand extends Command public function handle() { $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); + + if ($this->option('uuids')) { + $this->configureUuids(); + } + $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client']); } + + /** + * Configure Passport for client UUIDs. + * + * @return void + */ + protected function configureUuids() + { + $this->call('vendor:publish', ['--tag' => 'passport-config']); + $this->call('vendor:publish', ['--tag' => 'passport-migrations']); + + config(['passport.client_uuids' => true]); + Passport::setClientUuids(true); + + $this->replaceInFile(config_path('passport.php'), 'false', 'true'); + $this->replaceInFile(database_path('migrations/2016_06_01_000001_create_oauth_auth_codes_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + $this->replaceInFile(database_path('migrations/2016_06_01_000002_create_oauth_access_tokens_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + $this->replaceInFile(database_path('migrations/2016_06_01_000004_create_oauth_clients_table.php'), '$table->bigIncrements(\'id\');', '$table->uuid(\'id\')->primary();'); + $this->replaceInFile(database_path('migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + + if ($this->confirm('In order to finish configuring client UUIDs, we need to rebuild the Passport database tables. Would you like to rollback and re-run your last migration?')) { + $this->call('migrate:rollback'); + $this->call('migrate'); + $this->line(''); + } + } + + /** + * Replace a given string in a given file. + * + * @param string $path + * @param string $search + * @param string $replace + * @return void + */ + protected function replaceInFile($path, $search, $replace) + { + file_put_contents( + $path, + str_replace($search, $replace, file_get_contents($path)) + ); + } } diff --git a/src/Passport.php b/src/Passport.php index 992f4333b..f00d55e01 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -112,6 +112,13 @@ class Passport */ public static $clientModel = 'Laravel\Passport\Client'; + /** + * Indicates if client's are identified by UUIDs. + * + * @var bool + */ + public static $clientUuids = false; + /** * The personal access client model class name. * @@ -534,6 +541,27 @@ public static function client() return new static::$clientModel; } + /** + * Determine if clients are identified using UUIDs. + * + * @return bool + */ + public static function clientUuids() + { + return static::$clientUuids; + } + + /** + * Specify if clients are identified using UUIDs. + * + * @param bool $value + * @return void + */ + public static function setClientUuids($value) + { + static::$clientUuids = $value; + } + /** * Set the personal access client model class name. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 1f3bd4040..b4f649935 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -75,7 +75,7 @@ public function boot() */ protected function registerMigrations() { - if (Passport::$runsMigrations) { + if (Passport::$runsMigrations && ! config('passport.client_uuids')) { return $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); } } @@ -89,6 +89,8 @@ public function register() { $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); + Passport::setClientUuids($this->app->make(Config::class)->get('passport.client_uuids', false)); + $this->registerAuthorizationServer(); $this->registerResourceServer(); $this->registerGuard(); From 6affa6ed600c5f8909385fbae7cf6f8af3db2d39 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:25:53 +0200 Subject: [PATCH 115/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 013d1c461..47a8b82d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.4.4...8.x) +## [Unreleased](https://github.com/laravel/passport/compare/v8.5.0...8.x) + + +## [v8.5.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) + +### Added +- Automatic configuration of client UUIDs ([#1231](https://github.com/laravel/passport/pull/1231)) ## [v8.4.4 (2020-04-21)](https://github.com/laravel/passport/compare/v8.4.3...v8.4.4) From 933241b190097e0ddf13a3a52d17ad31de3d54d0 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:32:45 +0200 Subject: [PATCH 116/353] Remove deprecated functionality (#1235) --- src/Passport.php | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index b6a335d4d..a7f08282f 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -19,20 +19,6 @@ class Passport */ public static $implicitGrantEnabled = false; - /** - * Indicates if Passport should revoke existing tokens when issuing a new one. - * - * @var bool - */ - public static $revokeOtherTokens = false; - - /** - * Indicates if Passport should prune revoked tokens. - * - * @var bool - */ - public static $pruneRevokedTokens = false; - /** * The personal access token client ID. * @@ -203,30 +189,6 @@ public static function routes($callback = null, array $options = []) }); } - /** - * Instruct Passport to revoke other tokens when a new one is issued. - * - * @deprecated since 1.0. Listen to Passport events on token creation instead. - * - * @return static - */ - public static function revokeOtherTokens() - { - return new static; - } - - /** - * Instruct Passport to keep revoked tokens pruned. - * - * @deprecated since 1.0. Listen to Passport events on token creation instead. - * - * @return static - */ - public static function pruneRevokedTokens() - { - return new static; - } - /** * Set the client ID that should be used to issue personal access tokens. * From 1d508bbe745b089994ec468666be560708fed11d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:49:05 +0200 Subject: [PATCH 117/353] Update CHANGELOG.md --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63792e882..08b57a8c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,21 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v8.5.0...master) +## [Unreleased](https://github.com/laravel/passport/compare/v9.0.0...9.x) + + +## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) + +### Added +- Allow client credentials secret to be hashed ([#1145](https://github.com/laravel/passport/pull/1145), [ccbcfeb](https://github.com/laravel/passport/commit/ccbcfeb5301e8f757395ba0e43980615acf4385e), [1c40ae0](https://github.com/laravel/passport/commit/1c40ae07503aeb23173d48f3a6e5757cafcfd71b)) +- Initial support for multiple providers ([#1220](https://github.com/laravel/passport/pull/1220)) + +### Changed +- Client credentials middleware should allow any valid client ([#1132](https://github.com/laravel/passport/pull/1132)) +- Switch from `getKey()` to `getAuthIdentifier()` to match Laravel core ([#1134](https://github.com/laravel/passport/pull/1134)) +- Use Hasher interface instead of HashManager ([#1157](https://github.com/laravel/passport/pull/1157)) + +### Removed +- Remove deprecated functionality ([#1235](https://github.com/laravel/passport/pull/1235)) ## [v8.5.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) From d538b53403086788568b24d10a88b20332cb2b07 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:50:46 +0200 Subject: [PATCH 118/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b57a8c4..f599483ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.0.0...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.0.0...master) ## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) From 9687b554fd9341f42b552de1bd38ce17d18c9698 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:50:58 +0200 Subject: [PATCH 119/353] Update branch-alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 359197e76..21d7fa235 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ }, "extra": { "branch-alias": { - "dev-master": "9.x-dev" + "dev-master": "10.x-dev" }, "laravel": { "providers": [ From a8ce2011b204ce9803b66b5a1128c33289489b63 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:55:39 +0200 Subject: [PATCH 120/353] Drop support for old JWT versions --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 359197e76..8103328b4 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require": { "php": "^7.2", "ext-json": "*", - "firebase/php-jwt": "^3.0|^4.0|^5.0", + "firebase/php-jwt": "^5.0", "guzzlehttp/guzzle": "^6.0", "illuminate/auth": "^6.0|^7.0", "illuminate/console": "^6.0|^7.0", From 8a63623e0b177a86b2266d4b52391ea12e0c2067 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 16:58:37 +0200 Subject: [PATCH 121/353] Bump league server dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 359197e76..1a99c6f96 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "illuminate/http": "^6.0|^7.0", "illuminate/support": "^6.0|^7.0", "laminas/laminas-diactoros": "^2.2", - "league/oauth2-server": "^8.0", + "league/oauth2-server": "^8.1", "nyholm/psr7": "^1.0", "phpseclib/phpseclib": "^2.0", "symfony/psr-http-message-bridge": "^2.0" From 69ccc344ae7bb5fd24e503bbb1528724eec4544f Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 17:19:43 +0200 Subject: [PATCH 122/353] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b57a8c4..e35a41e3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,11 @@ - Client credentials middleware should allow any valid client ([#1132](https://github.com/laravel/passport/pull/1132)) - Switch from `getKey()` to `getAuthIdentifier()` to match Laravel core ([#1134](https://github.com/laravel/passport/pull/1134)) - Use Hasher interface instead of HashManager ([#1157](https://github.com/laravel/passport/pull/1157)) +- Bump league server dependency ([#1237](https://github.com/laravel/passport/pull/1237)) ### Removed - Remove deprecated functionality ([#1235](https://github.com/laravel/passport/pull/1235)) +- Drop support for old JWT versions ([#1236](https://github.com/laravel/passport/pull/1236)) ## [v8.5.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) From 7a397176163994d4a74dc16b34c0cf29c7712af2 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 21:26:53 +0200 Subject: [PATCH 123/353] [9.x] Implement passport:hash command (#1238) * Implement passport:hash command * Skip records which are already hashed * Fix client command when hashing secrets * Use password_get_info * Update HashCommand.php Co-authored-by: Taylor Otwell --- src/Console/ClientCommand.php | 2 +- src/Console/HashCommand.php | 55 +++++++++++++++++++++++++++++++++ src/PassportServiceProvider.php | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/Console/HashCommand.php diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index a312a401e..f51a6b08f 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -162,6 +162,6 @@ protected function createAuthCodeClient(ClientRepository $clients) protected function outputClientDetails(Client $client) { $this->line('Client ID: '.$client->id); - $this->line('Client secret: '.$client->secret); + $this->line('Client secret: '.$client->plainSecret); } } diff --git a/src/Console/HashCommand.php b/src/Console/HashCommand.php new file mode 100644 index 000000000..69f83e9aa --- /dev/null +++ b/src/Console/HashCommand.php @@ -0,0 +1,55 @@ +warn("Please enable client hashing yet in your AppServiceProvider before continuning."); + + return; + } + + if ($this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) { + $model = Passport::clientModel(); + + foreach ((new $model)->whereNotNull('secret')->cursor() as $client) { + if (password_get_info($client->secret)['algo'] === PASSWORD_BCRYPT) { + continue; + } + + $client->timestamps = false; + + $client->forceFill([ + 'secret' => password_hash($client->secret, PASSWORD_BCRYPT), + ])->save(); + } + + $this->info('All client secrets were successfully hashed.'); + } + } +} diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 02cf5a389..44900b2d4 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -62,6 +62,7 @@ public function boot() $this->commands([ Console\InstallCommand::class, Console\ClientCommand::class, + Console\HashCommand::class, Console\KeysCommand::class, Console\PurgeCommand::class, ]); From b9764582d06dd2327eb4d1d267c4dfe7861ceb5a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 5 May 2020 14:27:11 -0500 Subject: [PATCH 124/353] Apply fixes from StyleCI (#1242) --- src/Console/HashCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/HashCommand.php b/src/Console/HashCommand.php index 69f83e9aa..0831e0d16 100644 --- a/src/Console/HashCommand.php +++ b/src/Console/HashCommand.php @@ -29,7 +29,7 @@ class HashCommand extends Command public function handle() { if (! Passport::$hashesClientSecrets) { - $this->warn("Please enable client hashing yet in your AppServiceProvider before continuning."); + $this->warn('Please enable client hashing yet in your AppServiceProvider before continuning.'); return; } From 1176eb516c0501435862851a48adece9ca6fdcb4 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 21:35:31 +0200 Subject: [PATCH 125/353] [9.x] Update UPGRADE.md (#1240) * Update UPGRADE.md * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 7df72a606..7030930fa 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,48 @@ # Upgrade Guide +## Upgrading To 9.0 From 8.0 + +### Support For Multiple Guards + +PR: https://github.com/laravel/passport/pull/1220 + +Passport now has support for multiple guard user providers. Because of this change, you must add a `provider` column to the `oauth_clients` database table: + + Schema::table('oauth_clients', function (Blueprint $table) { + $table->string('provider')->after('secret')->nullable(); + }); + +### Client Credentials Secret Hashing + +PR: https://github.com/laravel/passport/pull/1145 + +Client secrets may now be stored using a SHA-256 hash. However, before enabling this functionality, please consider the following. First, there is no way to reverse the hashing process once you have migrated your existing tokens. Secondly, when hashing client secrets, you will only have one opportunity to display the plain-text value to the user before it is hashed and stored in the database. + +You may enable client secret hashing by calling the `Passport::hashClientSecrets()` method within the `boot` method of your `AppServiceProvider`. For convenience, we've included a new Artisan command which you can run to hash all existing client secrets: + + php artisan passport:hash + +**Again, please be aware that running this command cannot be undone. For extra precaution, you may wish to create a backup of your database before running the command.** + +### Client Credentials Middleware Changes + +PR: https://github.com/laravel/passport/pull/1132 + +[After a lengthy debate](https://github.com/laravel/passport/issues/1125), it was decided to revert the change made [in a previous PR](https://github.com/laravel/passport/pull/1040) that introduced an exception when the client credentials middleware was used to authenticate first party clients. + +### Switch From `getKey` To `getAuthIdentifier` + +PR: https://github.com/laravel/passport/pull/1134 + +Internally, Passport will now use the `getAuthIdentifier` method to determine a model's primary key. This is consistent with the framework and Laravel's first party libraries. + +### Remove Deprecated Functionality + +PR: https://github.com/laravel/passport/pull/1235 + +The deprecated `revokeOtherTokens` and `pruneRevokedTokens` methods and the `revokeOtherTokens` and `pruneRevokedTokens` properties were removed from the `Passport` object. + + ## Upgrading To 8.0 From 7.0 ### Minimum & Upgraded Versions From a9043df2aa2a7ee8d2350269f179576867d5f2ec Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 5 May 2020 14:41:02 -0500 Subject: [PATCH 126/353] fix hashing name --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 7030930fa..63e955571 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -16,7 +16,7 @@ Passport now has support for multiple guard user providers. Because of this chan PR: https://github.com/laravel/passport/pull/1145 -Client secrets may now be stored using a SHA-256 hash. However, before enabling this functionality, please consider the following. First, there is no way to reverse the hashing process once you have migrated your existing tokens. Secondly, when hashing client secrets, you will only have one opportunity to display the plain-text value to the user before it is hashed and stored in the database. +Client secrets may now be stored using a Bcrypt hash. However, before enabling this functionality, please consider the following. First, there is no way to reverse the hashing process once you have migrated your existing tokens. Secondly, when hashing client secrets, you will only have one opportunity to display the plain-text value to the user before it is hashed and stored in the database. You may enable client secret hashing by calling the `Passport::hashClientSecrets()` method within the `boot` method of your `AppServiceProvider`. For convenience, we've included a new Artisan command which you can run to hash all existing client secrets: From 683becd29508ca4a26451715cc2c393d39a7a1ec Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 21:44:02 +0200 Subject: [PATCH 127/353] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e35a41e3d..af45dd64e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Added - Allow client credentials secret to be hashed ([#1145](https://github.com/laravel/passport/pull/1145), [ccbcfeb](https://github.com/laravel/passport/commit/ccbcfeb5301e8f757395ba0e43980615acf4385e), [1c40ae0](https://github.com/laravel/passport/commit/1c40ae07503aeb23173d48f3a6e5757cafcfd71b)) +- Implement `passport:hash` command ([#1238](https://github.com/laravel/passport/pull/1238)) - Initial support for multiple providers ([#1220](https://github.com/laravel/passport/pull/1220)) ### Changed From 7183f2448c160650f9fa60937eb22b0f2bdb54d6 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 5 May 2020 21:46:08 +0200 Subject: [PATCH 128/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af45dd64e..d4adf1bf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## [Unreleased](https://github.com/laravel/passport/compare/v9.0.0...9.x) -## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) +## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.5.0...v9.0.0) ### Added - Allow client credentials secret to be hashed ([#1145](https://github.com/laravel/passport/pull/1145), [ccbcfeb](https://github.com/laravel/passport/commit/ccbcfeb5301e8f757395ba0e43980615acf4385e), [1c40ae0](https://github.com/laravel/passport/commit/1c40ae07503aeb23173d48f3a6e5757cafcfd71b)) From 586fc5a260e923e1dd7028d9c53a94ceb47c52dc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 6 May 2020 17:45:45 +0200 Subject: [PATCH 129/353] Fix displaying secret in Vue component (#1244) --- resources/js/components/Clients.vue | 4 ++-- src/Http/Controllers/ClientController.php | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/resources/js/components/Clients.vue b/resources/js/components/Clients.vue index 6bf4f4c3e..708a3e2b3 100644 --- a/resources/js/components/Clients.vue +++ b/resources/js/components/Clients.vue @@ -50,7 +50,7 @@ - {{ client.secret }} + {{ client.secret ? client.secret : '-' }} @@ -337,7 +337,7 @@ axios[method](uri, form) .then(response => { - this.getClients(); + this.clients.push(response.data); form.name = ''; form.redirect = ''; diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 1ef17d852..8e418a414 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -7,6 +7,7 @@ use Illuminate\Http\Response; use Laravel\Passport\ClientRepository; use Laravel\Passport\Http\Rules\RedirectRule; +use Laravel\Passport\Passport; class ClientController { @@ -59,14 +60,20 @@ public function forUser(Request $request) { $userId = $request->user()->getAuthIdentifier(); - return $this->clients->activeForUser($userId)->makeVisible('secret'); + $clients = $this->clients->activeForUser($userId); + + if (Passport::$hashesClientSecrets) { + return $clients; + } + + return $clients->makeVisible('secret'); } /** * Store a new client. * * @param \Illuminate\Http\Request $request - * @return \Laravel\Passport\Client + * @return \Laravel\Passport\Client|array */ public function store(Request $request) { @@ -76,10 +83,16 @@ public function store(Request $request) 'confidential' => 'boolean', ])->validate(); - return $this->clients->create( + $client = $this->clients->create( $request->user()->getAuthIdentifier(), $request->name, $request->redirect, false, false, (bool) $request->input('confidential', true) - )->makeVisible('secret'); + ); + + if (Passport::$hashesClientSecrets) { + return ['secret' => $client->plainSecret] + $client->toArray(); + } + + return $client->makeVisible('secret'); } /** From 32e5a6a2c11a53676bb12e65bc2eed7963ab8405 Mon Sep 17 00:00:00 2001 From: Bill Riess Date: Wed, 6 May 2020 12:56:23 -0400 Subject: [PATCH 130/353] Moved provider check to bearer token only (#1246) --- src/Guards/TokenGuard.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index f30468310..e4e01d1c2 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -108,10 +108,6 @@ protected function hasValidProvider(Request $request) */ public function user(Request $request) { - if (! $this->hasValidProvider($request)) { - return; - } - if ($request->bearerToken()) { return $this->authenticateViaBearerToken($request); } elseif ($request->cookie(Passport::cookie())) { @@ -154,6 +150,10 @@ protected function authenticateViaBearerToken($request) return; } + if (! $this->hasValidProvider($request)) { + return; + } + // If the access token is valid we will retrieve the user according to the user ID // associated with the token. We will use the provider implementation which may // be used to retrieve users from Eloquent. Next, we'll be ready to continue. From aff9d0933737354d04df98cfc431fa20309be03a Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 6 May 2020 19:08:52 +0200 Subject: [PATCH 131/353] Fix create client call --- src/Http/Controllers/ClientController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 8e418a414..219973441 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -85,7 +85,7 @@ public function store(Request $request) $client = $this->clients->create( $request->user()->getAuthIdentifier(), $request->name, $request->redirect, - false, false, (bool) $request->input('confidential', true) + null, false, false, (bool) $request->input('confidential', true) ); if (Passport::$hashesClientSecrets) { From 25552e0bad280f5f5b778f54b8f5e895b18bf7e5 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 6 May 2020 19:11:56 +0200 Subject: [PATCH 132/353] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4adf1bf8..83fb97c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.0.0...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.0.1...9.x) + + +## [v9.0.1 (2020-05-06)](https://github.com/laravel/passport/compare/v9.0.0...v9.0.1) + +### Fixed +- Fix displaying secret in Vue component ([#1244](https://github.com/laravel/passport/pull/1244)) +- Moved provider check to bearer token only ([#1246](https://github.com/laravel/passport/pull/1246)) +- Fix create client call ([aff9d09](https://github.com/laravel/passport/commit/aff9d0933737354d04df98cfc431fa20309be03a)) ## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.5.0...v9.0.0) From a368f9e079b6c52a8c6aa17f7dce3d98c0a61102 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 6 May 2020 19:12:38 +0200 Subject: [PATCH 133/353] Fix tests --- tests/ClientControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ClientControllerTest.php b/tests/ClientControllerTest.php index f1faf89bb..72383206c 100644 --- a/tests/ClientControllerTest.php +++ b/tests/ClientControllerTest.php @@ -48,7 +48,7 @@ public function test_clients_can_be_stored() $clients->shouldReceive('create') ->once() - ->with(1, 'client name', 'http://localhost', false, false, true) + ->with(1, 'client name', 'http://localhost', null, false, false, true) ->andReturn($client = new Client); $redirectRule = m::mock(RedirectRule::class); @@ -86,7 +86,7 @@ public function test_public_clients_can_be_stored() $clients->shouldReceive('create') ->once() - ->with(1, 'client name', 'http://localhost', false, false, false) + ->with(1, 'client name', 'http://localhost', null, false, false, false) ->andReturn($client = new Client); $redirectRule = m::mock(RedirectRule::class); From e82a6d2731c34d4dbea3bf19ce6c363f3980358e Mon Sep 17 00:00:00 2001 From: Aaron Huisinga Date: Thu, 7 May 2020 16:10:18 -0500 Subject: [PATCH 134/353] Add force option to hash command (#1251) --- src/Console/HashCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Console/HashCommand.php b/src/Console/HashCommand.php index 0831e0d16..5c1d23393 100644 --- a/src/Console/HashCommand.php +++ b/src/Console/HashCommand.php @@ -12,7 +12,7 @@ class HashCommand extends Command * * @var string */ - protected $signature = 'passport:hash'; + protected $signature = 'passport:hash {--force : Force the operation to run without confirmation prompt}'; /** * The console command description. @@ -34,7 +34,7 @@ public function handle() return; } - if ($this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) { + if ($this->option('force') || $this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) { $model = Passport::clientModel(); foreach ((new $model)->whereNotNull('secret')->cursor() as $client) { From 08bf38969087997de027068a0ab76db45e09a638 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 11:16:02 +0200 Subject: [PATCH 135/353] Fix updating clients in Vue --- resources/js/components/Clients.vue | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/resources/js/components/Clients.vue b/resources/js/components/Clients.vue index 708a3e2b3..7a50deea8 100644 --- a/resources/js/components/Clients.vue +++ b/resources/js/components/Clients.vue @@ -303,8 +303,10 @@ */ store() { this.persistClient( - 'post', '/oauth/clients', - this.createForm, '#modal-create-client' + 'post', + '/oauth/clients', + this.createForm, + '#modal-create-client' ); }, @@ -324,8 +326,10 @@ */ update() { this.persistClient( - 'put', '/oauth/clients/' + this.editForm.id, - this.editForm, '#modal-edit-client' + 'put', + '/oauth/clients/' + this.editForm.id, + this.editForm, + '#modal-edit-client' ); }, @@ -337,7 +341,11 @@ axios[method](uri, form) .then(response => { - this.clients.push(response.data); + if (method === 'post') { + this.clients.push(response.data); + } else { + this.getClients(); + } form.name = ''; form.redirect = ''; From e46ebc5f58e45bb865e4a3fb6037b03f7836ffc8 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 13:50:30 +0200 Subject: [PATCH 136/353] Implement personal access client config --- UPGRADE.md | 16 ++++++++++++++++ config/passport.php | 16 ++++++++++++++++ src/Passport.php | 24 ++++++++++++++++++++++-- src/PersonalAccessTokenFactory.php | 4 +++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 63e955571..57a989bec 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -18,6 +18,22 @@ PR: https://github.com/laravel/passport/pull/1145 Client secrets may now be stored using a Bcrypt hash. However, before enabling this functionality, please consider the following. First, there is no way to reverse the hashing process once you have migrated your existing tokens. Secondly, when hashing client secrets, you will only have one opportunity to display the plain-text value to the user before it is hashed and stored in the database. +#### Personal Access Client + +Before you continue, there's a special case for personal access clients. You should set your personal access client ID and unhashed secret in your `.env` file: + + PASSPORT_PERSONAL_ACCESS_CLIENT_ID= + PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET= + +After this, you should set register them with the `Passport` instance by playing the following calls within the `boot` method of your `AppServiceProvider`: + + Passport::personalAccessClientId(config('passport.personal_access_token.id')); + Passport::personalAccessClientSecret(config('passport.personal_access_token.secret')); + +Make sure to do this before hashing your secrets using the step below, otherwise they'll be lost forever. + +#### Hashing Existing Secrets + You may enable client secret hashing by calling the `Passport::hashClientSecrets()` method within the `boot` method of your `AppServiceProvider`. For convenience, we've included a new Artisan command which you can run to hash all existing client secrets: php artisan passport:hash diff --git a/config/passport.php b/config/passport.php index 95a48923d..b07bdbcad 100644 --- a/config/passport.php +++ b/config/passport.php @@ -30,4 +30,20 @@ 'client_uuids' => false, + /* + |-------------------------------------------------------------------------- + | Personal Access Client + |-------------------------------------------------------------------------- + | + | If you enable client hashing, you should set the personal access + | client id and secret in your config file. This way they will be + | used when you issue access tokens to your users. + | + */ + + 'personal_access_client' => [ + 'id' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_ID'), + 'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'), + ], + ]; diff --git a/src/Passport.php b/src/Passport.php index a7f08282f..ea347ec2b 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -22,10 +22,17 @@ class Passport /** * The personal access token client ID. * - * @var int + * @var int|string */ public static $personalAccessClientId; + /** + * The personal access token client secret. + * + * @var string + */ + public static $personalAccessClientSecret; + /** * The default scope. * @@ -192,7 +199,7 @@ public static function routes($callback = null, array $options = []) /** * Set the client ID that should be used to issue personal access tokens. * - * @param int $clientId + * @param int|string $clientId * @return static */ public static function personalAccessClientId($clientId) @@ -202,6 +209,19 @@ public static function personalAccessClientId($clientId) return new static; } + /** + * Set the client secret that should be used to issue personal access tokens. + * + * @param string $clientSecret + * @return static + */ + public static function personalAccessClientSecret($clientSecret) + { + static::$personalAccessClientSecret = $clientSecret; + + return new static; + } + /** * Set the default scope(s). Multiple scopes may be an array or specified delimited by spaces. * diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 2ab665c6b..27c558d79 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -93,10 +93,12 @@ public function make($userId, $name, array $scopes = []) */ protected function createRequest($client, $userId, array $scopes) { + $secret = Passport::$hashesClientSecrets ? Passport::$personalAccessClientSecret : $client->secret; + return (new ServerRequest)->withParsedBody([ 'grant_type' => 'personal_access', 'client_id' => $client->id, - 'client_secret' => $client->secret, + 'client_secret' => $secret, 'user_id' => $userId, 'scope' => implode(' ', $scopes), ]); From 03e4e516b6a0986e0557b11dd96ea2b180b1c3dd Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 8 May 2020 08:47:23 -0500 Subject: [PATCH 137/353] formatting --- UPGRADE.md | 12 ++++++------ config/passport.php | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 57a989bec..334f257e8 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -18,19 +18,19 @@ PR: https://github.com/laravel/passport/pull/1145 Client secrets may now be stored using a Bcrypt hash. However, before enabling this functionality, please consider the following. First, there is no way to reverse the hashing process once you have migrated your existing tokens. Secondly, when hashing client secrets, you will only have one opportunity to display the plain-text value to the user before it is hashed and stored in the database. -#### Personal Access Client +#### Personal Access Clients -Before you continue, there's a special case for personal access clients. You should set your personal access client ID and unhashed secret in your `.env` file: +Before you continue, you should set your personal access client ID and unhashed secret in your `.env` file: - PASSPORT_PERSONAL_ACCESS_CLIENT_ID= - PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET= + PASSPORT_PERSONAL_ACCESS_CLIENT_ID=client-id-value + PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET=unhashed-client-secret-value -After this, you should set register them with the `Passport` instance by playing the following calls within the `boot` method of your `AppServiceProvider`: +Next, you should set register these values by placing the following calls within the `boot` method of your `AppServiceProvider`: Passport::personalAccessClientId(config('passport.personal_access_token.id')); Passport::personalAccessClientSecret(config('passport.personal_access_token.secret')); -Make sure to do this before hashing your secrets using the step below, otherwise they'll be lost forever. +> Make sure you follow the instructions above before hashing your secrets. Otherwise, irreversible data loss may occur. #### Hashing Existing Secrets diff --git a/config/passport.php b/config/passport.php index b07bdbcad..79c59acb1 100644 --- a/config/passport.php +++ b/config/passport.php @@ -35,9 +35,9 @@ | Personal Access Client |-------------------------------------------------------------------------- | - | If you enable client hashing, you should set the personal access - | client id and secret in your config file. This way they will be - | used when you issue access tokens to your users. + | If you enable client hashing, you should set the personal access client + | ID and unhashed secret within your environment file. The values will + | get used while issuing fresh personal access tokens to your users. | */ From 07b5f1140dcc494aa366da81140a46b9b3636d45 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 15:49:40 +0200 Subject: [PATCH 138/353] [9.x] Warn about one-time-hashed-secret (#1259) * Warn about one-time-hashed-secret * Update ClientCommand.php Co-authored-by: Taylor Otwell --- src/Console/ClientCommand.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index f51a6b08f..f645cf613 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -5,6 +5,7 @@ use Illuminate\Console\Command; use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Passport; class ClientCommand extends Command { @@ -161,6 +162,11 @@ protected function createAuthCodeClient(ClientRepository $clients) */ protected function outputClientDetails(Client $client) { + if (Passport::$hashesClientSecrets) { + $this->line('Here is your new client secret. This is the only time it will be shown so don\'t lose it!'); + $this->line(''); + } + $this->line('Client ID: '.$client->id); $this->line('Client secret: '.$client->plainSecret); } From 2c24ae40239f17e6689830b8243eec7ebc140582 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 15:50:58 +0200 Subject: [PATCH 139/353] Update UPGRADE.md --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 334f257e8..23a3c813c 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -25,7 +25,7 @@ Before you continue, you should set your personal access client ID and unhashed PASSPORT_PERSONAL_ACCESS_CLIENT_ID=client-id-value PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET=unhashed-client-secret-value -Next, you should set register these values by placing the following calls within the `boot` method of your `AppServiceProvider`: +Next, you should register these values by placing the following calls within the `boot` method of your `AppServiceProvider`: Passport::personalAccessClientId(config('passport.personal_access_token.id')); Passport::personalAccessClientSecret(config('passport.personal_access_token.secret')); From ab797a3557c29f1eae7976a7cdec43ce0947295a Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 15:51:17 +0200 Subject: [PATCH 140/353] [9.x] Implement secret modal (#1258) * Implement secret modal * Add upgrade note on vue assets * Revert change * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 6 +++ resources/js/components/Clients.vue | 50 ++++++++++++++++++++--- src/Http/Controllers/ClientController.php | 2 +- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 23a3c813c..c75314498 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,11 @@ # Upgrade Guide +## General Notes + +After updating Passport, you should always re-publish and re-compile the Vue "quickstart" assets if you're using them: + + php artisan vendor:publish --tag=passport-views --force + ## Upgrading To 9.0 From 8.0 ### Support For Multiple Guards diff --git a/resources/js/components/Clients.vue b/resources/js/components/Clients.vue index 7a50deea8..a89003fff 100644 --- a/resources/js/components/Clients.vue +++ b/resources/js/components/Clients.vue @@ -224,6 +224,35 @@ + + +

@@ -236,6 +265,8 @@ return { clients: [], + clientSecret: null, + createForm: { errors: [], name: '', @@ -341,17 +372,17 @@ axios[method](uri, form) .then(response => { - if (method === 'post') { - this.clients.push(response.data); - } else { - this.getClients(); - } + this.getClients(); form.name = ''; form.redirect = ''; form.errors = []; $(modal).modal('hide'); + + if (response.data.plainSecret) { + this.showClientSecret(response.data.plainSecret); + } }) .catch(error => { if (typeof error.response.data === 'object') { @@ -362,6 +393,15 @@ }); }, + /** + * Show the given client secret to the user. + */ + showClientSecret(clientSecret) { + this.clientSecret = clientSecret; + + $('#modal-client-secret').modal('show'); + }, + /** * Destroy the given client. */ diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 219973441..7ce9fde04 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -89,7 +89,7 @@ public function store(Request $request) ); if (Passport::$hashesClientSecrets) { - return ['secret' => $client->plainSecret] + $client->toArray(); + return ['plainSecret' => $client->plainSecret] + $client->toArray(); } return $client->makeVisible('secret'); From c274e928a9f43d517b9887446288d3129b1543f9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 May 2020 15:55:52 +0200 Subject: [PATCH 141/353] Update CHANGELOG.md --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83fb97c56..787fc7eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.0.1...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.1.0...9.x) + + +## [v9.1.0 (2020-05-08](https://github.com/laravel/passport/compare/v9.0.1...v9.1.0) + +### Added +- Implement secret modal ([#1258](https://github.com/laravel/passport/pull/1258)) +- Warn about one-time-hashed-secret ([#1259](https://github.com/laravel/passport/pull/1259)) +- Add force option to hash command ([#1251](https://github.com/laravel/passport/pull/1251)) + +### Fixed +- Implement personal access client config ([#1260](https://github.com/laravel/passport/pull/1260)) ## [v9.0.1 (2020-05-06)](https://github.com/laravel/passport/compare/v9.0.0...v9.0.1) From d9bc3fa5f4b19fd15e42380048ff686ffcce0f3b Mon Sep 17 00:00:00 2001 From: Aaron Huisinga Date: Fri, 8 May 2020 10:08:09 -0500 Subject: [PATCH 142/353] Match name of personal access token methods to config The config values included in passport.php don't match those shown in the upgrade guide for personal access tokens in v9.1. This matches the values with those in the config file. --- UPGRADE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index c75314498..1eeb390f4 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -33,8 +33,8 @@ Before you continue, you should set your personal access client ID and unhashed Next, you should register these values by placing the following calls within the `boot` method of your `AppServiceProvider`: - Passport::personalAccessClientId(config('passport.personal_access_token.id')); - Passport::personalAccessClientSecret(config('passport.personal_access_token.secret')); + Passport::personalAccessClientId(config('passport.personal_access_client.id')); + Passport::personalAccessClientSecret(config('passport.personal_access_client.secret')); > Make sure you follow the instructions above before hashing your secrets. Otherwise, irreversible data loss may occur. From 555e02c212022393888cbd4e902b327e9ec9ad7a Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Fri, 8 May 2020 03:02:51 +0300 Subject: [PATCH 143/353] Allow to change Models database connection --- config/passport.php | 17 ++++++++++ ...1_000001_create_oauth_auth_codes_table.php | 31 +++++++++++++++++-- ...00002_create_oauth_access_tokens_table.php | 31 +++++++++++++++++-- ...0003_create_oauth_refresh_tokens_table.php | 31 +++++++++++++++++-- ...6_01_000004_create_oauth_clients_table.php | 31 +++++++++++++++++-- ...te_oauth_personal_access_clients_table.php | 31 +++++++++++++++++-- src/AuthCode.php | 10 ++++++ src/Client.php | 10 ++++++ src/PersonalAccessClient.php | 10 ++++++ src/RefreshToken.php | 10 ++++++ src/Token.php | 10 ++++++ tests/Feature/PassportTestCase.php | 2 ++ 12 files changed, 214 insertions(+), 10 deletions(-) diff --git a/config/passport.php b/config/passport.php index 79c59acb1..1c962adcf 100644 --- a/config/passport.php +++ b/config/passport.php @@ -46,4 +46,21 @@ 'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'), ], + /* + |-------------------------------------------------------------------------- + | Passport Storage Driver + |-------------------------------------------------------------------------- + | + | This configuration options determines the storage driver that will + | be used to store Passport's data. In addition, you may set any + | custom options as needed by the particular driver you choose. + | + */ + + 'storage' => [ + 'database' => [ + 'connection' => env('DB_CONNECTION', 'mysql'), + ], + ], + ]; diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 6c47d2473..5a8c232f4 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -6,6 +6,33 @@ class CreateOauthAuthCodesTable extends Migration { + /** + * The database schema. + * + * @var \Illuminate\Database\Schema\Builder + */ + protected $schema; + + /** + * Create a new migration instance. + * + * @return void + */ + public function __construct() + { + $this->schema = Schema::connection($this->getConnection()); + } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } + /** * Run the migrations. * @@ -13,7 +40,7 @@ class CreateOauthAuthCodesTable extends Migration */ public function up() { - Schema::create('oauth_auth_codes', function (Blueprint $table) { + $this->schema->create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->index(); $table->unsignedBigInteger('client_id'); @@ -30,6 +57,6 @@ public function up() */ public function down() { - Schema::dropIfExists('oauth_auth_codes'); + $this->schema->dropIfExists('oauth_auth_codes'); } } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 00f00633a..a30107471 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -6,6 +6,33 @@ class CreateOauthAccessTokensTable extends Migration { + /** + * The database schema. + * + * @var \Illuminate\Database\Schema\Builder + */ + protected $schema; + + /** + * Create a new migration instance. + * + * @return void + */ + public function __construct() + { + $this->schema = Schema::connection($this->getConnection()); + } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } + /** * Run the migrations. * @@ -13,7 +40,7 @@ class CreateOauthAccessTokensTable extends Migration */ public function up() { - Schema::create('oauth_access_tokens', function (Blueprint $table) { + $this->schema->create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->unsignedBigInteger('client_id'); @@ -32,6 +59,6 @@ public function up() */ public function down() { - Schema::dropIfExists('oauth_access_tokens'); + $this->schema->dropIfExists('oauth_access_tokens'); } } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 858d0f6db..23ea4a1b3 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -6,6 +6,33 @@ class CreateOauthRefreshTokensTable extends Migration { + /** + * The database schema. + * + * @var \Illuminate\Database\Schema\Builder + */ + protected $schema; + + /** + * Create a new migration instance. + * + * @return void + */ + public function __construct() + { + $this->schema = Schema::connection($this->getConnection()); + } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } + /** * Run the migrations. * @@ -13,7 +40,7 @@ class CreateOauthRefreshTokensTable extends Migration */ public function up() { - Schema::create('oauth_refresh_tokens', function (Blueprint $table) { + $this->schema->create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->string('access_token_id', 100); $table->boolean('revoked'); @@ -28,6 +55,6 @@ public function up() */ public function down() { - Schema::dropIfExists('oauth_refresh_tokens'); + $this->schema->dropIfExists('oauth_refresh_tokens'); } } diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index f0884ee7b..6ce3d9974 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -6,6 +6,33 @@ class CreateOauthClientsTable extends Migration { + /** + * The database schema. + * + * @var \Illuminate\Database\Schema\Builder + */ + protected $schema; + + /** + * Create a new migration instance. + * + * @return void + */ + public function __construct() + { + $this->schema = Schema::connection($this->getConnection()); + } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } + /** * Run the migrations. * @@ -13,7 +40,7 @@ class CreateOauthClientsTable extends Migration */ public function up() { - Schema::create('oauth_clients', function (Blueprint $table) { + $this->schema->create('oauth_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->string('name'); @@ -34,6 +61,6 @@ public function up() */ public function down() { - Schema::dropIfExists('oauth_clients'); + $this->schema->dropIfExists('oauth_clients'); } } diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 4b56435ce..561313578 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -6,6 +6,33 @@ class CreateOauthPersonalAccessClientsTable extends Migration { + /** + * The database schema. + * + * @var \Illuminate\Database\Schema\Builder + */ + protected $schema; + + /** + * Create a new migration instance. + * + * @return void + */ + public function __construct() + { + $this->schema = Schema::connection($this->getConnection()); + } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } + /** * Run the migrations. * @@ -13,7 +40,7 @@ class CreateOauthPersonalAccessClientsTable extends Migration */ public function up() { - Schema::create('oauth_personal_access_clients', function (Blueprint $table) { + $this->schema->create('oauth_personal_access_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('client_id'); $table->timestamps(); @@ -27,6 +54,6 @@ public function up() */ public function down() { - Schema::dropIfExists('oauth_personal_access_clients'); + $this->schema->dropIfExists('oauth_personal_access_clients'); } } diff --git a/src/AuthCode.php b/src/AuthCode.php index 09a79c826..44e9c20e3 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -59,6 +59,16 @@ class AuthCode extends Model */ protected $keyType = 'string'; + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } + /** * Get the client that owns the authentication code. * diff --git a/src/Client.php b/src/Client.php index e3bae044c..083a10112 100644 --- a/src/Client.php +++ b/src/Client.php @@ -65,6 +65,16 @@ public static function boot() }); } + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } + /** * Get the user that the client belongs to. * diff --git a/src/PersonalAccessClient.php b/src/PersonalAccessClient.php index 171b982ab..9d26593ea 100644 --- a/src/PersonalAccessClient.php +++ b/src/PersonalAccessClient.php @@ -20,6 +20,16 @@ class PersonalAccessClient extends Model */ protected $guarded = []; + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } + /** * Get all of the authentication codes for the client. * diff --git a/src/RefreshToken.php b/src/RefreshToken.php index cbfb427ca..ab31f5822 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -59,6 +59,16 @@ class RefreshToken extends Model */ public $timestamps = false; + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } + /** * Get the access token that the refresh token belongs to. * diff --git a/src/Token.php b/src/Token.php index aa1790098..1e6cf51f6 100644 --- a/src/Token.php +++ b/src/Token.php @@ -60,6 +60,16 @@ class Token extends Model */ public $timestamps = false; + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } + /** * Get the client that the token belongs to. * diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 74f1a0bb7..69cbff60b 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -39,6 +39,8 @@ protected function getEnvironmentSetUp($app) $app['config']->set('database.default', 'testbench'); + $app['config']->set('passport.storage.database.connection', 'testbench'); + $app['config']->set('database.connections.testbench', [ 'driver' => 'sqlite', 'database' => ':memory:', From 610cf06e3bd2b9c45abf366d88fd5083e85caa9d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 11 May 2020 15:51:45 +0200 Subject: [PATCH 144/353] [9.x] Update UPGRADE.md (#1265) * Update UPGRADE.md * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 1eeb390f4..8c5c62bbb 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -18,6 +18,8 @@ Passport now has support for multiple guard user providers. Because of this chan $table->string('provider')->after('secret')->nullable(); }); +If you have not previously published the Passport migations, you should manually create a new migration to add this column to your databsae. + ### Client Credentials Secret Hashing PR: https://github.com/laravel/passport/pull/1145 From 36acc8413d6eada8877d43e2ee71851a7a511e92 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 11 May 2020 08:54:33 -0500 Subject: [PATCH 145/353] wording --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 8c5c62bbb..d352d8363 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -18,7 +18,7 @@ Passport now has support for multiple guard user providers. Because of this chan $table->string('provider')->after('secret')->nullable(); }); -If you have not previously published the Passport migations, you should manually create a new migration to add this column to your databsae. +If you have not previously published the Passport migrations, you should manually add the `provider` column to your database. ### Client Credentials Secret Hashing From 7ab3bdbdb9bf162f2da9d8c445523dc63c862248 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 11 May 2020 10:11:04 -0500 Subject: [PATCH 146/353] formatting --- config/passport.php | 6 +++--- ...1_000001_create_oauth_auth_codes_table.php | 20 +++++++++---------- ...00002_create_oauth_access_tokens_table.php | 20 +++++++++---------- ...0003_create_oauth_refresh_tokens_table.php | 20 +++++++++---------- ...te_oauth_personal_access_clients_table.php | 20 +++++++++---------- src/AuthCode.php | 16 +++++++-------- src/Client.php | 20 +++++++++---------- src/PersonalAccessClient.php | 16 +++++++-------- src/RefreshToken.php | 20 +++++++++---------- src/Token.php | 20 +++++++++---------- 10 files changed, 89 insertions(+), 89 deletions(-) diff --git a/config/passport.php b/config/passport.php index 1c962adcf..162f1f84a 100644 --- a/config/passport.php +++ b/config/passport.php @@ -51,9 +51,9 @@ | Passport Storage Driver |-------------------------------------------------------------------------- | - | This configuration options determines the storage driver that will - | be used to store Passport's data. In addition, you may set any - | custom options as needed by the particular driver you choose. + | This configuration value allows you to customize the storage options + | for Passport, such as the database connection that should be used + | by Passport's internal database models which store tokens, etc. | */ diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 5a8c232f4..0eabf059c 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -23,16 +23,6 @@ public function __construct() $this->schema = Schema::connection($this->getConnection()); } - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. * @@ -59,4 +49,14 @@ public function down() { $this->schema->dropIfExists('oauth_auth_codes'); } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index a30107471..67c682d5f 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -23,16 +23,6 @@ public function __construct() $this->schema = Schema::connection($this->getConnection()); } - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. * @@ -61,4 +51,14 @@ public function down() { $this->schema->dropIfExists('oauth_access_tokens'); } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 23ea4a1b3..fe70957c1 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -23,16 +23,6 @@ public function __construct() $this->schema = Schema::connection($this->getConnection()); } - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. * @@ -57,4 +47,14 @@ public function down() { $this->schema->dropIfExists('oauth_refresh_tokens'); } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } } diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 561313578..c408248f5 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -23,16 +23,6 @@ public function __construct() $this->schema = Schema::connection($this->getConnection()); } - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. * @@ -56,4 +46,14 @@ public function down() { $this->schema->dropIfExists('oauth_personal_access_clients'); } + + /** + * Get the migration connection name. + * + * @return string|null + */ + public function getConnection() + { + return config('passport.storage.database.connection'); + } } diff --git a/src/AuthCode.php b/src/AuthCode.php index 44e9c20e3..94441b5f7 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -60,22 +60,22 @@ class AuthCode extends Model protected $keyType = 'string'; /** - * Get the current connection name for the model. + * Get the client that owns the authentication code. * - * @return string|null + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function getConnectionName() + public function client() { - return config('passport.storage.database.connection') ?? $this->connection; + return $this->belongsTo(Passport::clientModel()); } /** - * Get the client that owns the authentication code. + * Get the current connection name for the model. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return string|null */ - public function client() + public function getConnectionName() { - return $this->belongsTo(Passport::clientModel()); + return config('passport.storage.database.connection') ?? $this->connection; } } diff --git a/src/Client.php b/src/Client.php index 083a10112..9fbc155bd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -65,16 +65,6 @@ public static function boot() }); } - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } - /** * Get the user that the client belongs to. * @@ -189,4 +179,14 @@ public function getIncrementing() { return Passport::clientUuids() ? false : $this->incrementing; } + + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } } diff --git a/src/PersonalAccessClient.php b/src/PersonalAccessClient.php index 9d26593ea..1d35b0504 100644 --- a/src/PersonalAccessClient.php +++ b/src/PersonalAccessClient.php @@ -21,22 +21,22 @@ class PersonalAccessClient extends Model protected $guarded = []; /** - * Get the current connection name for the model. + * Get all of the authentication codes for the client. * - * @return string|null + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function getConnectionName() + public function client() { - return config('passport.storage.database.connection') ?? $this->connection; + return $this->belongsTo(Passport::clientModel()); } /** - * Get all of the authentication codes for the client. + * Get the current connection name for the model. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return string|null */ - public function client() + public function getConnectionName() { - return $this->belongsTo(Passport::clientModel()); + return config('passport.storage.database.connection') ?? $this->connection; } } diff --git a/src/RefreshToken.php b/src/RefreshToken.php index ab31f5822..7927662bf 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -59,16 +59,6 @@ class RefreshToken extends Model */ public $timestamps = false; - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } - /** * Get the access token that the refresh token belongs to. * @@ -98,4 +88,14 @@ public function transient() { return false; } + + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } } diff --git a/src/Token.php b/src/Token.php index 1e6cf51f6..1c7bb73b2 100644 --- a/src/Token.php +++ b/src/Token.php @@ -60,16 +60,6 @@ class Token extends Model */ public $timestamps = false; - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } - /** * Get the client that the token belongs to. * @@ -168,4 +158,14 @@ public function transient() { return false; } + + /** + * Get the current connection name for the model. + * + * @return string|null + */ + public function getConnectionName() + { + return config('passport.storage.database.connection') ?? $this->connection; + } } From 789bfe1b9fab6b3fb47e71ff57e58802dae01620 Mon Sep 17 00:00:00 2001 From: Geoff Garbers Date: Tue, 12 May 2020 15:26:47 +0200 Subject: [PATCH 147/353] Change to forceFill. Fixes #908. (#1266) --- src/Bridge/AuthCodeRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridge/AuthCodeRepository.php b/src/Bridge/AuthCodeRepository.php index f3fb39d70..2dfb626a9 100644 --- a/src/Bridge/AuthCodeRepository.php +++ b/src/Bridge/AuthCodeRepository.php @@ -32,7 +32,7 @@ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity) 'expires_at' => $authCodeEntity->getExpiryDateTime(), ]; - Passport::authCode()->setRawAttributes($attributes)->save(); + Passport::authCode()->forceFill($attributes)->save(); } /** From 515cc10ba0c80106c9178c0bb964bcabbe51782b Mon Sep 17 00:00:00 2001 From: Afonso Gloeden Date: Tue, 12 May 2020 17:35:26 -0300 Subject: [PATCH 148/353] Nonstandard ID in the token's relationship with the user (#1267) --- src/Token.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Token.php b/src/Token.php index 1c7bb73b2..9dfd874c6 100644 --- a/src/Token.php +++ b/src/Token.php @@ -79,7 +79,9 @@ public function user() { $provider = config('auth.guards.api.provider'); - return $this->belongsTo(config('auth.providers.'.$provider.'.model')); + $model = config('auth.providers.'.$provider.'.model'); + + return $this->belongsTo($model, 'user_id', (new $model)->getKeyName()); } /** From 9f4b88114e7517db58428cef0ba461f86a2e5f92 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 12 May 2020 22:45:28 +0200 Subject: [PATCH 149/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 787fc7eec..ea6a7bfda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.1.0...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.2.0...9.x) + + +## [v9.2.0 (2020-05-12](https://github.com/laravel/passport/compare/v9.1.0...v9.2.0) + +### Added +- Allow to change Models database connection ([#1255](https://github.com/laravel/passport/pull/1255), [7ab3bdb](https://github.com/laravel/passport/commit/7ab3bdbdb9bf162f2da9d8c445523dc63c862248)) + +### Fixed +- Nonstandard ID in the token's relationship with the user ([#1267](https://github.com/laravel/passport/pull/1267)) ## [v9.1.0 (2020-05-08](https://github.com/laravel/passport/compare/v9.0.1...v9.1.0) From 5a5c0cf2da4ef30d055346e3c109ea9b3b654a07 Mon Sep 17 00:00:00 2001 From: Jordan Hoff Date: Tue, 12 May 2020 16:44:09 -0500 Subject: [PATCH 150/353] Set actingAsClient token client as proper relationship --- src/Passport.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Passport.php b/src/Passport.php index ea347ec2b..22117a130 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -419,7 +419,8 @@ public static function actingAsClient($client, $scopes = []) { $token = app(self::tokenModel()); - $token->client = $client; + $token->client_id = $client->id; + $token->setRelation('client', $client); $token->scopes = $scopes; $mock = Mockery::mock(ResourceServer::class); From b8657e39c28e3d4a44dfa313688a028ea5a998e0 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 13 May 2020 09:11:27 -0500 Subject: [PATCH 151/353] formatting --- src/Passport.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Passport.php b/src/Passport.php index 22117a130..6113e2923 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -421,6 +421,7 @@ public static function actingAsClient($client, $scopes = []) $token->client_id = $client->id; $token->setRelation('client', $client); + $token->scopes = $scopes; $mock = Mockery::mock(ResourceServer::class); From bedf02c8bb8fb9ca373e34f0ceefb2e8c5bf006b Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 14 May 2020 10:21:57 +0200 Subject: [PATCH 152/353] Fix HashCommand --- src/Console/HashCommand.php | 4 ++-- tests/Feature/Console/HashCommand.php | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/Console/HashCommand.php diff --git a/src/Console/HashCommand.php b/src/Console/HashCommand.php index 5c1d23393..2e114d55d 100644 --- a/src/Console/HashCommand.php +++ b/src/Console/HashCommand.php @@ -29,7 +29,7 @@ class HashCommand extends Command public function handle() { if (! Passport::$hashesClientSecrets) { - $this->warn('Please enable client hashing yet in your AppServiceProvider before continuning.'); + $this->warn('Please enable client hashing yet in your AppServiceProvider before continuing.'); return; } @@ -45,7 +45,7 @@ public function handle() $client->timestamps = false; $client->forceFill([ - 'secret' => password_hash($client->secret, PASSWORD_BCRYPT), + 'secret' => $client->secret, ])->save(); } diff --git a/tests/Feature/Console/HashCommand.php b/tests/Feature/Console/HashCommand.php new file mode 100644 index 000000000..6102a6213 --- /dev/null +++ b/tests/Feature/Console/HashCommand.php @@ -0,0 +1,26 @@ +create(['secret' => $secret = Str::random(40)]); + $hasher = $this->app->make(Hasher::class); + + Passport::hashClientSecrets(); + + $this->artisan('passport:hash', ['--force' => true]); + + $this->assertTrue($hasher->check($secret, $client->refresh()->secret)); + + Passport::$hashesClientSecrets = false; + } +} From 0931d75235283d651b767d291a79cafba5d6ce68 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 14 May 2020 10:24:43 +0200 Subject: [PATCH 153/353] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6a7bfda..6ee5afc80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.2.0...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.2.1...9.x) + + +## [v9.2.1 (2020-05-14)](https://github.com/laravel/passport/compare/v9.2.0...v9.2.1) + +### Fixed +- Fix actingAsClient token relation ([#1268](https://github.com/laravel/passport/pull/1268)) +- Fix HashCommand ([bedf02c](https://github.com/laravel/passport/commit/bedf02c8bb8fb9ca373e34f0ceefb2e8c5bf006b)) ## [v9.2.0 (2020-05-12](https://github.com/laravel/passport/compare/v9.1.0...v9.2.0) From d2d157aaf1806ddb64a2f957ab0e0fb436fd3dda Mon Sep 17 00:00:00 2001 From: Cor Bosman Date: Wed, 27 May 2020 12:34:26 +0200 Subject: [PATCH 154/353] correct test name --- tests/Feature/Console/HashCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/Console/HashCommand.php b/tests/Feature/Console/HashCommand.php index 6102a6213..fae29cab1 100644 --- a/tests/Feature/Console/HashCommand.php +++ b/tests/Feature/Console/HashCommand.php @@ -10,7 +10,7 @@ class HashCommand extends PassportTestCase { - public function test_it_can_properly_has_client_secrets() + public function test_it_can_properly_hash_client_secrets() { $client = factory(Client::class)->create(['secret' => $secret = Str::random(40)]); $hasher = $this->app->make(Hasher::class); From 0c20f3165406843956768f1bfa9400fbafb78ca5 Mon Sep 17 00:00:00 2001 From: Panji Setya Nur Prawira Date: Thu, 4 Jun 2020 07:28:50 +0700 Subject: [PATCH 155/353] Fix typo on param doc --- src/PassportServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 44900b2d4..4a11e62f4 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -238,7 +238,7 @@ protected function registerResourceServer() /** * Create a CryptKey instance without permissions check. * - * @param string $key + * @param string $type * @return \League\OAuth2\Server\CryptKey */ protected function makeCryptKey($type) From 7359e3842fff1d795a76c91e81259f74f9a1bdd6 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 5 Jun 2020 15:37:50 +0200 Subject: [PATCH 156/353] Cleanup tests --- phpunit.xml.dist | 9 +++-- tests/Feature/PassportTestCase.php | 7 ++++ .../{ => Unit}/AccessTokenControllerTest.php | 2 +- .../{ => Unit}/ApiTokenCookieFactoryTest.php | 2 +- .../ApproveAuthorizationControllerTest.php | 2 +- .../AuthorizationControllerTest.php | 2 +- .../AuthorizedAccessTokenControllerTest.php | 2 +- .../BridgeAccessTokenRepositoryTest.php | 2 +- ...ridgeClientRepositoryHashedSecretsTest.php | 2 +- .../{ => Unit}/BridgeClientRepositoryTest.php | 2 +- .../BridgeRefreshTokenRepositoryTest.php | 2 +- .../{ => Unit}/BridgeScopeRepositoryTest.php | 2 +- .../CheckClientCredentialsForAnyScopeTest.php | 2 +- .../{ => Unit}/CheckClientCredentialsTest.php | 2 +- tests/{ => Unit}/CheckForAnyScopeTest.php | 2 +- tests/{ => Unit}/CheckScopesTest.php | 2 +- tests/{ => Unit}/ClientControllerTest.php | 2 +- tests/{ => Unit}/CreateFreshApiTokenTest.php | 2 +- .../DenyAuthorizationControllerTest.php | 2 +- tests/{ => Unit}/HandlesOAuthErrorsTest.php | 2 +- tests/{ => Unit}/HasApiTokensTest.php | 2 +- tests/{ => Unit}/KeysCommandTest.php | 40 +++++++++---------- .../PassportServiceProviderTest.php | 8 ++-- tests/{ => Unit}/PassportTest.php | 4 +- .../PersonalAccessTokenControllerTest.php | 2 +- .../PersonalAccessTokenFactoryTest.php | 2 +- tests/{ => Unit}/RedirectRuleTest.php | 2 +- tests/{ => Unit}/ScopeControllerTest.php | 2 +- tests/{ => Unit}/ScopeTest.php | 2 +- tests/{ => Unit}/TokenGuardTest.php | 2 +- tests/{ => Unit}/TokenTest.php | 2 +- .../TransientTokenControllerTest.php | 2 +- tests/{ => Unit}/TransientTokenTest.php | 2 +- tests/bootstrap.php | 3 -- tests/{files => keys}/.gitignore | 0 35 files changed, 68 insertions(+), 59 deletions(-) rename tests/{ => Unit}/AccessTokenControllerTest.php (98%) rename tests/{ => Unit}/ApiTokenCookieFactoryTest.php (96%) rename tests/{ => Unit}/ApproveAuthorizationControllerTest.php (98%) rename tests/{ => Unit}/AuthorizationControllerTest.php (99%) rename tests/{ => Unit}/AuthorizedAccessTokenControllerTest.php (98%) rename tests/{ => Unit}/BridgeAccessTokenRepositoryTest.php (98%) rename tests/{ => Unit}/BridgeClientRepositoryHashedSecretsTest.php (95%) rename tests/{ => Unit}/BridgeClientRepositoryTest.php (99%) rename tests/{ => Unit}/BridgeRefreshTokenRepositoryTest.php (97%) rename tests/{ => Unit}/BridgeScopeRepositoryTest.php (96%) rename tests/{ => Unit}/CheckClientCredentialsForAnyScopeTest.php (99%) rename tests/{ => Unit}/CheckClientCredentialsTest.php (99%) rename tests/{ => Unit}/CheckForAnyScopeTest.php (98%) rename tests/{ => Unit}/CheckScopesTest.php (98%) rename tests/{ => Unit}/ClientControllerTest.php (99%) rename tests/{ => Unit}/CreateFreshApiTokenTest.php (98%) rename tests/{ => Unit}/DenyAuthorizationControllerTest.php (99%) rename tests/{ => Unit}/HandlesOAuthErrorsTest.php (98%) rename tests/{ => Unit}/HasApiTokensTest.php (97%) rename tests/{ => Unit}/KeysCommandTest.php (63%) rename tests/{ => Unit}/PassportServiceProviderTest.php (90%) rename tests/{ => Unit}/PassportTest.php (96%) rename tests/{ => Unit}/PersonalAccessTokenControllerTest.php (99%) rename tests/{ => Unit}/PersonalAccessTokenFactoryTest.php (98%) rename tests/{ => Unit}/RedirectRuleTest.php (97%) rename tests/{ => Unit}/ScopeControllerTest.php (95%) rename tests/{ => Unit}/ScopeTest.php (94%) rename tests/{ => Unit}/TokenGuardTest.php (99%) rename tests/{ => Unit}/TokenTest.php (98%) rename tests/{ => Unit}/TransientTokenControllerTest.php (96%) rename tests/{ => Unit}/TransientTokenTest.php (89%) delete mode 100644 tests/bootstrap.php rename tests/{files => keys}/.gitignore (100%) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f313b78a5..f22833f60 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,7 +2,7 @@ - - ./tests/ + + ./tests/Unit + + + ./tests/Feature diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 69cbff60b..36a2cb734 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -12,6 +12,10 @@ abstract class PassportTestCase extends TestCase { use RefreshDatabase; + const KEYS = __DIR__ . '/keys'; + const PUBLIC_KEY = self::KEYS . '/oauth-public.key'; + const PRIVATE_KEY = self::KEYS . '/oauth-private.key'; + protected function setUp(): void { parent::setUp(); @@ -22,6 +26,9 @@ protected function setUp(): void Passport::routes(); + @unlink(self::PUBLIC_KEY); + @unlink(self::PRIVATE_KEY); + $this->artisan('passport:keys'); } diff --git a/tests/AccessTokenControllerTest.php b/tests/Unit/AccessTokenControllerTest.php similarity index 98% rename from tests/AccessTokenControllerTest.php rename to tests/Unit/AccessTokenControllerTest.php index 967f003f6..ae18953fb 100644 --- a/tests/AccessTokenControllerTest.php +++ b/tests/Unit/AccessTokenControllerTest.php @@ -1,6 +1,6 @@ with('Encryption keys generated successfully.') ->getMock(); - Container::getInstance()->instance('path.storage', storage_path()); + Container::getInstance()->instance('path.storage', self::KEYS); $rsa = new RSA(); $command->handle($rsa); - $this->assertFileExists(storage_path('oauth-private.key')); - $this->assertFileExists(storage_path('oauth-public.key')); + $this->assertFileExists(self::PUBLIC_KEY); + $this->assertFileExists(self::PRIVATE_KEY); } public function testPrivateAndPublicKeysAreGeneratedInCustomPath() { - Passport::loadKeysFrom(custom_path()); + Passport::loadKeysFrom(self::KEYS); $command = m::mock(KeysCommand::class) ->makePartial() @@ -61,8 +61,8 @@ public function testPrivateAndPublicKeysAreGeneratedInCustomPath() $command->handle(new RSA); - $this->assertFileExists(custom_path('oauth-private.key')); - $this->assertFileExists(custom_path('oauth-public.key')); + $this->assertFileExists(self::PUBLIC_KEY); + $this->assertFileExists(self::PRIVATE_KEY); return $command; } diff --git a/tests/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php similarity index 90% rename from tests/PassportServiceProviderTest.php rename to tests/Unit/PassportServiceProviderTest.php index 5a350d86f..bf6354fcd 100644 --- a/tests/PassportServiceProviderTest.php +++ b/tests/Unit/PassportServiceProviderTest.php @@ -1,6 +1,6 @@ getKeyPath()) ); - @unlink(__DIR__.'/files/oauth-private.key'); + @unlink(__DIR__ . '/../keys/oauth-private.key'); } } diff --git a/tests/PassportTest.php b/tests/Unit/PassportTest.php similarity index 96% rename from tests/PassportTest.php rename to tests/Unit/PassportTest.php index 72b5fdfe5..31d7d6178 100644 --- a/tests/PassportTest.php +++ b/tests/Unit/PassportTest.php @@ -1,6 +1,6 @@ assertInstanceOf(RefreshTokenStub::class, $refreshToken); $this->assertInstanceOf(Passport::refreshTokenModel(), $refreshToken); + + Passport::useRefreshTokenModel(RefreshToken::class); } } diff --git a/tests/PersonalAccessTokenControllerTest.php b/tests/Unit/PersonalAccessTokenControllerTest.php similarity index 99% rename from tests/PersonalAccessTokenControllerTest.php rename to tests/Unit/PersonalAccessTokenControllerTest.php index c1951b62c..65b53803c 100644 --- a/tests/PersonalAccessTokenControllerTest.php +++ b/tests/Unit/PersonalAccessTokenControllerTest.php @@ -1,6 +1,6 @@ Date: Fri, 5 Jun 2020 15:38:22 +0200 Subject: [PATCH 157/353] Apply fixes from StyleCI (#1291) --- tests/Feature/PassportTestCase.php | 6 +++--- tests/Unit/KeysCommandTest.php | 6 +++--- tests/Unit/PassportServiceProviderTest.php | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 36a2cb734..4e0cded0c 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -12,9 +12,9 @@ abstract class PassportTestCase extends TestCase { use RefreshDatabase; - const KEYS = __DIR__ . '/keys'; - const PUBLIC_KEY = self::KEYS . '/oauth-public.key'; - const PRIVATE_KEY = self::KEYS . '/oauth-private.key'; + const KEYS = __DIR__.'/keys'; + const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; + const PRIVATE_KEY = self::KEYS.'/oauth-private.key'; protected function setUp(): void { diff --git a/tests/Unit/KeysCommandTest.php b/tests/Unit/KeysCommandTest.php index 4044cd99d..e85f64a29 100644 --- a/tests/Unit/KeysCommandTest.php +++ b/tests/Unit/KeysCommandTest.php @@ -11,9 +11,9 @@ class KeysCommandTest extends TestCase { - const KEYS = __DIR__ . '/../keys'; - const PUBLIC_KEY = self::KEYS . '/oauth-public.key'; - const PRIVATE_KEY = self::KEYS . '/oauth-private.key'; + const KEYS = __DIR__.'/../keys'; + const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; + const PRIVATE_KEY = self::KEYS.'/oauth-private.key'; protected function setUp(): void { diff --git a/tests/Unit/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php index bf6354fcd..a1e24828f 100644 --- a/tests/Unit/PassportServiceProviderTest.php +++ b/tests/Unit/PassportServiceProviderTest.php @@ -36,10 +36,10 @@ public function test_can_use_crypto_keys_from_config() public function test_can_use_crypto_keys_from_local_disk() { - Passport::loadKeysFrom(__DIR__ . '/../keys'); + Passport::loadKeysFrom(__DIR__.'/../keys'); file_put_contents( - __DIR__ . '/../keys/oauth-private.key', + __DIR__.'/../keys/oauth-private.key', "-----BEGIN RSA PRIVATE KEY-----\ndisk\n-----END RSA PRIVATE KEY-----" ); @@ -61,6 +61,6 @@ public function test_can_use_crypto_keys_from_local_disk() file_get_contents($cryptKey->getKeyPath()) ); - @unlink(__DIR__ . '/../keys/oauth-private.key'); + @unlink(__DIR__.'/../keys/oauth-private.key'); } } From f66b981857d8d093ee3f7b617fa6761b42950e6b Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 5 Jun 2020 15:38:42 +0200 Subject: [PATCH 158/353] Apply fixes from StyleCI (#1292) --- tests/Feature/PassportTestCase.php | 6 +++--- tests/Unit/KeysCommandTest.php | 6 +++--- tests/Unit/PassportServiceProviderTest.php | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 36a2cb734..4e0cded0c 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -12,9 +12,9 @@ abstract class PassportTestCase extends TestCase { use RefreshDatabase; - const KEYS = __DIR__ . '/keys'; - const PUBLIC_KEY = self::KEYS . '/oauth-public.key'; - const PRIVATE_KEY = self::KEYS . '/oauth-private.key'; + const KEYS = __DIR__.'/keys'; + const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; + const PRIVATE_KEY = self::KEYS.'/oauth-private.key'; protected function setUp(): void { diff --git a/tests/Unit/KeysCommandTest.php b/tests/Unit/KeysCommandTest.php index 4044cd99d..e85f64a29 100644 --- a/tests/Unit/KeysCommandTest.php +++ b/tests/Unit/KeysCommandTest.php @@ -11,9 +11,9 @@ class KeysCommandTest extends TestCase { - const KEYS = __DIR__ . '/../keys'; - const PUBLIC_KEY = self::KEYS . '/oauth-public.key'; - const PRIVATE_KEY = self::KEYS . '/oauth-private.key'; + const KEYS = __DIR__.'/../keys'; + const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; + const PRIVATE_KEY = self::KEYS.'/oauth-private.key'; protected function setUp(): void { diff --git a/tests/Unit/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php index bf6354fcd..a1e24828f 100644 --- a/tests/Unit/PassportServiceProviderTest.php +++ b/tests/Unit/PassportServiceProviderTest.php @@ -36,10 +36,10 @@ public function test_can_use_crypto_keys_from_config() public function test_can_use_crypto_keys_from_local_disk() { - Passport::loadKeysFrom(__DIR__ . '/../keys'); + Passport::loadKeysFrom(__DIR__.'/../keys'); file_put_contents( - __DIR__ . '/../keys/oauth-private.key', + __DIR__.'/../keys/oauth-private.key', "-----BEGIN RSA PRIVATE KEY-----\ndisk\n-----END RSA PRIVATE KEY-----" ); @@ -61,6 +61,6 @@ public function test_can_use_crypto_keys_from_local_disk() file_get_contents($cryptKey->getKeyPath()) ); - @unlink(__DIR__ . '/../keys/oauth-private.key'); + @unlink(__DIR__.'/../keys/oauth-private.key'); } } From 63c8b6645b2503af10ae3f64938c12b2790ac753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E4=BF=8A=E9=81=A5?= Date: Thu, 11 Jun 2020 22:45:14 +0800 Subject: [PATCH 159/353] Improve `passport:install` command (#1294) --- src/Console/InstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 843dc5d4e..f5ed11023 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -56,7 +56,7 @@ protected function configureUuids() config(['passport.client_uuids' => true]); Passport::setClientUuids(true); - $this->replaceInFile(config_path('passport.php'), 'false', 'true'); + $this->replaceInFile(config_path('passport.php'), '\'client_uuids\' => false', '\'client_uuids\' => true'); $this->replaceInFile(database_path('migrations/2016_06_01_000001_create_oauth_auth_codes_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); $this->replaceInFile(database_path('migrations/2016_06_01_000002_create_oauth_access_tokens_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); $this->replaceInFile(database_path('migrations/2016_06_01_000004_create_oauth_clients_table.php'), '$table->bigIncrements(\'id\');', '$table->uuid(\'id\')->primary();'); From f984a7f557ad38f55287322b6143071a5f61a40d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 19 Jun 2020 15:40:04 +0200 Subject: [PATCH 160/353] Fix maxlength for token names (#1300) --- src/Http/Controllers/ClientController.php | 4 ++-- src/Http/Controllers/PersonalAccessTokenController.php | 2 +- tests/Unit/ClientControllerTest.php | 6 +++--- tests/Unit/PersonalAccessTokenControllerTest.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 7ce9fde04..a36be44c1 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -78,7 +78,7 @@ public function forUser(Request $request) public function store(Request $request) { $this->validation->make($request->all(), [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'redirect' => ['required', $this->redirectRule], 'confidential' => 'boolean', ])->validate(); @@ -111,7 +111,7 @@ public function update(Request $request, $clientId) } $this->validation->make($request->all(), [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'redirect' => ['required', $this->redirectRule], ])->validate(); diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index 81797e8c3..2fde42483 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -61,7 +61,7 @@ public function forUser(Request $request) public function store(Request $request) { $this->validation->make($request->all(), [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'scopes' => 'array|in:'.implode(',', Passport::scopeIds()), ])->validate(); diff --git a/tests/Unit/ClientControllerTest.php b/tests/Unit/ClientControllerTest.php index a3b9c6b5b..29229e222 100644 --- a/tests/Unit/ClientControllerTest.php +++ b/tests/Unit/ClientControllerTest.php @@ -58,7 +58,7 @@ public function test_clients_can_be_stored() 'name' => 'client name', 'redirect' => 'http://localhost', ], [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'redirect' => ['required', $redirectRule], 'confidential' => 'boolean', ])->andReturn($validator); @@ -97,7 +97,7 @@ public function test_public_clients_can_be_stored() 'redirect' => 'http://localhost', 'confidential' => false, ], [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'redirect' => ['required', $redirectRule], 'confidential' => 'boolean', ])->andReturn($validator); @@ -136,7 +136,7 @@ public function test_clients_can_be_updated() 'name' => 'client name', 'redirect' => 'http://localhost', ], [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'redirect' => ['required', $redirectRule], ])->andReturn($validator); $validator->shouldReceive('validate')->once(); diff --git a/tests/Unit/PersonalAccessTokenControllerTest.php b/tests/Unit/PersonalAccessTokenControllerTest.php index 65b53803c..007d87bce 100644 --- a/tests/Unit/PersonalAccessTokenControllerTest.php +++ b/tests/Unit/PersonalAccessTokenControllerTest.php @@ -74,7 +74,7 @@ public function test_tokens_can_be_updated() 'name' => 'token name', 'scopes' => ['user', 'user-admin'], ], [ - 'name' => 'required|max:255', + 'name' => 'required|max:191', 'scopes' => 'array|in:'.implode(',', Passport::scopeIds()), ])->andReturn($validator); $validator->shouldReceive('validate')->once(); From 7ddaa0fa6ff5c100cf755bf85d86886e0edcb0e8 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 25 Jun 2020 14:36:25 +0200 Subject: [PATCH 161/353] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee5afc80..9369db8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.2.1...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.2.2...9.x) + + +## [v9.2.2 (2020-06-25)](https://github.com/laravel/passport/compare/v9.2.1...v9.2.2) + +### Fixed +- Fix maxlength for token names ([#1300](https://github.com/laravel/passport/pull/1300)) +- Improve `passport:install` command ([#1294](https://github.com/laravel/passport/pull/1294)) ## [v9.2.1 (2020-05-14)](https://github.com/laravel/passport/compare/v9.2.0...v9.2.1) From 5599571d410656e68d3be1cd4b35b3e811737814 Mon Sep 17 00:00:00 2001 From: Ankur Kumar Date: Tue, 30 Jun 2020 17:44:11 +0530 Subject: [PATCH 162/353] Allow guzzle v7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0b06af26f..557498ae9 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "php": "^7.2", "ext-json": "*", "firebase/php-jwt": "^5.0", - "guzzlehttp/guzzle": "^6.0", + "guzzlehttp/guzzle": "^6.0|^7.0", "illuminate/auth": "^6.0|^7.0", "illuminate/console": "^6.0|^7.0", "illuminate/container": "^6.0|^7.0", From 724acaea99204728a1baf7b9b730bf97debbf94c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 Jun 2020 22:17:21 +0200 Subject: [PATCH 163/353] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9369db8b6..59ec89886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ ## [Unreleased](https://github.com/laravel/passport/compare/v9.2.2...9.x) +## [v9.3.0 (2020-06-30)](https://github.com/laravel/passport/compare/v9.2.2...v9.3.0) + +### Added +- Guzzle 7 support ([#1311](https://github.com/laravel/passport/pull/1311)) + + ## [v9.2.2 (2020-06-25)](https://github.com/laravel/passport/compare/v9.2.1...v9.2.2) ### Fixed From 5654ce8211528cfcbb53c395d86955ebfe66c37d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 6 Jul 2020 18:39:05 +0200 Subject: [PATCH 164/353] Match property sequence --- src/RefreshToken.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/RefreshToken.php b/src/RefreshToken.php index 7927662bf..376a97b82 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -14,18 +14,18 @@ class RefreshToken extends Model protected $table = 'oauth_refresh_tokens'; /** - * Indicates if the IDs are auto-incrementing. + * The "type" of the primary key ID. * - * @var bool + * @var string */ - public $incrementing = false; + protected $keyType = 'string'; /** - * The "type" of the primary key ID. + * Indicates if the IDs are auto-incrementing. * - * @var string + * @var bool */ - protected $keyType = 'string'; + public $incrementing = false; /** * The guarded attributes on the model. From 52fc782d8013e27c53f9dd1bfba66e0c42fdb3db Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 7 Jul 2020 17:06:30 +0200 Subject: [PATCH 165/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59ec89886..0701fa762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.2.2...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.3.0...9.x) ## [v9.3.0 (2020-06-30)](https://github.com/laravel/passport/compare/v9.2.2...v9.3.0) From 5e3656187a56ad49eeaa9afe804f417f2e6db844 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 7 Jul 2020 17:49:46 +0200 Subject: [PATCH 166/353] Add index to access_token_id column --- .../2016_06_01_000003_create_oauth_refresh_tokens_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index fe70957c1..b4ac09544 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -32,7 +32,7 @@ public function up() { $this->schema->create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); - $table->string('access_token_id', 100); + $table->string('access_token_id', 100)->index(); $table->boolean('revoked'); $table->dateTime('expires_at')->nullable(); }); From f0bd801f0cc646aff7d5d849c8397c4b31f586c5 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 9 Jul 2020 16:26:39 +0200 Subject: [PATCH 167/353] Update tests.yml --- .github/workflows/tests.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2d7e7eb41..1443e4ed7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,21 +22,18 @@ jobs: - name: Checkout code uses: actions/checkout@v1 - - name: Cache dependencies - uses: actions/cache@v1 - with: - path: ~/.composer/cache/files - key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} - - name: Setup PHP uses: shivammathur/setup-php@v1 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick + tools: composer:v2 coverage: none - name: Install dependencies - run: composer require "illuminate/contracts=${{ matrix.laravel }}" --prefer-dist --no-interaction + run: | + composer require "illuminate/contracts=${{ matrix.laravel }}" --no-update + composer update --prefer-dist --no-interaction --no-progress - name: Execute tests run: vendor/bin/phpunit --verbose From 248b95adf0a9019f12d0d62c5dcfa7eac0febeab Mon Sep 17 00:00:00 2001 From: Martin Hettiger Date: Tue, 14 Jul 2020 20:32:36 +0200 Subject: [PATCH 168/353] Use custom models in purge command if set (#1316) --- src/Console/PurgeCommand.php | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index f70064aa2..7854c6ab2 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -4,9 +4,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; -use Laravel\Passport\AuthCode; -use Laravel\Passport\RefreshToken; -use Laravel\Passport\Token; +use Laravel\Passport\Passport; class PurgeCommand extends Command { @@ -35,21 +33,21 @@ public function handle() if (($this->option('revoked') && $this->option('expired')) || (! $this->option('revoked') && ! $this->option('expired'))) { - Token::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); - AuthCode::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); - RefreshToken::where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { - Token::where('revoked', 1)->delete(); - AuthCode::where('revoked', 1)->delete(); - RefreshToken::where('revoked', 1)->delete(); + Passport::token()->where('revoked', 1)->delete(); + Passport::authCode()->where('revoked', 1)->delete(); + Passport::refreshToken()->where('revoked', 1)->delete(); $this->info('Purged revoked items.'); } elseif ($this->option('expired')) { - Token::whereDate('expires_at', '<', $expired)->delete(); - AuthCode::whereDate('expires_at', '<', $expired)->delete(); - RefreshToken::whereDate('expires_at', '<', $expired)->delete(); + Passport::token()->whereDate('expires_at', '<', $expired)->delete(); + Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); $this->info('Purged items expired for more than seven days.'); } From f09aee52e807c6c884a1d5834a61df899ea8276f Mon Sep 17 00:00:00 2001 From: TARMIZI SANUSI Date: Thu, 16 Jul 2020 20:45:59 +0800 Subject: [PATCH 169/353] Apply table responsive on table class (#1318) --- resources/js/components/AuthorizedClients.vue | 2 +- resources/js/components/Clients.vue | 2 +- resources/js/components/PersonalAccessTokens.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/js/components/AuthorizedClients.vue b/resources/js/components/AuthorizedClients.vue index 7b1e8d56f..3e712cb40 100644 --- a/resources/js/components/AuthorizedClients.vue +++ b/resources/js/components/AuthorizedClients.vue @@ -12,7 +12,7 @@
- +
diff --git a/resources/js/components/Clients.vue b/resources/js/components/Clients.vue index a89003fff..522233f57 100644 --- a/resources/js/components/Clients.vue +++ b/resources/js/components/Clients.vue @@ -25,7 +25,7 @@ You have not created any OAuth clients.

-
Name
+
diff --git a/resources/js/components/PersonalAccessTokens.vue b/resources/js/components/PersonalAccessTokens.vue index 6f6f61748..7eedfe975 100644 --- a/resources/js/components/PersonalAccessTokens.vue +++ b/resources/js/components/PersonalAccessTokens.vue @@ -27,7 +27,7 @@

-
Client ID
+
From 38d9ee08974fed5d41376a52a994eaca615138a4 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 21 Jul 2020 17:16:20 +0200 Subject: [PATCH 170/353] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0701fa762..b1b1c15e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.3.0...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.3.1...9.x) + + +## [v9.3.1 (2020-07-21)](https://github.com/laravel/passport/compare/v9.3.0...v9.3.1) + +### Fixed +- Use custom models in purge command if set ([#1316](https://github.com/laravel/passport/pull/1316)) +- Apply table responsive on table class ([#1318](https://github.com/laravel/passport/pull/1318)) ## [v9.3.0 (2020-06-30)](https://github.com/laravel/passport/compare/v9.2.2...v9.3.0) From de6ae4b12ec3b9497c3d4193a5d8994482d00769 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 27 Jul 2020 13:16:19 -0500 Subject: [PATCH 171/353] fix cookie handling for security release --- composer.json | 18 +++++++++--------- src/Guards/TokenGuard.php | 5 +++-- tests/Unit/TokenGuardTest.php | 11 ++++++----- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index 557498ae9..b9cb299e1 100644 --- a/composer.json +++ b/composer.json @@ -18,15 +18,15 @@ "ext-json": "*", "firebase/php-jwt": "^5.0", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/auth": "^6.0|^7.0", - "illuminate/console": "^6.0|^7.0", - "illuminate/container": "^6.0|^7.0", - "illuminate/contracts": "^6.0|^7.0", - "illuminate/cookie": "^6.0|^7.0", - "illuminate/database": "^6.0|^7.0", - "illuminate/encryption": "^6.0|^7.0", - "illuminate/http": "^6.0|^7.0", - "illuminate/support": "^6.0|^7.0", + "illuminate/auth": "^6.18.30|^7.22.3", + "illuminate/console": "^6.18.30|^7.22.3", + "illuminate/container": "^6.18.30|^7.22.3", + "illuminate/contracts": "^6.18.30|^7.22.3", + "illuminate/cookie": "^6.18.30|^7.22.3", + "illuminate/database": "^6.18.30|^7.22.3", + "illuminate/encryption": "^6.18.30|^7.22.3", + "illuminate/http": "^6.18.30|^7.22.3", + "illuminate/support": "^6.18.30|^7.22.3", "laminas/laminas-diactoros": "^2.2", "league/oauth2-server": "^8.1", "nyholm/psr7": "^1.0", diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index e4e01d1c2..2aab387cc 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -7,6 +7,7 @@ use Illuminate\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Encryption\Encrypter; +use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Http\Request; use Laminas\Diactoros\ResponseFactory; @@ -270,7 +271,7 @@ protected function getTokenViaCookie($request) protected function decodeJwtTokenCookie($request) { return (array) JWT::decode( - $this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies), + CookieValuePrefix::remove($this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies)), $this->encrypter->getKey(), ['HS256'] ); @@ -301,7 +302,7 @@ protected function getTokenFromRequest($request) $token = $request->header('X-CSRF-TOKEN'); if (! $token && $header = $request->header('X-XSRF-TOKEN')) { - $token = $this->encrypter->decrypt($header, static::serialized()); + $token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized())); } return $token; diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index 929d19ede..a7f4b8556 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -6,6 +6,7 @@ use Firebase\JWT\JWT; use Illuminate\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Encryption\Encrypter; use Illuminate\Http\Request; use Laravel\Passport\ClientRepository; @@ -127,7 +128,7 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', - $encrypter->encrypt(JWT::encode([ + $encrypter->encrypt(CookieValuePrefix::create('laravel_token', $encrypter->getKey()).JWT::encode([ 'sub' => 1, 'aud' => 1, 'csrf' => 'token', @@ -158,9 +159,9 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); $request = Request::create('/'); - $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt('token', false)); + $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); $request->cookies->set('laravel_token', - $encrypter->encrypt(JWT::encode([ + $encrypter->encrypt(CookieValuePrefix::create('laravel_token', $encrypter->getKey()).JWT::encode([ 'sub' => 1, 'aud' => 1, 'csrf' => 'token', @@ -298,7 +299,7 @@ public function test_csrf_check_can_be_disabled() $request = Request::create('/'); $request->cookies->set('laravel_token', - $encrypter->encrypt(JWT::encode([ + $encrypter->encrypt(CookieValuePrefix::create('laravel_token', $encrypter->getKey()).JWT::encode([ 'sub' => 1, 'aud' => 1, 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), @@ -396,7 +397,7 @@ public function test_clients_may_be_retrieved_from_cookies() $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', - $encrypter->encrypt(JWT::encode([ + $encrypter->encrypt(CookieValuePrefix::create('laravel_token', $encrypter->getKey()).JWT::encode([ 'sub' => 1, 'aud' => 1, 'csrf' => 'token', From 4977c8268bd3f84b1d2a4a00cd2b8a7ed3bdf666 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 27 Jul 2020 13:16:41 -0500 Subject: [PATCH 172/353] Apply fixes from StyleCI (#1321) --- tests/Unit/AuthorizationControllerTest.php | 2 +- tests/Unit/AuthorizedAccessTokenControllerTest.php | 2 +- tests/Unit/PersonalAccessTokenControllerTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index 2ceefadc3..333bb1101 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -55,7 +55,7 @@ public function test_authorization_view_is_presented() $client->shouldReceive('skipsAuthorization')->andReturn(false); - $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($authRequest, $client, $user) { + $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { $this->assertEquals('passport::authorize', $view); $this->assertEquals($client, $data['client']); $this->assertEquals($user, $data['user']); diff --git a/tests/Unit/AuthorizedAccessTokenControllerTest.php b/tests/Unit/AuthorizedAccessTokenControllerTest.php index 63b4f9ca2..89154c7fa 100644 --- a/tests/Unit/AuthorizedAccessTokenControllerTest.php +++ b/tests/Unit/AuthorizedAccessTokenControllerTest.php @@ -63,7 +63,7 @@ public function test_tokens_can_be_retrieved_for_users() $this->tokenRepository->shouldReceive('forUser')->andReturn($userTokens); - $request->setUserResolver(function () use ($token1, $token2) { + $request->setUserResolver(function () { $user = m::mock(); $user->shouldReceive('getAuthIdentifier')->andReturn(1); diff --git a/tests/Unit/PersonalAccessTokenControllerTest.php b/tests/Unit/PersonalAccessTokenControllerTest.php index 007d87bce..0fdbbe577 100644 --- a/tests/Unit/PersonalAccessTokenControllerTest.php +++ b/tests/Unit/PersonalAccessTokenControllerTest.php @@ -36,7 +36,7 @@ public function test_tokens_can_be_retrieved_for_users() $tokenRepository = m::mock(TokenRepository::class); $tokenRepository->shouldReceive('forUser')->andReturn($userTokens); - $request->setUserResolver(function () use ($token1, $token2) { + $request->setUserResolver(function () { $user = m::mock(); $user->shouldReceive('getAuthIdentifier')->andReturn(1); From 75f1ad218ddf4500f2beb9e5c2fb186530e8ddb6 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 27 Jul 2020 20:32:31 +0200 Subject: [PATCH 173/353] Update composer.json --- composer.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index b9cb299e1..738a77f17 100644 --- a/composer.json +++ b/composer.json @@ -18,15 +18,15 @@ "ext-json": "*", "firebase/php-jwt": "^5.0", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/auth": "^6.18.30|^7.22.3", - "illuminate/console": "^6.18.30|^7.22.3", - "illuminate/container": "^6.18.30|^7.22.3", - "illuminate/contracts": "^6.18.30|^7.22.3", - "illuminate/cookie": "^6.18.30|^7.22.3", - "illuminate/database": "^6.18.30|^7.22.3", - "illuminate/encryption": "^6.18.30|^7.22.3", - "illuminate/http": "^6.18.30|^7.22.3", - "illuminate/support": "^6.18.30|^7.22.3", + "illuminate/auth": "^6.18.31|^7.22.4", + "illuminate/console": "^6.18.31|^7.22.4", + "illuminate/container": "^6.18.31|^7.22.4", + "illuminate/contracts": "^6.18.31|^7.22.4", + "illuminate/cookie": "^6.18.31|^7.22.4", + "illuminate/database": "^6.18.31|^7.22.4", + "illuminate/encryption": "^6.18.31|^7.22.4", + "illuminate/http": "^6.18.31|^7.22.4", + "illuminate/support": "^6.18.31|^7.22.4", "laminas/laminas-diactoros": "^2.2", "league/oauth2-server": "^8.1", "nyholm/psr7": "^1.0", From 192fe387c1c173c12f82784e2a1b51be8bd1bf45 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 27 Jul 2020 20:34:39 +0200 Subject: [PATCH 174/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b1c15e4..d549dfd4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.3.1...9.x) +## [Unreleased](https://github.com/laravel/passport/compare/v9.3.2...9.x) + + +## [v9.3.2 (2020-07-27)](https://github.com/laravel/passport/compare/v9.3.1...v9.3.2) + +### Security +- Fix cookie handling for security release ([#1322](https://github.com/laravel/passport/pull/1322), [75f1ad2](https://github.com/laravel/passport/commit/75f1ad218ddf4500f2beb9e5c2fb186530e8ddb6)) ## [v9.3.1 (2020-07-21)](https://github.com/laravel/passport/compare/v9.3.0...v9.3.1) From fcb7654e600f3c6afef880f82be5eafd0d6883b0 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 27 Jul 2020 21:29:56 +0200 Subject: [PATCH 175/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d549dfd4c..0b4262a54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ## [v9.3.2 (2020-07-27)](https://github.com/laravel/passport/compare/v9.3.1...v9.3.2) -### Security +### Fixes - Fix cookie handling for security release ([#1322](https://github.com/laravel/passport/pull/1322), [75f1ad2](https://github.com/laravel/passport/commit/75f1ad218ddf4500f2beb9e5c2fb186530e8ddb6)) From 6d4393e3be8b2ffb8a9e3c270f6ca3b534f0ccf9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 7 Aug 2020 22:57:40 +0200 Subject: [PATCH 176/353] Remove old static personal client methods (#1325) --- src/ClientRepository.php | 51 ++++++++++++++++++++++++++++-- src/Passport.php | 40 ----------------------- src/PassportServiceProvider.php | 15 +++++++++ src/PersonalAccessTokenFactory.php | 2 +- 4 files changed, 65 insertions(+), 43 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index e04dfc0d8..6a6af3902 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -7,6 +7,33 @@ class ClientRepository { + /** + * The personal access client ID. + * + * @var int|string|null + */ + protected $personalAccessClientId; + + /** + * The personal access client secret. + * + * @var string|null + */ + protected $personalAccessClientSecret; + + /** + * Create a new client repository. + * + * @param int|string|null $personalAccessClientId + * @param string|null $personalAccessClientSecret + * @return void + */ + public function __construct($personalAccessClientId = null, $personalAccessClientSecret = null) + { + $this->personalAccessClientId = $personalAccessClientId; + $this->personalAccessClientSecret = $personalAccessClientSecret; + } + /** * Get a client by the given ID. * @@ -85,8 +112,8 @@ public function activeForUser($userId) */ public function personalAccessClient() { - if (Passport::$personalAccessClientId) { - return $this->find(Passport::$personalAccessClientId); + if ($this->personalAccessClientId) { + return $this->find($this->personalAccessClientId); } $client = Passport::personalAccessClient(); @@ -216,4 +243,24 @@ public function delete(Client $client) $client->forceFill(['revoked' => true])->save(); } + + /** + * Get the personal access client id. + * + * @return int|string|null + */ + public function getPersonalAccessClientId() + { + return $this->personalAccessClientId; + } + + /** + * Get the personal access client secret. + * + * @return string|null + */ + public function getPersonalAccessClientSecret() + { + return $this->personalAccessClientSecret; + } } diff --git a/src/Passport.php b/src/Passport.php index 6113e2923..ecad1944e 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -19,20 +19,6 @@ class Passport */ public static $implicitGrantEnabled = false; - /** - * The personal access token client ID. - * - * @var int|string - */ - public static $personalAccessClientId; - - /** - * The personal access token client secret. - * - * @var string - */ - public static $personalAccessClientSecret; - /** * The default scope. * @@ -196,32 +182,6 @@ public static function routes($callback = null, array $options = []) }); } - /** - * Set the client ID that should be used to issue personal access tokens. - * - * @param int|string $clientId - * @return static - */ - public static function personalAccessClientId($clientId) - { - static::$personalAccessClientId = $clientId; - - return new static; - } - - /** - * Set the client secret that should be used to issue personal access tokens. - * - * @param string $clientSecret - * @return static - */ - public static function personalAccessClientSecret($clientSecret) - { - static::$personalAccessClientSecret = $clientSecret; - - return new static; - } - /** * Set the default scope(s). Multiple scopes may be an array or specified delimited by spaces. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 4a11e62f4..6c6d97439 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -93,6 +93,7 @@ public function register() Passport::setClientUuids($this->app->make(Config::class)->get('passport.client_uuids', false)); $this->registerAuthorizationServer(); + $this->registerClientRepository(); $this->registerResourceServer(); $this->registerGuard(); } @@ -220,6 +221,20 @@ public function makeAuthorizationServer() ); } + /** + * Register the client repository. + * + * @return void + */ + protected function registerClientRepository() + { + $this->app->singleton(ClientRepository::class, function ($container) { + $config = $container->make('config')->get('passport.personal_access_client'); + + return new ClientRepository($config['id'] ?? null, $config['secret'] ?? null); + }); + } + /** * Register the resource server. * diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 27c558d79..34fefcd66 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -93,7 +93,7 @@ public function make($userId, $name, array $scopes = []) */ protected function createRequest($client, $userId, array $scopes) { - $secret = Passport::$hashesClientSecrets ? Passport::$personalAccessClientSecret : $client->secret; + $secret = Passport::$hashesClientSecrets ? $this->clients->getPersonalAccessClientSecret() : $client->secret; return (new ServerRequest)->withParsedBody([ 'grant_type' => 'personal_access', From bc0aca315b84c7d59abf925d6f4cee43a388fee3 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Thu, 20 Aug 2020 15:47:52 +0200 Subject: [PATCH 177/353] Remove Guzzle dependency (#1327) --- composer.json | 1 - tests/Unit/AuthorizationControllerTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 738a77f17..892a867cf 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ "php": "^7.2", "ext-json": "*", "firebase/php-jwt": "^5.0", - "guzzlehttp/guzzle": "^6.0|^7.0", "illuminate/auth": "^6.18.31|^7.22.4", "illuminate/console": "^6.18.31|^7.22.4", "illuminate/container": "^6.18.31|^7.22.4", diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index 333bb1101..4fd7c6a42 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests\Unit; -use GuzzleHttp\Psr7\Response; use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Laravel\Passport\Bridge\Scope; @@ -17,6 +16,7 @@ use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use Mockery as m; +use Nyholm\Psr7\Response; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; From 7792cd6eebb4a5b7870862d212b0f70253db587f Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Thu, 20 Aug 2020 21:23:33 +0200 Subject: [PATCH 178/353] Use newer Github actions (#1329) --- .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 1443e4ed7..36ef2a9d2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,10 +20,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Setup PHP - uses: shivammathur/setup-php@v1 + uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick From 98ad6792287dd0025482d58eb39e38e420c2f86a Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Thu, 20 Aug 2020 21:23:48 +0200 Subject: [PATCH 179/353] Allow PHPUnit 9 (#1328) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 892a867cf..07c74c1df 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "require-dev": { "mockery/mockery": "^1.0", "orchestra/testbench": "^4.4|^5.0", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^8.5|^9.3" }, "autoload": { "psr-4": { From 29f137a74ccd225c9e7efc70d649f0f655928728 Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Fri, 21 Aug 2020 15:08:09 +0200 Subject: [PATCH 180/353] Use only one PSR7 implementation (#1330) --- composer.json | 3 +-- src/Guards/TokenGuard.php | 15 ++++++--------- src/Http/Controllers/AccessTokenController.php | 2 +- .../ApproveAuthorizationController.php | 2 +- src/Http/Controllers/AuthorizationController.php | 2 +- src/Http/Controllers/HandlesOAuthErrors.php | 2 +- src/Http/Middleware/CheckCredentials.php | 13 +++++-------- src/PersonalAccessTokenFactory.php | 13 +++++++------ tests/Unit/AccessTokenControllerTest.php | 2 +- tests/Unit/ApproveAuthorizationControllerTest.php | 2 +- 10 files changed, 25 insertions(+), 31 deletions(-) diff --git a/composer.json b/composer.json index b9b793c62..1cebaef92 100644 --- a/composer.json +++ b/composer.json @@ -27,9 +27,8 @@ "illuminate/encryption": "^6.18.31|^7.22.4", "illuminate/http": "^6.18.31|^7.22.4", "illuminate/support": "^6.18.31|^7.22.4", - "laminas/laminas-diactoros": "^2.2", "league/oauth2-server": "^8.1", - "nyholm/psr7": "^1.0", + "nyholm/psr7": "^1.3", "phpseclib/phpseclib": "^2.0", "symfony/psr-http-message-bridge": "^2.0" }, diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 2aab387cc..7d81ed068 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -10,10 +10,6 @@ use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Http\Request; -use Laminas\Diactoros\ResponseFactory; -use Laminas\Diactoros\ServerRequestFactory; -use Laminas\Diactoros\StreamFactory; -use Laminas\Diactoros\UploadedFileFactory; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\PassportUserProvider; @@ -21,6 +17,7 @@ use Laravel\Passport\TransientToken; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; +use Nyholm\Psr7\Factory\Psr17Factory; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; class TokenGuard @@ -195,12 +192,12 @@ protected function getPsrRequestViaBearerToken($request) { // First, we will convert the Symfony request to a PSR-7 implementation which will // be compatible with the base OAuth2 library. The Symfony bridge can perform a - // conversion for us to a new Diactoros implementation of this PSR-7 request. + // conversion for us to a new Nyholm implementation of this PSR-7 request. $psr = (new PsrHttpFactory( - new ServerRequestFactory, - new StreamFactory, - new UploadedFileFactory, - new ResponseFactory + new Psr17Factory, + new Psr17Factory, + new Psr17Factory, + new Psr17Factory ))->createRequest($request); try { diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index c6bb70af9..03af02fd8 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -2,10 +2,10 @@ namespace Laravel\Passport\Http\Controllers; -use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; class AccessTokenController diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index 9dc3b9f52..90023d5e2 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -3,8 +3,8 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Http\Request; -use Laminas\Diactoros\Response as Psr7Response; use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response as Psr7Response; class ApproveAuthorizationController { diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 43dd3895e..22e08ef23 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -5,12 +5,12 @@ use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Illuminate\Support\Str; -use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\Bridge\User; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; class AuthorizationController diff --git a/src/Http/Controllers/HandlesOAuthErrors.php b/src/Http/Controllers/HandlesOAuthErrors.php index 3ec32e711..b036f96bc 100644 --- a/src/Http/Controllers/HandlesOAuthErrors.php +++ b/src/Http/Controllers/HandlesOAuthErrors.php @@ -2,9 +2,9 @@ namespace Laravel\Passport\Http\Controllers; -use Laminas\Diactoros\Response as Psr7Response; use Laravel\Passport\Exceptions\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; +use Nyholm\Psr7\Response as Psr7Response; trait HandlesOAuthErrors { diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index c2efdb8e5..4fe71897a 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -4,13 +4,10 @@ use Closure; use Illuminate\Auth\AuthenticationException; -use Laminas\Diactoros\ResponseFactory; -use Laminas\Diactoros\ServerRequestFactory; -use Laminas\Diactoros\StreamFactory; -use Laminas\Diactoros\UploadedFileFactory; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; +use Nyholm\Psr7\Factory\Psr17Factory; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; abstract class CheckCredentials @@ -55,10 +52,10 @@ public function __construct(ResourceServer $server, TokenRepository $repository) public function handle($request, Closure $next, ...$scopes) { $psr = (new PsrHttpFactory( - new ServerRequestFactory, - new StreamFactory, - new UploadedFileFactory, - new ResponseFactory + new Psr17Factory, + new Psr17Factory, + new Psr17Factory, + new Psr17Factory ))->createRequest($request); try { diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 34fefcd66..ca157f7bc 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -2,10 +2,11 @@ namespace Laravel\Passport; -use Laminas\Diactoros\Response; -use Laminas\Diactoros\ServerRequest; use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response; +use Nyholm\Psr7\ServerRequest; +use Psr\Http\Message\ServerRequestInterface; class PersonalAccessTokenFactory { @@ -89,13 +90,13 @@ public function make($userId, $name, array $scopes = []) * @param \Laravel\Passport\Client $client * @param mixed $userId * @param array $scopes - * @return \Laminas\Diactoros\ServerRequest + * @return \Psr\Http\Message\ServerRequestInterface */ protected function createRequest($client, $userId, array $scopes) { $secret = Passport::$hashesClientSecrets ? $this->clients->getPersonalAccessClientSecret() : $client->secret; - return (new ServerRequest)->withParsedBody([ + return (new ServerRequest('POST', 'not-important'))->withParsedBody([ 'grant_type' => 'personal_access', 'client_id' => $client->id, 'client_secret' => $secret, @@ -107,10 +108,10 @@ protected function createRequest($client, $userId, array $scopes) /** * Dispatch the given request to the authorization server. * - * @param \Laminas\Diactoros\ServerRequest $request + * @param \Psr\Http\Message\ServerRequestInterface $request * @return array */ - protected function dispatchRequestToAuthorizationServer(ServerRequest $request) + protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $request) { return json_decode($this->server->respondToAccessTokenRequest( $request, new Response diff --git a/tests/Unit/AccessTokenControllerTest.php b/tests/Unit/AccessTokenControllerTest.php index ae18953fb..aebf9c571 100644 --- a/tests/Unit/AccessTokenControllerTest.php +++ b/tests/Unit/AccessTokenControllerTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests\Unit; -use Laminas\Diactoros\Response; use Laravel\Passport\Exceptions\OAuthServerException; use Laravel\Passport\Http\Controllers\AccessTokenController; use Laravel\Passport\TokenRepository; @@ -10,6 +9,7 @@ use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; use Mockery as m; +use Nyholm\Psr7\Response; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; diff --git a/tests/Unit/ApproveAuthorizationControllerTest.php b/tests/Unit/ApproveAuthorizationControllerTest.php index e715c759a..646876ec1 100644 --- a/tests/Unit/ApproveAuthorizationControllerTest.php +++ b/tests/Unit/ApproveAuthorizationControllerTest.php @@ -3,11 +3,11 @@ namespace Laravel\Passport\Tests\Unit; use Illuminate\Http\Request; -use Laminas\Diactoros\Response; use Laravel\Passport\Http\Controllers\ApproveAuthorizationController; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use Mockery as m; +use Nyholm\Psr7\Response; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; From df21a4351da85329ce42f43426dfb3d1a117cefa Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 25 Aug 2020 19:46:18 +0200 Subject: [PATCH 181/353] [10.x] Support Laravel 8 (#1336) * Support Laravel 8 * Fix factories * Apply fixes from StyleCI (#1337) * fix tests Co-authored-by: Taylor Otwell --- .github/workflows/tests.yml | 4 +- composer.json | 27 +++++------ database/factories/ClientFactory.php | 48 ++++++++++++++++++++ database/factories/PassportClientFactory.php | 26 ----------- tests/Feature/AccessTokenControllerTest.php | 14 +++--- tests/Feature/PassportTestCase.php | 2 - 6 files changed, 71 insertions(+), 50 deletions(-) create mode 100644 database/factories/ClientFactory.php delete mode 100644 database/factories/PassportClientFactory.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 36ef2a9d2..7acc16c95 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,8 +13,8 @@ jobs: strategy: fail-fast: true matrix: - php: [7.2, 7.3, 7.4] - laravel: [^6.0, ^7.0] + php: [7.3, 7.4] + laravel: [^8.0] name: P${{ matrix.php }} - L${{ matrix.laravel }} diff --git a/composer.json b/composer.json index f1f910850..9d3d1cde7 100644 --- a/composer.json +++ b/composer.json @@ -14,18 +14,18 @@ } ], "require": { - "php": "^7.2", + "php": "^7.3", "ext-json": "*", "firebase/php-jwt": "^5.0", - "illuminate/auth": "^6.18.31|^7.22.4", - "illuminate/console": "^6.18.31|^7.22.4", - "illuminate/container": "^6.18.31|^7.22.4", - "illuminate/contracts": "^6.18.31|^7.22.4", - "illuminate/cookie": "^6.18.31|^7.22.4", - "illuminate/database": "^6.18.31|^7.22.4", - "illuminate/encryption": "^6.18.31|^7.22.4", - "illuminate/http": "^6.18.31|^7.22.4", - "illuminate/support": "^6.18.31|^7.22.4", + "illuminate/auth": "^8.0", + "illuminate/console": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/cookie": "^8.0", + "illuminate/database": "^8.0", + "illuminate/encryption": "^8.0", + "illuminate/http": "^8.0", + "illuminate/support": "^8.0", "league/oauth2-server": "^8.1", "nyholm/psr7": "^1.3", "phpseclib/phpseclib": "^2.0", @@ -33,12 +33,13 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^4.4|^5.0", - "phpunit/phpunit": "^8.5|^9.3" + "orchestra/testbench": "^6.0", + "phpunit/phpunit": "^9.3" }, "autoload": { "psr-4": { - "Laravel\\Passport\\": "src/" + "Laravel\\Passport\\": "src/", + "Laravel\\Passport\\Database\\Factories\\": "database/factories/" } }, "autoload-dev": { diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php new file mode 100644 index 000000000..e844cafe5 --- /dev/null +++ b/database/factories/ClientFactory.php @@ -0,0 +1,48 @@ + null, + 'name' => $this->faker->company, + 'secret' => Str::random(40), + 'redirect' => $this->faker->url, + 'personal_access_client' => false, + 'password_client' => false, + 'revoked' => false, + ]; + } + + /** + * Use as Password Client. + * + * @return $this + */ + public function asPasswordClient() + { + return $this->state([ + 'personal_access_client' => false, + 'password_client' => true, + ]); + } +} diff --git a/database/factories/PassportClientFactory.php b/database/factories/PassportClientFactory.php deleted file mode 100644 index a84c4c6ab..000000000 --- a/database/factories/PassportClientFactory.php +++ /dev/null @@ -1,26 +0,0 @@ -define(Client::class, function (Faker $faker) { - return [ - 'user_id' => null, - 'name' => $faker->company, - 'secret' => Str::random(40), - 'redirect' => $faker->url, - 'personal_access_client' => false, - 'password_client' => false, - 'revoked' => false, - ]; -}); - -$factory->state(Client::class, 'password_client', function (Faker $faker) { - return [ - 'personal_access_client' => false, - 'password_client' => true, - ]; -}); diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 48697da62..98698dd6c 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -4,11 +4,11 @@ use Carbon\CarbonImmutable; use Illuminate\Contracts\Hashing\Hasher; -use Illuminate\Database\Eloquent\Factory; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Database\Factories\ClientFactory; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -52,7 +52,7 @@ public function testGettingAccessTokenWithPasswordGrant() $user->save(); /** @var Client $client */ - $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); $response = $this->post( '/oauth/token', @@ -71,7 +71,7 @@ public function testGettingAccessTokenWithPasswordGrant() $response->assertHeader('cache-control', 'no-store, private'); $response->assertHeader('content-type', 'application/json; charset=UTF-8'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayHasKey('token_type', $decodedResponse); $this->assertArrayHasKey('expires_in', $decodedResponse); @@ -103,7 +103,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() $user->save(); /** @var Client $client */ - $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); $response = $this->post( '/oauth/token', @@ -121,7 +121,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() $response->assertHeader('cache-control', 'no-cache, private'); $response->assertHeader('content-type', 'application/json'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayNotHasKey('token_type', $decodedResponse); $this->assertArrayNotHasKey('expires_in', $decodedResponse); @@ -146,7 +146,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() $user->save(); /** @var Client $client */ - $client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); $response = $this->post( '/oauth/token', @@ -164,7 +164,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() $response->assertHeader('cache-control', 'no-cache, private'); $response->assertHeader('content-type', 'application/json'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayNotHasKey('token_type', $decodedResponse); $this->assertArrayNotHasKey('expires_in', $decodedResponse); diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 4e0cded0c..d7da023cb 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -20,8 +20,6 @@ protected function setUp(): void { parent::setUp(); - $this->withFactories(__DIR__.'/../../database/factories'); - $this->artisan('migrate:fresh'); Passport::routes(); From ffcb546137a4ab609f8bef0d39feb2a9526bbade Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Wed, 2 Sep 2020 09:15:46 -0400 Subject: [PATCH 182/353] style: correct NBSP for regular spaces (#1339) --- src/Passport.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index 6113e2923..f3c49fdc9 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -409,11 +409,11 @@ public static function actingAs($user, $scopes = [], $guard = 'api') } /** - * Set the current client for the application with the given scopes. + * Set the current client for the application with the given scopes. * - * @param  \Laravel\Passport\Client  $client - * @param  array  $scopes - * @return \Laravel\Passport\Client + * @param \Laravel\Passport\Client $client + * @param array $scopes + * @return \Laravel\Passport\Client */ public static function actingAsClient($client, $scopes = []) { From e576928242fc2d2c0e469c9aa5d07745671255b6 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Wed, 2 Sep 2020 11:13:05 -0400 Subject: [PATCH 183/353] [10.x] Client Credentials Feature tests (#1341) * feat: add factory state method for client credentials grant * test: add pass/fail tests for client credentials grant * style: trailing comma --- database/factories/ClientFactory.php | 13 +++ tests/Feature/AccessTokenControllerTest.php | 89 +++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index e844cafe5..091be54f5 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -45,4 +45,17 @@ public function asPasswordClient() 'password_client' => true, ]); } + + /** + * Use as Client Credentials. + * + * @return $this + */ + public function asClientCredentials() + { + return $this->state([ + 'personal_access_client' => false, + 'password_client' => false, + ]); + } } diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 98698dd6c..2bca3459c 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -41,6 +41,95 @@ protected function getUserClass() return User::class; } + public function testGettingAccessTokenWithClientCredentialsGrant() + { + $this->withoutExceptionHandling(); + + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make('foobar123'); + $user->save(); + + /** @var Client $client */ + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'client_credentials', + 'client_id' => $client->id, + 'client_secret' => $client->secret, + ] + ); + + $response->assertOk(); + + $response->assertHeader('pragma', 'no-cache'); + $response->assertHeader('cache-control', 'no-store, private'); + $response->assertHeader('content-type', 'application/json; charset=UTF-8'); + + $decodedResponse = $response->decodeResponseJson()->json(); + + $this->assertArrayHasKey('token_type', $decodedResponse); + $this->assertArrayHasKey('expires_in', $decodedResponse); + $this->assertArrayHasKey('access_token', $decodedResponse); + $this->assertSame('Bearer', $decodedResponse['token_type']); + $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)); + + $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->getClaim('jti')); + $this->assertInstanceOf(Token::class, $token); + $this->assertTrue($token->client->is($client)); + $this->assertFalse($token->revoked); + $this->assertNull($token->name); + $this->assertNull($token->user_id); + $this->assertLessThanOrEqual(5, CarbonImmutable::now()->addSeconds($expiresInSeconds)->diffInSeconds($token->expires_at)); + } + + public function testGettingAccessTokenWithClientCredentialsGrantInvalidClientSecret() + { + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make('foobar123'); + $user->save(); + + /** @var Client $client */ + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'client_credentials', + 'client_id' => $client->id, + 'client_secret' => $client->secret.'foo', + ] + ); + + $response->assertStatus(401); + + $response->assertHeader('cache-control', 'no-cache, private'); + $response->assertHeader('content-type', 'application/json'); + + $decodedResponse = $response->decodeResponseJson()->json(); + + $this->assertArrayNotHasKey('token_type', $decodedResponse); + $this->assertArrayNotHasKey('expires_in', $decodedResponse); + $this->assertArrayNotHasKey('access_token', $decodedResponse); + + $this->assertArrayHasKey('error', $decodedResponse); + $this->assertSame('invalid_client', $decodedResponse['error']); + $this->assertArrayHasKey('error_description', $decodedResponse); + $this->assertSame('Client authentication failed', $decodedResponse['error_description']); + $this->assertArrayNotHasKey('hint', $decodedResponse); + $this->assertArrayHasKey('message', $decodedResponse); + $this->assertSame('Client authentication failed', $decodedResponse['message']); + + $this->assertSame(0, Token::count()); + } + public function testGettingAccessTokenWithPasswordGrant() { $this->withoutExceptionHandling(); From 11d95f57393db5b3ebd0d9458c4a3f62b98ab9ee Mon Sep 17 00:00:00 2001 From: "Chun-Sheng, Li" Date: Fri, 4 Sep 2020 02:36:42 +0800 Subject: [PATCH 184/353] Using assertSame to make assertion equals strict (#1343) --- tests/Unit/AccessTokenControllerTest.php | 2 +- tests/Unit/ApproveAuthorizationControllerTest.php | 2 +- tests/Unit/AuthorizationControllerTest.php | 10 +++++----- tests/Unit/AuthorizedAccessTokenControllerTest.php | 4 ++-- tests/Unit/BridgeAccessTokenRepositoryTest.php | 8 ++++---- tests/Unit/BridgeClientRepositoryTest.php | 4 ++-- tests/Unit/CheckClientCredentialsForAnyScopeTest.php | 4 ++-- tests/Unit/CheckClientCredentialsTest.php | 4 ++-- tests/Unit/CheckForAnyScopeTest.php | 2 +- tests/Unit/CheckScopesTest.php | 2 +- tests/Unit/ClientControllerTest.php | 8 ++++---- tests/Unit/DenyAuthorizationControllerTest.php | 8 ++++---- tests/Unit/HandlesOAuthErrorsTest.php | 2 +- tests/Unit/PassportTest.php | 2 +- tests/Unit/PersonalAccessTokenControllerTest.php | 6 +++--- tests/Unit/TransientTokenControllerTest.php | 4 ++-- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/Unit/AccessTokenControllerTest.php b/tests/Unit/AccessTokenControllerTest.php index ae18953fb..07905ac19 100644 --- a/tests/Unit/AccessTokenControllerTest.php +++ b/tests/Unit/AccessTokenControllerTest.php @@ -38,7 +38,7 @@ public function test_a_token_can_be_issued() $controller = new AccessTokenController($server, $tokens, $jwt); - $this->assertEquals('{"access_token":"access-token"}', $controller->issueToken($request)->getContent()); + $this->assertSame('{"access_token":"access-token"}', $controller->issueToken($request)->getContent()); } public function test_exceptions_are_handled() diff --git a/tests/Unit/ApproveAuthorizationControllerTest.php b/tests/Unit/ApproveAuthorizationControllerTest.php index e715c759a..67bf85cbc 100644 --- a/tests/Unit/ApproveAuthorizationControllerTest.php +++ b/tests/Unit/ApproveAuthorizationControllerTest.php @@ -49,7 +49,7 @@ public function test_complete_authorization_request() ->with($authRequest, m::type(ResponseInterface::class)) ->andReturn($psrResponse); - $this->assertEquals('response', $controller->approve($request)->getContent()); + $this->assertSame('response', $controller->approve($request)->getContent()); } } diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index 4fd7c6a42..a8672cf10 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -56,10 +56,10 @@ public function test_authorization_view_is_presented() $client->shouldReceive('skipsAuthorization')->andReturn(false); $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { - $this->assertEquals('passport::authorize', $view); + $this->assertSame('passport::authorize', $view); $this->assertEquals($client, $data['client']); $this->assertEquals($user, $data['user']); - $this->assertEquals('description', $data['scopes'][0]->description); + $this->assertSame('description', $data['scopes'][0]->description); return 'view'; }); @@ -67,7 +67,7 @@ public function test_authorization_view_is_presented() $tokens = m::mock(TokenRepository::class); $tokens->shouldReceive('findValidToken')->with($user, $client)->andReturnNull(); - $this->assertEquals('view', $controller->authorize( + $this->assertSame('view', $controller->authorize( m::mock(ServerRequestInterface::class), $request, $clients, $tokens )); } @@ -131,7 +131,7 @@ public function test_request_is_approved_if_valid_token_exists() ->andReturn($token = m::mock(Token::class)); $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['scope-1']); - $this->assertEquals('approved', $controller->authorize( + $this->assertSame('approved', $controller->authorize( m::mock(ServerRequestInterface::class), $request, $clients, $tokens )->getContent()); } @@ -174,7 +174,7 @@ public function test_request_is_approved_if_client_can_skip_authorization() ->with($user, $client) ->andReturnNull(); - $this->assertEquals('approved', $controller->authorize( + $this->assertSame('approved', $controller->authorize( m::mock(ServerRequestInterface::class), $request, $clients, $tokens )->getContent()); } diff --git a/tests/Unit/AuthorizedAccessTokenControllerTest.php b/tests/Unit/AuthorizedAccessTokenControllerTest.php index 89154c7fa..fdf04fa54 100644 --- a/tests/Unit/AuthorizedAccessTokenControllerTest.php +++ b/tests/Unit/AuthorizedAccessTokenControllerTest.php @@ -96,7 +96,7 @@ public function test_tokens_can_be_deleted() $response = $this->controller->destroy($request, 1); - $this->assertEquals(Response::HTTP_NO_CONTENT, $response->status()); + $this->assertSame(Response::HTTP_NO_CONTENT, $response->status()); } public function test_not_found_response_is_returned_if_user_doesnt_have_token() @@ -112,6 +112,6 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() return $user; }); - $this->assertEquals(404, $this->controller->destroy($request, 3)->status()); + $this->assertSame(404, $this->controller->destroy($request, 3)->status()); } } diff --git a/tests/Unit/BridgeAccessTokenRepositoryTest.php b/tests/Unit/BridgeAccessTokenRepositoryTest.php index 996bdce5e..0d34d9b45 100644 --- a/tests/Unit/BridgeAccessTokenRepositoryTest.php +++ b/tests/Unit/BridgeAccessTokenRepositoryTest.php @@ -27,9 +27,9 @@ public function test_access_tokens_can_be_persisted() $events = m::mock(Dispatcher::class); $tokenRepository->shouldReceive('create')->once()->andReturnUsing(function ($array) use ($expiration) { - $this->assertEquals(1, $array['id']); - $this->assertEquals(2, $array['user_id']); - $this->assertEquals('client-id', $array['client_id']); + $this->assertSame(1, $array['id']); + $this->assertSame(2, $array['user_id']); + $this->assertSame('client-id', $array['client_id']); $this->assertEquals(['scopes'], $array['scopes']); $this->assertEquals(false, $array['revoked']); $this->assertInstanceOf('DateTime', $array['created_at']); @@ -62,6 +62,6 @@ public function test_can_get_new_access_token() $this->assertInstanceOf(AccessToken::class, $token); $this->assertEquals($client, $token->getClient()); $this->assertEquals($scopes, $token->getScopes()); - $this->assertEquals($userIdentifier, $token->getUserIdentifier()); + $this->assertSame($userIdentifier, $token->getUserIdentifier()); } } diff --git a/tests/Unit/BridgeClientRepositoryTest.php b/tests/Unit/BridgeClientRepositoryTest.php index c30a89564..c20503407 100644 --- a/tests/Unit/BridgeClientRepositoryTest.php +++ b/tests/Unit/BridgeClientRepositoryTest.php @@ -46,8 +46,8 @@ public function test_can_get_client() $client = $this->repository->getClientEntity(1); $this->assertInstanceOf(Client::class, $client); - $this->assertEquals('1', $client->getIdentifier()); - $this->assertEquals('Client', $client->getName()); + $this->assertSame('1', $client->getIdentifier()); + $this->assertSame('Client', $client->getName()); $this->assertEquals(['http://localhost'], $client->getRedirectUri()); $this->assertTrue($client->isConfidential()); } diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 33d4bce8b..754d9a7de 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -47,7 +47,7 @@ public function test_request_is_passed_along_if_token_is_valid() return 'response'; }); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_request_is_passed_along_if_token_has_any_required_scope() @@ -80,7 +80,7 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() return 'response'; }, 'notfoo', 'bar', 'notbaz'); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_exception_is_thrown_when_oauth_throws_exception() diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 4a2ed767a..36e410dd5 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -47,7 +47,7 @@ public function test_request_is_passed_along_if_token_is_valid() return 'response'; }); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_request_is_passed_along_if_token_and_scope_are_valid() @@ -79,7 +79,7 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() return 'response'; }, 'see-profile'); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_exception_is_thrown_when_oauth_throws_exception() diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index 797c6b9f9..cf9e04c5b 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -26,7 +26,7 @@ public function test_request_is_passed_along_if_scopes_are_present_on_token() return 'response'; }, 'foo', 'bar'); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_exception_is_thrown_if_token_doesnt_have_scope() diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index cbd99d4d7..3eb172b9b 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -26,7 +26,7 @@ public function test_request_is_passed_along_if_scopes_are_present_on_token() return 'response'; }, 'foo', 'bar'); - $this->assertEquals('response', $response); + $this->assertSame('response', $response); } public function test_exception_is_thrown_if_token_doesnt_have_scope() diff --git a/tests/Unit/ClientControllerTest.php b/tests/Unit/ClientControllerTest.php index 29229e222..7da484042 100644 --- a/tests/Unit/ClientControllerTest.php +++ b/tests/Unit/ClientControllerTest.php @@ -145,7 +145,7 @@ public function test_clients_can_be_updated() $clients, $validator, $redirectRule ); - $this->assertEquals('response', $controller->update($request, 1)); + $this->assertSame('response', $controller->update($request, 1)); } public function test_404_response_if_client_doesnt_belong_to_user() @@ -170,7 +170,7 @@ public function test_404_response_if_client_doesnt_belong_to_user() $clients, $validator, m::mock(RedirectRule::class) ); - $this->assertEquals(404, $controller->update($request, 1)->status()); + $this->assertSame(404, $controller->update($request, 1)->status()); } public function test_clients_can_be_deleted() @@ -200,7 +200,7 @@ public function test_clients_can_be_deleted() $response = $controller->destroy($request, 1); - $this->assertEquals(Response::HTTP_NO_CONTENT, $response->status()); + $this->assertSame(Response::HTTP_NO_CONTENT, $response->status()); } public function test_404_response_if_client_doesnt_belong_to_user_on_delete() @@ -225,7 +225,7 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() $clients, $validator, m::mock(RedirectRule::class) ); - $this->assertEquals(404, $controller->destroy($request, 1)->status()); + $this->assertSame(404, $controller->destroy($request, 1)->status()); } } diff --git a/tests/Unit/DenyAuthorizationControllerTest.php b/tests/Unit/DenyAuthorizationControllerTest.php index 30a1e250c..cfb5e01cc 100644 --- a/tests/Unit/DenyAuthorizationControllerTest.php +++ b/tests/Unit/DenyAuthorizationControllerTest.php @@ -45,7 +45,7 @@ public function test_authorization_can_be_denied() return $url; }); - $this->assertEquals('http://localhost?error=access_denied&state=state', $controller->deny($request)); + $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); } public function test_authorization_can_be_denied_with_multiple_redirect_uris() @@ -77,7 +77,7 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris() return $url; }); - $this->assertEquals('http://localhost?error=access_denied&state=state', $controller->deny($request)); + $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); } public function test_authorization_can_be_denied_implicit() @@ -109,7 +109,7 @@ public function test_authorization_can_be_denied_implicit() return $url; }); - $this->assertEquals('http://localhost#error=access_denied&state=state', $controller->deny($request)); + $this->assertSame('http://localhost#error=access_denied&state=state', $controller->deny($request)); } public function test_authorization_can_be_denied_with_existing_query_string() @@ -141,7 +141,7 @@ public function test_authorization_can_be_denied_with_existing_query_string() return $url; }); - $this->assertEquals('http://localhost?action=some_action&error=access_denied&state=state', $controller->deny($request)); + $this->assertSame('http://localhost?action=some_action&error=access_denied&state=state', $controller->deny($request)); } public function test_auth_request_should_exist() diff --git a/tests/Unit/HandlesOAuthErrorsTest.php b/tests/Unit/HandlesOAuthErrorsTest.php index 676512bd1..ed8dd1c1d 100644 --- a/tests/Unit/HandlesOAuthErrorsTest.php +++ b/tests/Unit/HandlesOAuthErrorsTest.php @@ -47,7 +47,7 @@ public function testShouldHandleOAuthServerException() } $this->assertInstanceOf(OAuthServerException::class, $e); - $this->assertEquals('Error', $e->getMessage()); + $this->assertSame('Error', $e->getMessage()); $this->assertInstanceOf(LeagueException::class, $e->getPrevious()); $response = $e->render(new Request); diff --git a/tests/Unit/PassportTest.php b/tests/Unit/PassportTest.php index 31d7d6178..b6e69e2ad 100644 --- a/tests/Unit/PassportTest.php +++ b/tests/Unit/PassportTest.php @@ -21,7 +21,7 @@ public function test_scopes_can_be_managed() $this->assertTrue(Passport::hasScope('user')); $this->assertEquals(['user'], Passport::scopeIds()); - $this->assertEquals('user', Passport::scopes()[0]->id); + $this->assertSame('user', Passport::scopes()[0]->id); } public function test_auth_code_instance_can_be_created() diff --git a/tests/Unit/PersonalAccessTokenControllerTest.php b/tests/Unit/PersonalAccessTokenControllerTest.php index 0fdbbe577..9e8b1ad50 100644 --- a/tests/Unit/PersonalAccessTokenControllerTest.php +++ b/tests/Unit/PersonalAccessTokenControllerTest.php @@ -82,7 +82,7 @@ public function test_tokens_can_be_updated() $tokenRepository = m::mock(TokenRepository::class); $controller = new PersonalAccessTokenController($tokenRepository, $validator); - $this->assertEquals('response', $controller->store($request)); + $this->assertSame('response', $controller->store($request)); } public function test_tokens_can_be_deleted() @@ -108,7 +108,7 @@ public function test_tokens_can_be_deleted() $response = $controller->destroy($request, 1); - $this->assertEquals(Response::HTTP_NO_CONTENT, $response->status()); + $this->assertSame(Response::HTTP_NO_CONTENT, $response->status()); } public function test_not_found_response_is_returned_if_user_doesnt_have_token() @@ -128,6 +128,6 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $validator = m::mock(Factory::class); $controller = new PersonalAccessTokenController($tokenRepository, $validator); - $this->assertEquals(404, $controller->destroy($request, 3)->status()); + $this->assertSame(404, $controller->destroy($request, 3)->status()); } } diff --git a/tests/Unit/TransientTokenControllerTest.php b/tests/Unit/TransientTokenControllerTest.php index b3ebbfaef..0ebb1ab86 100644 --- a/tests/Unit/TransientTokenControllerTest.php +++ b/tests/Unit/TransientTokenControllerTest.php @@ -30,7 +30,7 @@ public function test_token_can_be_refreshed() $response = $controller->refresh($request); - $this->assertEquals(200, $response->status()); - $this->assertEquals('Refreshed.', $response->getOriginalContent()); + $this->assertSame(200, $response->status()); + $this->assertSame('Refreshed.', $response->getOriginalContent()); } } From 23cc8e23940db77e44b549887cf985abf8917cc8 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 16:27:54 +0200 Subject: [PATCH 185/353] Update CHANGELOG.md --- CHANGELOG.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac135cf92..282fe1471 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v9.3.2...master) +## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...master) + + +## [v9.3.2 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) + +### Added +- Support Laravel 8 ([#1336](https://github.com/laravel/passport/pull/1336)) + +### Changed +- `forceFill` new auth code attributes ([#1266](https://github.com/laravel/passport/pull/1266)) +- Use only one PSR 7 implementation ([#1330](https://github.com/laravel/passport/pull/1330)) + +### Removed +- Remove old static personal client methods ([#1325](https://github.com/laravel/passport/pull/1325)) +- Remove Guzzle dependency ([#1327](https://github.com/laravel/passport/pull/1327)) ## [v9.3.2 (2020-07-27)](https://github.com/laravel/passport/compare/v9.3.1...v9.3.2) From 8a84da3464bde233f04748e46d3e78233db23179 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 16:36:41 +0200 Subject: [PATCH 186/353] wip --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 282fe1471..8a6303014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...master) -## [v9.3.2 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) +## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) ### Added - Support Laravel 8 ([#1336](https://github.com/laravel/passport/pull/1336)) From 445a445304a2ab76335b841797fcd951385ae37f Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 16:44:12 +0200 Subject: [PATCH 187/353] [10.x] Upgrade guide (#1345) * Update README.md * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index d352d8363..e9e179b91 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -6,7 +6,23 @@ After updating Passport, you should always re-publish and re-compile the Vue "qu php artisan vendor:publish --tag=passport-views --force -## Upgrading To 9.0 From 8.0 +## Upgrading To 10.0 From 9.x + +### Minimum PHP Version + +PHP 7.3 is now the minimum required version. + +### Minimum Laravel Version + +Laravel 8.0 is now the minimum required version. + +### Old Static Personal Client Methods Removed + +PR: https://github.com/laravel/passport/pull/1325 + +The personal client configuration methods have been removed from the `Passport` class since they are no longer necessary. You should remove calls to these methods from your `AuthServiceProvider`. + +## Upgrading To 9.0 From 8.x ### Support For Multiple Guards @@ -67,7 +83,7 @@ PR: https://github.com/laravel/passport/pull/1235 The deprecated `revokeOtherTokens` and `pruneRevokedTokens` methods and the `revokeOtherTokens` and `pruneRevokedTokens` properties were removed from the `Passport` object. -## Upgrading To 8.0 From 7.0 +## Upgrading To 8.0 From 7.x ### Minimum & Upgraded Versions From 71d1a70a920f991e4f459f4896b9a32fefb3f5d5 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 17:27:48 +0200 Subject: [PATCH 188/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a6303014..80c7f05f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...master) +## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...10.x) ## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) From b182a80e4dcc93e48a2e8833348706e4a6f6786c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 17:30:36 +0200 Subject: [PATCH 189/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c7f05f2..8a6303014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...master) ## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) From ce7f5ab7e15f11446de77a94c50fc2faf2ac283e Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Sep 2020 17:30:52 +0200 Subject: [PATCH 190/353] update branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9d3d1cde7..990652e80 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ }, "extra": { "branch-alias": { - "dev-master": "10.x-dev" + "dev-master": "11.x-dev" }, "laravel": { "providers": [ From 7a2ce6ccaa8eb56adfb2524f677d0d06806a55c9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 14 Sep 2020 15:47:45 +0200 Subject: [PATCH 191/353] [10.x] Use newFactory to properly reference factory (#1349) * Use newFactory to properly reference factory * Update composer.json --- composer.json | 18 +++++++++--------- src/Client.php | 14 ++++++++++++++ src/PassportServiceProvider.php | 4 ---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index 9d3d1cde7..e04b5259c 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,15 @@ "php": "^7.3", "ext-json": "*", "firebase/php-jwt": "^5.0", - "illuminate/auth": "^8.0", - "illuminate/console": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/cookie": "^8.0", - "illuminate/database": "^8.0", - "illuminate/encryption": "^8.0", - "illuminate/http": "^8.0", - "illuminate/support": "^8.0", + "illuminate/auth": "^8.2", + "illuminate/console": "^8.2", + "illuminate/container": "^8.2", + "illuminate/contracts": "^8.2", + "illuminate/cookie": "^8.2", + "illuminate/database": "^8.2", + "illuminate/encryption": "^8.2", + "illuminate/http": "^8.2", + "illuminate/support": "^8.2", "league/oauth2-server": "^8.1", "nyholm/psr7": "^1.3", "phpseclib/phpseclib": "^2.0", diff --git a/src/Client.php b/src/Client.php index 9fbc155bd..f75fb7b97 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,11 +2,15 @@ namespace Laravel\Passport; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; +use Laravel\Passport\Database\Factories\ClientFactory; class Client extends Model { + use HasFactory; + /** * The database table used by the model. * @@ -189,4 +193,14 @@ public function getConnectionName() { return config('passport.storage.database.connection') ?? $this->connection; } + + /** + * Create a new factory instance for the model. + * + * @return \Illuminate\Database\Eloquent\Factories\Factory + */ + public static function newFactory() + { + return ClientFactory::new(); + } } diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 6c6d97439..e5082048b 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -51,10 +51,6 @@ public function boot() __DIR__.'/../resources/js/components' => base_path('resources/js/components/passport'), ], 'passport-components'); - $this->publishes([ - __DIR__.'/../database/factories' => database_path('factories'), - ], 'passport-factories'); - $this->publishes([ __DIR__.'/../config/passport.php' => config_path('passport.php'), ], 'passport-config'); From 4e53f1b237a9e51ac10f0b30c6ebedd68f6848ab Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 15 Sep 2020 18:41:42 +0200 Subject: [PATCH 192/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c7f05f2..e9600708c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.0.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.0.1...10.x) + + +## [v10.0.1 (2020-09-15)](https://github.com/laravel/passport/compare/v10.0.0...v10.0.1) + +### Fixed +- Use newFactory to properly reference factory ([#1349](https://github.com/laravel/passport/pull/1349)) ## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) From 61de2cf4e0002982baad3168256c7dd083897e41 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 21 Sep 2020 17:19:40 +0200 Subject: [PATCH 193/353] Remove Vue components (#1352) --- UPGRADE.md | 4 - resources/js/components/AuthorizedClients.vue | 107 ----- resources/js/components/Clients.vue | 416 ------------------ .../js/components/PersonalAccessTokens.vue | 298 ------------- src/PassportServiceProvider.php | 4 - 5 files changed, 829 deletions(-) delete mode 100644 resources/js/components/AuthorizedClients.vue delete mode 100644 resources/js/components/Clients.vue delete mode 100644 resources/js/components/PersonalAccessTokens.vue diff --git a/UPGRADE.md b/UPGRADE.md index e9e179b91..3f1c91239 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -2,10 +2,6 @@ ## General Notes -After updating Passport, you should always re-publish and re-compile the Vue "quickstart" assets if you're using them: - - php artisan vendor:publish --tag=passport-views --force - ## Upgrading To 10.0 From 9.x ### Minimum PHP Version diff --git a/resources/js/components/AuthorizedClients.vue b/resources/js/components/AuthorizedClients.vue deleted file mode 100644 index 3e712cb40..000000000 --- a/resources/js/components/AuthorizedClients.vue +++ /dev/null @@ -1,107 +0,0 @@ - - - - - diff --git a/resources/js/components/Clients.vue b/resources/js/components/Clients.vue deleted file mode 100644 index 522233f57..000000000 --- a/resources/js/components/Clients.vue +++ /dev/null @@ -1,416 +0,0 @@ - - - - - diff --git a/resources/js/components/PersonalAccessTokens.vue b/resources/js/components/PersonalAccessTokens.vue deleted file mode 100644 index 7eedfe975..000000000 --- a/resources/js/components/PersonalAccessTokens.vue +++ /dev/null @@ -1,298 +0,0 @@ - - - - - diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index e5082048b..00ca15290 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -47,10 +47,6 @@ public function boot() __DIR__.'/../resources/views' => base_path('resources/views/vendor/passport'), ], 'passport-views'); - $this->publishes([ - __DIR__.'/../resources/js/components' => base_path('resources/js/components/passport'), - ], 'passport-components'); - $this->publishes([ __DIR__.'/../config/passport.php' => config_path('passport.php'), ], 'passport-config'); From 6713bd16277dbfc5258ac95926ca6949668661fe Mon Sep 17 00:00:00 2001 From: Sergey Pashkevich Date: Mon, 5 Oct 2020 13:56:05 +0300 Subject: [PATCH 194/353] remove unnecessary return form service provider --- src/PassportServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 00ca15290..3f4271285 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -69,7 +69,7 @@ public function boot() protected function registerMigrations() { if (Passport::$runsMigrations && ! config('passport.client_uuids')) { - return $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); } } From ed0e6600e18a8b3cd7690ec7c68dd4d46671e1b1 Mon Sep 17 00:00:00 2001 From: Pataar Date: Mon, 5 Oct 2020 16:04:21 +0200 Subject: [PATCH 195/353] [10.x] Update the badges to use shields.io --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 927b5d810..42a394df0 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@

Build Status -Total Downloads -Latest Stable Version -License +Total Downloads +Latest Stable Version +License

## Introduction From 5758a35582156ca0a116106389dd3d7f1055e1bf Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 26 Oct 2020 13:51:44 +0100 Subject: [PATCH 196/353] Update .gitattributes --- .gitattributes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitattributes b/.gitattributes index 9f9414b4c..5fe92d4cb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,11 @@ * text=auto +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + /.github export-ignore /tests export-ignore .editorconfig export-ignore From 034b7bac89387981c02a52c8d1d30e44b28e1e80 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 25 Nov 2020 17:26:46 +0100 Subject: [PATCH 197/353] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9600708c..c0d49f6ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ ## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) ### Added -- Support Laravel 8 ([#1336](https://github.com/laravel/passport/pull/1336)) +- Support Laravel 8 & drop PHP 7.2 support ([#1336](https://github.com/laravel/passport/pull/1336)) ### Changed - `forceFill` new auth code attributes ([#1266](https://github.com/laravel/passport/pull/1266)) From 032e2e4a7b5ed906106e9d23099c054f442a45c9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 26 Nov 2020 08:53:02 +0100 Subject: [PATCH 198/353] [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); From c2b93a7d8d93cf303bb1eefbfa5610f084f9bdd4 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 26 Nov 2020 08:57:30 +0100 Subject: [PATCH 199/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d49f6ff..285660a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.0.1...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.1.0...10.x) + + +## [v10.1.0 (2020-11-26)](https://github.com/laravel/passport/compare/v10.0.1...v10.1.0) + +### Added +- PHP 8 Support ([#1373](https://github.com/laravel/passport/pull/1373)) + +### Removed +- Remove Vue components ([#1352](https://github.com/laravel/passport/pull/1352)) ## [v10.0.1 (2020-09-15)](https://github.com/laravel/passport/compare/v10.0.0...v10.0.1) From 985577cec359d57df15ac641bfaed84fdc222824 Mon Sep 17 00:00:00 2001 From: Alexander Karlstad Date: Thu, 14 Jan 2021 15:11:49 +0100 Subject: [PATCH 200/353] [10.x] Add purging of invalid refresh tokens to command (#1396) * Delete invalid refresh tokens Delete refresh tokens referring to non-existing access tokens. * Use whereDoesntHave() instead * Add test for purge command * Update description and output of command * Update PurgeCommand.php Co-authored-by: Taylor Otwell --- src/Console/PurgeCommand.php | 11 ++++--- tests/Feature/Console/PurgeCommand.php | 45 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 tests/Feature/Console/PurgeCommand.php diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 7854c6ab2..7b97783f1 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -22,7 +22,7 @@ class PurgeCommand extends Command * * @var string */ - protected $description = 'Purge revoked and / or expired tokens and authentication codes'; + protected $description = 'Purge revoked and / or expired tokens, authentication codes, and refresh tokens.'; /** * Execute the console command. @@ -36,20 +36,23 @@ public function handle() Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged revoked items and items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens, revoked tokens, and tokens expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged revoked items.'); + $this->info('Purged invalid refresh tokens and revoked tokens.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens and tokens expired for more than seven days.'); } } } diff --git a/tests/Feature/Console/PurgeCommand.php b/tests/Feature/Console/PurgeCommand.php new file mode 100644 index 000000000..baed3424d --- /dev/null +++ b/tests/Feature/Console/PurgeCommand.php @@ -0,0 +1,45 @@ +subDays(8); + $notExpired = now(); + + $accessTokenExpired = Token::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); + $accessTokenRevoked = Token::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); + $accessTokenOk = Token::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); + + $authCodeExpired = AuthCode::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); + $authCodeRevoked = AuthCode::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); + $authCodeOk = AuthCode::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); + + $refreshTokenExpired = RefreshToken::create(['id' => 'a', 'access_token_id' => $accessTokenExpired->id, 'revoked' => 0, 'expires_at' => $expired]); + $refreshTokenRevoked = RefreshToken::create(['id' => 'b', 'access_token_id' => $accessTokenRevoked->id, 'revoked' => 1, 'expires_at' => $notExpired]); + $refreshTokenInvalidAccessToken = RefreshToken::create(['id' => 'c', 'access_token_id' => 'xyz', 'revoked' => 0, 'expires_at' => $notExpired]); + $refreshTokenOk = RefreshToken::create(['id' => 'd', 'access_token_id' => $accessTokenOk->id, 'revoked' => 0, 'expires_at' => $notExpired]); + + $this->artisan('passport:purge'); + + $this->assertFalse(Token::whereKey($accessTokenExpired->id)->exists()); + $this->assertFalse(Token::whereKey($accessTokenRevoked->id)->exists()); + $this->assertTrue(Token::whereKey($accessTokenOk->id)->exists()); + + $this->assertFalse(AuthCode::whereKey($authCodeExpired->id)->exists()); + $this->assertFalse(AuthCode::whereKey($authCodeRevoked->id)->exists()); + $this->assertTrue(AuthCode::whereKey($authCodeOk->id)->exists()); + + $this->assertFalse(RefreshToken::whereKey($refreshTokenExpired->id)->exists()); + $this->assertFalse(RefreshToken::whereKey($refreshTokenRevoked->id)->exists()); + $this->assertFalse(RefreshToken::whereKey($refreshTokenInvalidAccessToken->id)->exists()); + $this->assertTrue(RefreshToken::whereKey($refreshTokenOk->id)->exists()); + } +} From 8b792b4f614bd1b955d24a3ceec3521dba727e35 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 14 Jan 2021 17:28:55 +0100 Subject: [PATCH 201/353] Revert "[10.x] Add purging of invalid refresh tokens to command (#1396)" (#1397) This reverts commit 985577cec359d57df15ac641bfaed84fdc222824. --- src/Console/PurgeCommand.php | 11 +++---- tests/Feature/Console/PurgeCommand.php | 45 -------------------------- 2 files changed, 4 insertions(+), 52 deletions(-) delete mode 100644 tests/Feature/Console/PurgeCommand.php diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 7b97783f1..7854c6ab2 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -22,7 +22,7 @@ class PurgeCommand extends Command * * @var string */ - protected $description = 'Purge revoked and / or expired tokens, authentication codes, and refresh tokens.'; + protected $description = 'Purge revoked and / or expired tokens and authentication codes'; /** * Execute the console command. @@ -36,23 +36,20 @@ public function handle() Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); - Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens, revoked tokens, and tokens expired for more than seven days.'); + $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); - Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens and revoked tokens.'); + $this->info('Purged revoked items.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); - Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens and tokens expired for more than seven days.'); + $this->info('Purged items expired for more than seven days.'); } } } diff --git a/tests/Feature/Console/PurgeCommand.php b/tests/Feature/Console/PurgeCommand.php deleted file mode 100644 index baed3424d..000000000 --- a/tests/Feature/Console/PurgeCommand.php +++ /dev/null @@ -1,45 +0,0 @@ -subDays(8); - $notExpired = now(); - - $accessTokenExpired = Token::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); - $accessTokenRevoked = Token::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); - $accessTokenOk = Token::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); - - $authCodeExpired = AuthCode::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); - $authCodeRevoked = AuthCode::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); - $authCodeOk = AuthCode::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); - - $refreshTokenExpired = RefreshToken::create(['id' => 'a', 'access_token_id' => $accessTokenExpired->id, 'revoked' => 0, 'expires_at' => $expired]); - $refreshTokenRevoked = RefreshToken::create(['id' => 'b', 'access_token_id' => $accessTokenRevoked->id, 'revoked' => 1, 'expires_at' => $notExpired]); - $refreshTokenInvalidAccessToken = RefreshToken::create(['id' => 'c', 'access_token_id' => 'xyz', 'revoked' => 0, 'expires_at' => $notExpired]); - $refreshTokenOk = RefreshToken::create(['id' => 'd', 'access_token_id' => $accessTokenOk->id, 'revoked' => 0, 'expires_at' => $notExpired]); - - $this->artisan('passport:purge'); - - $this->assertFalse(Token::whereKey($accessTokenExpired->id)->exists()); - $this->assertFalse(Token::whereKey($accessTokenRevoked->id)->exists()); - $this->assertTrue(Token::whereKey($accessTokenOk->id)->exists()); - - $this->assertFalse(AuthCode::whereKey($authCodeExpired->id)->exists()); - $this->assertFalse(AuthCode::whereKey($authCodeRevoked->id)->exists()); - $this->assertTrue(AuthCode::whereKey($authCodeOk->id)->exists()); - - $this->assertFalse(RefreshToken::whereKey($refreshTokenExpired->id)->exists()); - $this->assertFalse(RefreshToken::whereKey($refreshTokenRevoked->id)->exists()); - $this->assertFalse(RefreshToken::whereKey($refreshTokenInvalidAccessToken->id)->exists()); - $this->assertTrue(RefreshToken::whereKey($refreshTokenOk->id)->exists()); - } -} From b28cd974cbdca374c15a8ba6cd3533c2719e2447 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 18 Feb 2021 16:06:38 +0100 Subject: [PATCH 202/353] Update to phpseclib v3 (#1410) --- composer.json | 2 +- src/Console/KeysCommand.php | 12 +++++------- tests/Unit/KeysCommandTest.php | 9 +++------ 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 319a8c4b8..4eb1089da 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "league/oauth2-server": "^8.2", "lcobucci/jwt": "^3.4|^4.0", "nyholm/psr7": "^1.3", - "phpseclib/phpseclib": "^2.0", + "phpseclib/phpseclib": "^3.0", "symfony/psr-http-message-bridge": "^2.0" }, "require-dev": { diff --git a/src/Console/KeysCommand.php b/src/Console/KeysCommand.php index ac0a5f165..b0851acec 100644 --- a/src/Console/KeysCommand.php +++ b/src/Console/KeysCommand.php @@ -3,9 +3,8 @@ namespace Laravel\Passport\Console; use Illuminate\Console\Command; -use Illuminate\Support\Arr; use Laravel\Passport\Passport; -use phpseclib\Crypt\RSA; +use phpseclib3\Crypt\RSA; class KeysCommand extends Command { @@ -28,10 +27,9 @@ class KeysCommand extends Command /** * Execute the console command. * - * @param \phpseclib\Crypt\RSA $rsa * @return void */ - public function handle(RSA $rsa) + public function handle() { [$publicKey, $privateKey] = [ Passport::keyPath('oauth-public.key'), @@ -41,10 +39,10 @@ public function handle(RSA $rsa) if ((file_exists($publicKey) || file_exists($privateKey)) && ! $this->option('force')) { $this->error('Encryption keys already exist. Use the --force option to overwrite them.'); } else { - $keys = $rsa->createKey($this->input ? (int) $this->option('length') : 4096); + $key = RSA::createKey($this->input ? (int) $this->option('length') : 4096); - file_put_contents($publicKey, Arr::get($keys, 'publickey')); - file_put_contents($privateKey, Arr::get($keys, 'privatekey')); + file_put_contents($publicKey, (string) $key->getPublicKey()); + file_put_contents($privateKey, (string) $key); $this->info('Encryption keys generated successfully.'); } diff --git a/tests/Unit/KeysCommandTest.php b/tests/Unit/KeysCommandTest.php index e85f64a29..991d21564 100644 --- a/tests/Unit/KeysCommandTest.php +++ b/tests/Unit/KeysCommandTest.php @@ -6,7 +6,6 @@ use Laravel\Passport\Console\KeysCommand; use Laravel\Passport\Passport; use Mockery as m; -use phpseclib\Crypt\RSA; use PHPUnit\Framework\TestCase; class KeysCommandTest extends TestCase @@ -41,9 +40,7 @@ public function testPrivateAndPublicKeysAreGenerated() Container::getInstance()->instance('path.storage', self::KEYS); - $rsa = new RSA(); - - $command->handle($rsa); + $command->handle(); $this->assertFileExists(self::PUBLIC_KEY); $this->assertFileExists(self::PRIVATE_KEY); @@ -59,7 +56,7 @@ public function testPrivateAndPublicKeysAreGeneratedInCustomPath() ->with('Encryption keys generated successfully.') ->getMock(); - $command->handle(new RSA); + $command->handle(); $this->assertFileExists(self::PUBLIC_KEY); $this->assertFileExists(self::PRIVATE_KEY); @@ -79,6 +76,6 @@ public function testPrivateAndPublicKeysShouldNotBeGeneratedTwice($command) $command->shouldReceive('error') ->with('Encryption keys already exist. Use the --force option to overwrite them.'); - $command->handle(new RSA); + $command->handle(); } } From fb950814a5bf86473a53f98c14312b761e1b0a39 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 22 Feb 2021 15:13:46 +0100 Subject: [PATCH 203/353] Revert model DB connection customization (#1412) --- config/passport.php | 17 ---------- ...1_000001_create_oauth_auth_codes_table.php | 31 ++----------------- ...00002_create_oauth_access_tokens_table.php | 31 ++----------------- ...0003_create_oauth_refresh_tokens_table.php | 31 ++----------------- ...6_01_000004_create_oauth_clients_table.php | 31 ++----------------- ...te_oauth_personal_access_clients_table.php | 31 ++----------------- src/AuthCode.php | 10 ------ src/Client.php | 10 ------ src/PersonalAccessClient.php | 10 ------ src/RefreshToken.php | 10 ------ src/Token.php | 10 ------ tests/Feature/PassportTestCase.php | 2 -- 12 files changed, 10 insertions(+), 214 deletions(-) diff --git a/config/passport.php b/config/passport.php index 162f1f84a..79c59acb1 100644 --- a/config/passport.php +++ b/config/passport.php @@ -46,21 +46,4 @@ 'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'), ], - /* - |-------------------------------------------------------------------------- - | Passport Storage Driver - |-------------------------------------------------------------------------- - | - | This configuration value allows you to customize the storage options - | for Passport, such as the database connection that should be used - | by Passport's internal database models which store tokens, etc. - | - */ - - 'storage' => [ - 'database' => [ - 'connection' => env('DB_CONNECTION', 'mysql'), - ], - ], - ]; diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 0eabf059c..6c47d2473 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -6,23 +6,6 @@ class CreateOauthAuthCodesTable extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. * @@ -30,7 +13,7 @@ public function __construct() */ public function up() { - $this->schema->create('oauth_auth_codes', function (Blueprint $table) { + Schema::create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->index(); $table->unsignedBigInteger('client_id'); @@ -47,16 +30,6 @@ public function up() */ public function down() { - $this->schema->dropIfExists('oauth_auth_codes'); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_auth_codes'); } } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 67c682d5f..00f00633a 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -6,23 +6,6 @@ class CreateOauthAccessTokensTable extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. * @@ -30,7 +13,7 @@ public function __construct() */ public function up() { - $this->schema->create('oauth_access_tokens', function (Blueprint $table) { + Schema::create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->unsignedBigInteger('client_id'); @@ -49,16 +32,6 @@ public function up() */ public function down() { - $this->schema->dropIfExists('oauth_access_tokens'); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_access_tokens'); } } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index b4ac09544..60c523489 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -6,23 +6,6 @@ class CreateOauthRefreshTokensTable extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. * @@ -30,7 +13,7 @@ public function __construct() */ public function up() { - $this->schema->create('oauth_refresh_tokens', function (Blueprint $table) { + Schema::create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->string('access_token_id', 100)->index(); $table->boolean('revoked'); @@ -45,16 +28,6 @@ public function up() */ public function down() { - $this->schema->dropIfExists('oauth_refresh_tokens'); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_refresh_tokens'); } } diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 6ce3d9974..f0884ee7b 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -6,33 +6,6 @@ class CreateOauthClientsTable extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. * @@ -40,7 +13,7 @@ public function getConnection() */ public function up() { - $this->schema->create('oauth_clients', function (Blueprint $table) { + Schema::create('oauth_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->string('name'); @@ -61,6 +34,6 @@ public function up() */ public function down() { - $this->schema->dropIfExists('oauth_clients'); + Schema::dropIfExists('oauth_clients'); } } diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index c408248f5..4b56435ce 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -6,23 +6,6 @@ class CreateOauthPersonalAccessClientsTable extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. * @@ -30,7 +13,7 @@ public function __construct() */ public function up() { - $this->schema->create('oauth_personal_access_clients', function (Blueprint $table) { + Schema::create('oauth_personal_access_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('client_id'); $table->timestamps(); @@ -44,16 +27,6 @@ public function up() */ public function down() { - $this->schema->dropIfExists('oauth_personal_access_clients'); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_personal_access_clients'); } } diff --git a/src/AuthCode.php b/src/AuthCode.php index 94441b5f7..09a79c826 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -68,14 +68,4 @@ public function client() { return $this->belongsTo(Passport::clientModel()); } - - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } } diff --git a/src/Client.php b/src/Client.php index f75fb7b97..7313b40d8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -184,16 +184,6 @@ public function getIncrementing() return Passport::clientUuids() ? false : $this->incrementing; } - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } - /** * Create a new factory instance for the model. * diff --git a/src/PersonalAccessClient.php b/src/PersonalAccessClient.php index 1d35b0504..171b982ab 100644 --- a/src/PersonalAccessClient.php +++ b/src/PersonalAccessClient.php @@ -29,14 +29,4 @@ public function client() { return $this->belongsTo(Passport::clientModel()); } - - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } } diff --git a/src/RefreshToken.php b/src/RefreshToken.php index 376a97b82..00e5a1c84 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -88,14 +88,4 @@ public function transient() { return false; } - - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } } diff --git a/src/Token.php b/src/Token.php index 9dfd874c6..4a0a13d17 100644 --- a/src/Token.php +++ b/src/Token.php @@ -160,14 +160,4 @@ public function transient() { return false; } - - /** - * Get the current connection name for the model. - * - * @return string|null - */ - public function getConnectionName() - { - return config('passport.storage.database.connection') ?? $this->connection; - } } diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index d7da023cb..47a752fee 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -44,8 +44,6 @@ protected function getEnvironmentSetUp($app) $app['config']->set('database.default', 'testbench'); - $app['config']->set('passport.storage.database.connection', 'testbench'); - $app['config']->set('database.connections.testbench', [ 'driver' => 'sqlite', 'database' => ':memory:', From 2ed01909228b049f6ea0aa2d4b0ae78d3b27bee3 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 23 Feb 2021 21:45:29 +0100 Subject: [PATCH 204/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 285660a56..681503a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.1.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.1.1...10.x) + + +## [v10.1.1 (2021-02-23)](https://github.com/laravel/passport/compare/v10.1.0...v10.1.1) + +### Changed +- Update to phpseclib v3 ([#1410](https://github.com/laravel/passport/pull/1410)) ## [v10.1.0 (2020-11-26)](https://github.com/laravel/passport/compare/v10.0.1...v10.1.0) From d429a9823dc6ba00b607efa3b73c76e17f547e57 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 1 Mar 2021 14:37:32 +0100 Subject: [PATCH 205/353] [10.x] Backport phpseclib v2 (#1418) * Backport support for phpseclib v2 * Apply fixes from StyleCI (#1417) --- composer.json | 4 ++-- src/Console/KeysCommand.php | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 4eb1089da..0726c28c7 100644 --- a/composer.json +++ b/composer.json @@ -26,10 +26,10 @@ "illuminate/encryption": "^8.2", "illuminate/http": "^8.2", "illuminate/support": "^8.2", - "league/oauth2-server": "^8.2", "lcobucci/jwt": "^3.4|^4.0", + "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", - "phpseclib/phpseclib": "^3.0", + "phpseclib/phpseclib": "^2.0|^3.0", "symfony/psr-http-message-bridge": "^2.0" }, "require-dev": { diff --git a/src/Console/KeysCommand.php b/src/Console/KeysCommand.php index b0851acec..36ff6e6c6 100644 --- a/src/Console/KeysCommand.php +++ b/src/Console/KeysCommand.php @@ -3,7 +3,9 @@ namespace Laravel\Passport\Console; use Illuminate\Console\Command; +use Illuminate\Support\Arr; use Laravel\Passport\Passport; +use phpseclib\Crypt\RSA as LegacyRSA; use phpseclib3\Crypt\RSA; class KeysCommand extends Command @@ -39,10 +41,17 @@ public function handle() if ((file_exists($publicKey) || file_exists($privateKey)) && ! $this->option('force')) { $this->error('Encryption keys already exist. Use the --force option to overwrite them.'); } else { - $key = RSA::createKey($this->input ? (int) $this->option('length') : 4096); + if (class_exists(LegacyRSA::class)) { + $keys = (new LegacyRSA)->createKey($this->input ? (int) $this->option('length') : 4096); - file_put_contents($publicKey, (string) $key->getPublicKey()); - file_put_contents($privateKey, (string) $key); + file_put_contents($publicKey, Arr::get($keys, 'publickey')); + file_put_contents($privateKey, Arr::get($keys, 'privatekey')); + } else { + $key = RSA::createKey($this->input ? (int) $this->option('length') : 4096); + + file_put_contents($publicKey, (string) $key->getPublicKey()); + file_put_contents($privateKey, (string) $key); + } $this->info('Encryption keys generated successfully.'); } From 9f1a5d56eb609250104afc38cf407f7c2520cda3 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 2 Mar 2021 17:40:00 +0100 Subject: [PATCH 206/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 681503a4e..a79e5347e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.1.1...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.1.2...10.x) + + +## [v10.1.2 (2021-03-02)](https://github.com/laravel/passport/compare/v10.1.1...v10.1.2) + +### Fixed +- Backport phpseclib v2 ([#1418](https://github.com/laravel/passport/pull/1418)) ## [v10.1.1 (2021-02-23)](https://github.com/laravel/passport/compare/v10.1.0...v10.1.1) From c7c798f872a29cebcf9979e8d7c4e53e8d4eb77d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 5 Mar 2021 22:01:37 +0100 Subject: [PATCH 207/353] Use ubuntu-18.04 --- .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 ad2acaee8..6f8cfb443 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,15 +8,15 @@ on: jobs: tests: + runs-on: ubuntu-18.04 - runs-on: ubuntu-latest strategy: fail-fast: true matrix: php: [7.3, 7.4, 8.0] laravel: [^8.0] - name: P${{ matrix.php }} - L${{ matrix.laravel }} + name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} steps: - name: Checkout code From 2138d5941cb7aaae0d745925e7807faf9c1479cc Mon Sep 17 00:00:00 2001 From: baijunyao Date: Mon, 8 Mar 2021 04:26:25 +0800 Subject: [PATCH 208/353] Fix `$userId` type (#1422) --- src/Events/AccessTokenCreated.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Events/AccessTokenCreated.php b/src/Events/AccessTokenCreated.php index 6922c76ef..bcaf0d650 100644 --- a/src/Events/AccessTokenCreated.php +++ b/src/Events/AccessTokenCreated.php @@ -29,7 +29,7 @@ class AccessTokenCreated * Create a new event instance. * * @param string $tokenId - * @param string $userId + * @param string|int|null $userId * @param string $clientId * @return void */ From ab9e2045e0d8649cd84de411d0332bdd5fe763a3 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 11 Mar 2021 17:44:50 +0100 Subject: [PATCH 209/353] Update tests.yml --- .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 6f8cfb443..0e5539a6e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ on: jobs: tests: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 strategy: fail-fast: true From 66b9088993f1be9a4a95129b61dca951e04223ff Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 16 Mar 2021 18:09:22 +0100 Subject: [PATCH 210/353] Allow timestamps on Token model (#1425) --- src/Token.php | 7 ------- tests/Unit/BridgeAccessTokenRepositoryTest.php | 5 +++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Token.php b/src/Token.php index 4a0a13d17..6f5d7b94f 100644 --- a/src/Token.php +++ b/src/Token.php @@ -53,13 +53,6 @@ class Token extends Model 'expires_at', ]; - /** - * Indicates if the model should be timestamped. - * - * @var bool - */ - public $timestamps = false; - /** * Get the client that the token belongs to. * diff --git a/tests/Unit/BridgeAccessTokenRepositoryTest.php b/tests/Unit/BridgeAccessTokenRepositoryTest.php index 0d34d9b45..aa99cd051 100644 --- a/tests/Unit/BridgeAccessTokenRepositoryTest.php +++ b/tests/Unit/BridgeAccessTokenRepositoryTest.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Tests\Unit; use Carbon\CarbonImmutable; +use DateTime; use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Bridge\AccessToken; use Laravel\Passport\Bridge\AccessTokenRepository; @@ -32,8 +33,8 @@ public function test_access_tokens_can_be_persisted() $this->assertSame('client-id', $array['client_id']); $this->assertEquals(['scopes'], $array['scopes']); $this->assertEquals(false, $array['revoked']); - $this->assertInstanceOf('DateTime', $array['created_at']); - $this->assertInstanceOf('DateTime', $array['updated_at']); + $this->assertInstanceOf(DateTime::class, $array['created_at']); + $this->assertInstanceOf(DateTime::class, $array['updated_at']); $this->assertEquals($expiration, $array['expires_at']); }); From e3478dedd938671b7598239cc8554f77de9ab9c7 Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Mon, 5 Apr 2021 16:45:08 +0200 Subject: [PATCH 211/353] fix binding --- src/PassportServiceProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index a8a0b78ff..1d6e7ec7c 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -249,9 +249,9 @@ protected function registerJWTParser() */ protected function registerResourceServer() { - $this->app->singleton(ResourceServer::class, function () { + $this->app->singleton(ResourceServer::class, function ($container) { return new ResourceServer( - $this->app->make(Bridge\AccessTokenRepository::class), + $container->make(Bridge\AccessTokenRepository::class), $this->makeCryptKey('public') ); }); From 3d1e6bbdedf71efb147f3b5205259e8b20c2e6ad Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 5 Apr 2021 13:44:12 -0500 Subject: [PATCH 212/353] use app helper --- src/PassportServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 1d6e7ec7c..daeb04422 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -284,7 +284,7 @@ protected function registerGuard() Auth::resolved(function ($auth) { $auth->extend('passport', function ($app, $name, array $config) { return tap($this->makeGuard($config), function ($guard) { - $this->app->refresh('request', $guard, 'setRequest'); + app()->refresh('request', $guard, 'setRequest'); }); }); }); From a5e4471dd99b7638ab5ca3ecab6cd87cf37eb410 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 6 Apr 2021 16:30:45 +0200 Subject: [PATCH 213/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79e5347e..cf2be114e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.1.2...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.1.3...10.x) + + +## [v10.1.3 (2021-04-06)](https://github.com/laravel/passport/compare/v10.1.2...v10.1.3) + +### Changed +- Use app helper ([3d1e6bb](https://github.com/laravel/passport/commit/3d1e6bbdedf71efb147f3b5205259e8b20c2e6ad)) + +### Fixed +- Fix binding ([e3478de](https://github.com/laravel/passport/commit/e3478dedd938671b7598239cc8554f77de9ab9c7)) ## [v10.1.2 (2021-03-02)](https://github.com/laravel/passport/compare/v10.1.1...v10.1.2) From 95bdc167391f2aba326eda674f58d7e77dd8ae60 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 26 May 2021 11:42:54 +0200 Subject: [PATCH 214/353] Improve authenticateViaBearerToken() performance --- src/Guards/TokenGuard.php | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 7d81ed068..da69464a8 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -81,23 +81,6 @@ public function __construct( $this->encrypter = $encrypter; } - /** - * Determine if the requested provider matches the client's provider. - * - * @param \Illuminate\Http\Request $request - * @return bool - */ - protected function hasValidProvider(Request $request) - { - $client = $this->client($request); - - if ($client && ! $client->provider) { - return true; - } - - return $client && $client->provider === $this->provider->getProviderName(); - } - /** * Get the user for the incoming request. * @@ -148,7 +131,17 @@ protected function authenticateViaBearerToken($request) return; } - if (! $this->hasValidProvider($request)) { + $client = $this->clients->findActive( + $psr->getAttribute('oauth_client_id') + ); + + // Verify if the client that issued this token exists and is still valid + if (! $client) { + return; + } + + // Verify if the client that issued this token matches the requested provider. + if ($client->provider && $client->provider !== $this->provider->getProviderName()) { return; } @@ -170,15 +163,6 @@ protected function authenticateViaBearerToken($request) $psr->getAttribute('oauth_access_token_id') ); - $clientId = $psr->getAttribute('oauth_client_id'); - - // Finally, we will verify if the client that issued this token is still valid and - // its tokens may still be used. If not, we will bail out since we don't want a - // user to be able to send access tokens for deleted or revoked applications. - if ($this->clients->revoked($clientId)) { - return; - } - return $token ? $user->withAccessToken($token) : null; } From b69f25a69ffe2897fff397ff56994f059538201e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 26 May 2021 08:09:39 -0500 Subject: [PATCH 215/353] formatting --- src/Guards/TokenGuard.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index da69464a8..88381f0be 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -135,13 +135,9 @@ protected function authenticateViaBearerToken($request) $psr->getAttribute('oauth_client_id') ); - // Verify if the client that issued this token exists and is still valid - if (! $client) { - return; - } - - // Verify if the client that issued this token matches the requested provider. - if ($client->provider && $client->provider !== $this->provider->getProviderName()) { + if (! $client || + ($client->provider && + $client->provider !== $this->provider->getProviderName())) { return; } From cafb8e64a91f905ff5ab3f85836371216554f379 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 4 Jun 2021 17:33:04 +0200 Subject: [PATCH 216/353] Update 1_Bug_report.md --- .github/ISSUE_TEMPLATE/1_Bug_report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md index 5d665d723..2d7b68a23 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.md @@ -15,3 +15,6 @@ about: "Report something that's broken. Please ensure your Laravel version is st ### Steps To Reproduce: + + + From 519e1df2062e1524d1ed352ccc2227cac882f667 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Fri, 4 Jun 2021 19:26:16 +0100 Subject: [PATCH 217/353] [10.x] Use Real Keys in Tests (#1450) * use real keys in tests * revert composer change * reset position of loadKeysFrom() function --- tests/Unit/PassportServiceProviderTest.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/Unit/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php index a1e24828f..9fc237432 100644 --- a/tests/Unit/PassportServiceProviderTest.php +++ b/tests/Unit/PassportServiceProviderTest.php @@ -13,10 +13,14 @@ class PassportServiceProviderTest extends TestCase { public function test_can_use_crypto_keys_from_config() { - $config = m::mock(Config::class, function ($config) { + $privateKey = openssl_pkey_new(); + + openssl_pkey_export($privateKey, $privateKeyString); + + $config = m::mock(Config::class, function ($config) use ($privateKeyString) { $config->shouldReceive('get') ->with('passport.private_key') - ->andReturn('-----BEGIN RSA PRIVATE KEY-----\nconfig\n-----END RSA PRIVATE KEY-----'); + ->andReturn($privateKeyString); }); $provider = new PassportServiceProvider( @@ -29,7 +33,7 @@ public function test_can_use_crypto_keys_from_config() })->call($provider); $this->assertSame( - "-----BEGIN RSA PRIVATE KEY-----\nconfig\n-----END RSA PRIVATE KEY-----", + $privateKeyString, file_get_contents($cryptKey->getKeyPath()) ); } @@ -38,10 +42,10 @@ public function test_can_use_crypto_keys_from_local_disk() { Passport::loadKeysFrom(__DIR__.'/../keys'); - file_put_contents( - __DIR__.'/../keys/oauth-private.key', - "-----BEGIN RSA PRIVATE KEY-----\ndisk\n-----END RSA PRIVATE KEY-----" - ); + $privateKey = openssl_pkey_new(); + + openssl_pkey_export_to_file($privateKey, __DIR__.'/../keys/oauth-private.key'); + openssl_pkey_export($privateKey, $privateKeyString); $config = m::mock(Config::class, function ($config) { $config->shouldReceive('get')->with('passport.private_key')->andReturn(null); @@ -57,7 +61,7 @@ public function test_can_use_crypto_keys_from_local_disk() })->call($provider); $this->assertSame( - "-----BEGIN RSA PRIVATE KEY-----\ndisk\n-----END RSA PRIVATE KEY-----", + $privateKeyString, file_get_contents($cryptKey->getKeyPath()) ); From 4b28beb7657652e7ee710148375a00bb49902acd Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Sat, 12 Jun 2021 20:09:02 +0200 Subject: [PATCH 218/353] dark mode logo --- README.md | 2 +- art/logo.svg | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 art/logo.svg diff --git a/README.md b/README.md index 42a394df0..dbc5062df 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

Logo Laravel Passport

Build Status diff --git a/art/logo.svg b/art/logo.svg new file mode 100644 index 000000000..ef46d183a --- /dev/null +++ b/art/logo.svg @@ -0,0 +1,9 @@ + + + + From 12678fbe8c6b661e61736630db55e98d13ccad77 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Sun, 13 Jun 2021 11:40:01 +0200 Subject: [PATCH 219/353] wip --- .gitattributes | 1 + art/logo.svg | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index 5fe92d4cb..efd7a3a8e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,7 @@ *.php diff=php /.github export-ignore +/art export-ignore /tests export-ignore .editorconfig export-ignore .gitattributes export-ignore diff --git a/art/logo.svg b/art/logo.svg index ef46d183a..913321afa 100644 --- a/art/logo.svg +++ b/art/logo.svg @@ -1,9 +1,3 @@ - - + From 7a026acac7576224474f9f51b3b04d8b4541c0e7 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Sun, 18 Jul 2021 18:05:25 +0200 Subject: [PATCH 220/353] [11.x] Refactor routes to dedicated file (#1464) * Refactor routes to dedicated file * Update web.php * Apply fixes from StyleCI (#1465) * formatting Co-authored-by: Taylor Otwell --- routes/web.php | 81 ++++++++++++++ src/Passport.php | 26 ----- src/PassportServiceProvider.php | 77 +++++++++++--- src/RouteRegistrar.php | 165 ----------------------------- tests/Feature/PassportTestCase.php | 3 - 5 files changed, 143 insertions(+), 209 deletions(-) create mode 100644 routes/web.php delete mode 100644 src/RouteRegistrar.php diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 000000000..dfe69dc9e --- /dev/null +++ b/routes/web.php @@ -0,0 +1,81 @@ + 'AccessTokenController@issueToken', + 'as' => 'token', + 'middleware' => 'throttle', +]); + +Route::middleware(['web', 'auth'])->group(function () { + Route::post('/token/refresh', [ + 'uses' => 'TransientTokenController@refresh', + 'as' => 'token.refresh', + ]); + + Route::get('/authorize', [ + 'uses' => 'AuthorizationController@authorize', + 'as' => 'authorizations.authorize', + ]); + + Route::post('/authorize', [ + 'uses' => 'ApproveAuthorizationController@approve', + 'as' => 'authorizations.approve', + ]); + + Route::delete('/authorize', [ + 'uses' => 'DenyAuthorizationController@deny', + 'as' => 'authorizations.deny', + ]); + + Route::get('/tokens', [ + 'uses' => 'AuthorizedAccessTokenController@forUser', + 'as' => 'tokens.index', + ]); + + Route::delete('/tokens/{token_id}', [ + 'uses' => 'AuthorizedAccessTokenController@destroy', + 'as' => 'tokens.destroy', + ]); + + Route::get('/clients', [ + 'uses' => 'ClientController@forUser', + 'as' => 'clients.index', + ]); + + Route::post('/clients', [ + 'uses' => 'ClientController@store', + 'as' => 'clients.store', + ]); + + Route::put('/clients/{client_id}', [ + 'uses' => 'ClientController@update', + 'as' => 'clients.update', + ]); + + Route::delete('/clients/{client_id}', [ + 'uses' => 'ClientController@destroy', + 'as' => 'clients.destroy', + ]); + + Route::get('/scopes', [ + 'uses' => 'ScopeController@all', + 'as' => 'scopes.index', + ]); + + Route::get('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@forUser', + 'as' => 'personal.tokens.index', + ]); + + Route::post('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@store', + 'as' => 'personal.tokens.store', + ]); + + Route::delete('/personal-access-tokens/{token_id}', [ + 'uses' => 'PersonalAccessTokenController@destroy', + 'as' => 'personal.tokens.destroy', + ]); +}); diff --git a/src/Passport.php b/src/Passport.php index 0db48e26d..8ca81ed49 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -5,7 +5,6 @@ use Carbon\Carbon; use DateInterval; use DateTimeInterface; -use Illuminate\Support\Facades\Route; use League\OAuth2\Server\ResourceServer; use Mockery; use Psr\Http\Message\ServerRequestInterface; @@ -157,31 +156,6 @@ public static function enableImplicitGrant() return new static; } - /** - * Binds the Passport routes into the controller. - * - * @param callable|null $callback - * @param array $options - * @return void - */ - public static function routes($callback = null, array $options = []) - { - $callback = $callback ?: function ($router) { - $router->all(); - }; - - $defaultOptions = [ - 'prefix' => 'oauth', - 'namespace' => '\Laravel\Passport\Http\Controllers', - ]; - - $options = array_merge($defaultOptions, $options); - - Route::group($options, function ($router) use ($callback) { - $callback(new RouteRegistrar($router)); - }); - } - /** * Set the default scope(s). Multiple scopes may be an array or specified delimited by spaces. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index daeb04422..de02ca4ee 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Request; +use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; use Laravel\Passport\Bridge\PersonalAccessGrant; use Laravel\Passport\Bridge\RefreshTokenRepository; @@ -34,13 +35,61 @@ class PassportServiceProvider extends ServiceProvider */ public function boot() { - $this->loadViewsFrom(__DIR__.'/../resources/views', 'passport'); + $this->registerRoutes(); + $this->registerResources(); + $this->registerMigrations(); + $this->registerPublishing(); + $this->registerCommands(); $this->deleteCookieOnLogout(); + } - if ($this->app->runningInConsole()) { - $this->registerMigrations(); + /** + * Register the Passport routes. + * + * @return void + */ + protected function registerRoutes() + { + Route::group([ + 'as' => 'passport.', + 'prefix' => config('passport.path', 'oauth'), + 'namespace' => 'Laravel\Passport\Http\Controllers', + ], function () { + $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); + }); + } + + /** + * Register the Passport resources. + * + * @return void + */ + protected function registerResources() + { + $this->loadViewsFrom(__DIR__.'/../resources/views', 'passport'); + } + + /** + * Register the Passport migration files. + * + * @return void + */ + protected function registerMigrations() + { + if ($this->app->runningInConsole() && Passport::$runsMigrations && ! config('passport.client_uuids')) { + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + } + } + /** + * Register the package's publishable resources. + * + * @return void + */ + protected function registerPublishing() + { + if ($this->app->runningInConsole()) { $this->publishes([ __DIR__.'/../database/migrations' => database_path('migrations'), ], 'passport-migrations'); @@ -52,26 +101,24 @@ public function boot() $this->publishes([ __DIR__.'/../config/passport.php' => config_path('passport.php'), ], 'passport-config'); - - $this->commands([ - Console\InstallCommand::class, - Console\ClientCommand::class, - Console\HashCommand::class, - Console\KeysCommand::class, - Console\PurgeCommand::class, - ]); } } /** - * Register Passport's migration files. + * Register the Passport Artisan commands. * * @return void */ - protected function registerMigrations() + protected function registerCommands() { - if (Passport::$runsMigrations && ! config('passport.client_uuids')) { - $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + if ($this->app->runningInConsole()) { + $this->commands([ + Console\InstallCommand::class, + Console\ClientCommand::class, + Console\HashCommand::class, + Console\KeysCommand::class, + Console\PurgeCommand::class, + ]); } } diff --git a/src/RouteRegistrar.php b/src/RouteRegistrar.php deleted file mode 100644 index 12ab3d74e..000000000 --- a/src/RouteRegistrar.php +++ /dev/null @@ -1,165 +0,0 @@ -router = $router; - } - - /** - * Register routes for transient tokens, clients, and personal access tokens. - * - * @return void - */ - public function all() - { - $this->forAuthorization(); - $this->forAccessTokens(); - $this->forTransientTokens(); - $this->forClients(); - $this->forPersonalAccessTokens(); - } - - /** - * Register the routes needed for authorization. - * - * @return void - */ - public function forAuthorization() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/authorize', [ - 'uses' => 'AuthorizationController@authorize', - 'as' => 'passport.authorizations.authorize', - ]); - - $router->post('/authorize', [ - 'uses' => 'ApproveAuthorizationController@approve', - 'as' => 'passport.authorizations.approve', - ]); - - $router->delete('/authorize', [ - 'uses' => 'DenyAuthorizationController@deny', - 'as' => 'passport.authorizations.deny', - ]); - }); - } - - /** - * Register the routes for retrieving and issuing access tokens. - * - * @return void - */ - public function forAccessTokens() - { - $this->router->post('/token', [ - 'uses' => 'AccessTokenController@issueToken', - 'as' => 'passport.token', - 'middleware' => 'throttle', - ]); - - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/tokens', [ - 'uses' => 'AuthorizedAccessTokenController@forUser', - 'as' => 'passport.tokens.index', - ]); - - $router->delete('/tokens/{token_id}', [ - 'uses' => 'AuthorizedAccessTokenController@destroy', - 'as' => 'passport.tokens.destroy', - ]); - }); - } - - /** - * Register the routes needed for refreshing transient tokens. - * - * @return void - */ - public function forTransientTokens() - { - $this->router->post('/token/refresh', [ - 'middleware' => ['web', 'auth'], - 'uses' => 'TransientTokenController@refresh', - 'as' => 'passport.token.refresh', - ]); - } - - /** - * Register the routes needed for managing clients. - * - * @return void - */ - public function forClients() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/clients', [ - 'uses' => 'ClientController@forUser', - 'as' => 'passport.clients.index', - ]); - - $router->post('/clients', [ - 'uses' => 'ClientController@store', - 'as' => 'passport.clients.store', - ]); - - $router->put('/clients/{client_id}', [ - 'uses' => 'ClientController@update', - 'as' => 'passport.clients.update', - ]); - - $router->delete('/clients/{client_id}', [ - 'uses' => 'ClientController@destroy', - 'as' => 'passport.clients.destroy', - ]); - }); - } - - /** - * Register the routes needed for managing personal access tokens. - * - * @return void - */ - public function forPersonalAccessTokens() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/scopes', [ - 'uses' => 'ScopeController@all', - 'as' => 'passport.scopes.index', - ]); - - $router->get('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@forUser', - 'as' => 'passport.personal.tokens.index', - ]); - - $router->post('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@store', - 'as' => 'passport.personal.tokens.store', - ]); - - $router->delete('/personal-access-tokens/{token_id}', [ - 'uses' => 'PersonalAccessTokenController@destroy', - 'as' => 'passport.personal.tokens.destroy', - ]); - }); - } -} diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 47a752fee..d67e841f3 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -4,7 +4,6 @@ use Illuminate\Contracts\Config\Repository; use Illuminate\Foundation\Testing\RefreshDatabase; -use Laravel\Passport\Passport; use Laravel\Passport\PassportServiceProvider; use Orchestra\Testbench\TestCase; @@ -22,8 +21,6 @@ protected function setUp(): void $this->artisan('migrate:fresh'); - Passport::routes(); - @unlink(self::PUBLIC_KEY); @unlink(self::PRIVATE_KEY); From 5381868ded5ac32c34ad7b6b774f02c0d51e50bb Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 28 Jul 2021 13:13:56 +0100 Subject: [PATCH 221/353] Fix tests (#1469) --- tests/Feature/AccessTokenControllerTest.php | 2 +- tests/Unit/PassportServiceProviderTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index e5f4af83b..cb1052482 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -216,11 +216,11 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() $this->assertArrayNotHasKey('expires_in', $decodedResponse); $this->assertArrayNotHasKey('access_token', $decodedResponse); $this->assertArrayNotHasKey('refresh_token', $decodedResponse); + $this->assertArrayNotHasKey('hint', $decodedResponse); $this->assertArrayHasKey('error', $decodedResponse); $this->assertSame('invalid_grant', $decodedResponse['error']); $this->assertArrayHasKey('error_description', $decodedResponse); - $this->assertArrayHasKey('hint', $decodedResponse); $this->assertArrayHasKey('message', $decodedResponse); $this->assertSame(0, Token::count()); diff --git a/tests/Unit/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php index 9fc237432..9355268df 100644 --- a/tests/Unit/PassportServiceProviderTest.php +++ b/tests/Unit/PassportServiceProviderTest.php @@ -34,7 +34,7 @@ public function test_can_use_crypto_keys_from_config() $this->assertSame( $privateKeyString, - file_get_contents($cryptKey->getKeyPath()) + $cryptKey->getKeyContents() ); } From 6906a6d84b10dc412fa5fee557e50714c26f62ba Mon Sep 17 00:00:00 2001 From: Ricardo Gobbo de Souza Date: Thu, 29 Jul 2021 08:53:17 -0300 Subject: [PATCH 222/353] Fix link to documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dbc5062df..dd386c48f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Laravel Passport is an OAuth2 server and API authentication package that is simp ## Official Documentation -Documentation for Passport can be found on the [Laravel website](https://laravel.com/docs/master/passport). +Documentation for Passport can be found on the [Laravel website](https://laravel.com/docs/passport). ## Contributing From 1d9d0e474dc0d634eb17b3f6e17a1cbb827de5c5 Mon Sep 17 00:00:00 2001 From: Francisco Madeira Date: Wed, 22 Sep 2021 14:02:37 +0100 Subject: [PATCH 223/353] Change logo to work on Dark Theme (#1481) --- art/logo.svg | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/art/logo.svg b/art/logo.svg index 913321afa..330d82344 100644 --- a/art/logo.svg +++ b/art/logo.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file From 0ee9586e72d87b78e4e43c53a62f189373e6ac79 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 22 Sep 2021 13:02:46 +0000 Subject: [PATCH 224/353] Apply fixes from StyleCI --- src/Http/Middleware/CheckCredentials.php | 2 +- src/Passport.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 4fe71897a..20a937632 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -72,7 +72,7 @@ public function handle($request, Closure $next, ...$scopes) /** * Validate the scopes and token on the incoming request. * - * @param \Psr\Http\Message\ServerRequestInterface $psr + * @param \Psr\Http\Message\ServerRequestInterface $psr * @param array $scopes * @return void * diff --git a/src/Passport.php b/src/Passport.php index 0db48e26d..675e43dff 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -371,8 +371,8 @@ public static function actingAs($user, $scopes = [], $guard = 'api') /** * Set the current client for the application with the given scopes. * - * @param \Laravel\Passport\Client $client - * @param array $scopes + * @param \Laravel\Passport\Client $client + * @param array $scopes * @return \Laravel\Passport\Client */ public static function actingAsClient($client, $scopes = []) From 9b5da83893ce350f6f79e6baca61908ed33323c1 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Fri, 15 Oct 2021 16:28:08 +0200 Subject: [PATCH 225/353] [10.x] Ensure client model factory always creates models with a primary key, even when events are disabled (#1492) * Ensure client model factory always creates models with a primary key, even when events are disabled * Update ClientFactory.php Co-authored-by: Taylor Otwell --- database/factories/ClientFactory.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index 091be54f5..332285ec5 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; use Laravel\Passport\Client; +use Laravel\Passport\Passport; class ClientFactory extends Factory { @@ -22,7 +23,7 @@ class ClientFactory extends Factory */ public function definition() { - return [ + return $this->ensurePrimaryKeyIsSet([ 'user_id' => null, 'name' => $this->faker->company, 'secret' => Str::random(40), @@ -30,7 +31,24 @@ public function definition() 'personal_access_client' => false, 'password_client' => false, 'revoked' => false, - ]; + ]); + } + + /** + * Ensure the primary key is set on the model when using UUIDs. + * + * @param array $data + * @return array + */ + protected function ensurePrimaryKeyIsSet(array $data) + { + if (Passport::clientUuids()) { + $keyName = (new $this->model)->getKeyName(); + + $data[$keyName] = (string) Str::orderedUuid(); + } + + return $data; } /** From 2ab4b1a055e9430330f9f753ffdbd7c44ed8bae4 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 19 Oct 2021 15:48:51 +0200 Subject: [PATCH 226/353] PHP 8.1 support --- .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 0e5539a6e..e5d48d657 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, 8.0] + php: [7.3, 7.4, 8.0, 8.1] laravel: [^8.0] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} From c889d9c464fea409dffe283e9c4e7054ef7aca6f Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 19 Oct 2021 17:25:10 +0200 Subject: [PATCH 227/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf2be114e..fc1aa951a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.1.3...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.1.4...10.x) + + +## [v10.1.4 (2021-10-19)](https://github.com/laravel/passport/compare/v10.1.3...v10.1.4) + +### Fixed +- Ensure client model factory always creates models with a primary key ([#1492](https://github.com/laravel/passport/pull/1492) ## [v10.1.3 (2021-04-06)](https://github.com/laravel/passport/compare/v10.1.2...v10.1.3) From e6b20bc5918b5731d93c91dfc4e1ad4ad2a11f75 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 21 Oct 2021 11:41:40 +0200 Subject: [PATCH 228/353] Update phpunit.xml.dist --- phpunit.xml.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0ec92aebd..58f195173 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,6 +4,7 @@ beStrictAboutTestsThatDoNotTestAnything="false" bootstrap="vendor/autoload.php" colors="true" + convertDeprecationsToExceptions="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" From fda2c2efd54f337be4ea8bed47d7f2665b6b7e0c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 28 Oct 2021 21:54:22 +0200 Subject: [PATCH 229/353] Refactor expiry dates to intervals (#1500) --- src/Passport.php | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index 675e43dff..eafffb849 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -39,23 +39,50 @@ class Passport * The date when access tokens expire. * * @var \DateTimeInterface|null + * + * @deprecated Will be removed in the next major Passport release. */ public static $tokensExpireAt; + /** + * The interval when access tokens expire. + * + * @var \DateInterval|null + */ + public static $tokensExpireIn; + /** * The date when refresh tokens expire. * * @var \DateTimeInterface|null + * + * @deprecated Will be removed in the next major Passport release. */ public static $refreshTokensExpireAt; + /** + * The date when refresh tokens expire. + * + * @var \DateInterval|null + */ + public static $refreshTokensExpireIn; + /** * The date when personal access tokens expire. * * @var \DateTimeInterface|null + * + * @deprecated Will be removed in the next major Passport release. */ public static $personalAccessTokensExpireAt; + /** + * The date when personal access tokens expire. + * + * @var \DateInterval|null + */ + public static $personalAccessTokensExpireIn; + /** * The name for API token cookies. * @@ -261,12 +288,11 @@ public static function tokensCan(array $scopes) public static function tokensExpireIn(DateTimeInterface $date = null) { if (is_null($date)) { - return static::$tokensExpireAt - ? Carbon::now()->diff(static::$tokensExpireAt) - : new DateInterval('P1Y'); + return static::$tokensExpireIn ?? new DateInterval('P1Y'); } static::$tokensExpireAt = $date; + static::$tokensExpireIn = Carbon::now()->diff($date); return new static; } @@ -280,12 +306,11 @@ public static function tokensExpireIn(DateTimeInterface $date = null) public static function refreshTokensExpireIn(DateTimeInterface $date = null) { if (is_null($date)) { - return static::$refreshTokensExpireAt - ? Carbon::now()->diff(static::$refreshTokensExpireAt) - : new DateInterval('P1Y'); + return static::$refreshTokensExpireIn ?? new DateInterval('P1Y'); } static::$refreshTokensExpireAt = $date; + static::$refreshTokensExpireIn = Carbon::now()->diff($date); return new static; } @@ -299,12 +324,11 @@ public static function refreshTokensExpireIn(DateTimeInterface $date = null) public static function personalAccessTokensExpireIn(DateTimeInterface $date = null) { if (is_null($date)) { - return static::$personalAccessTokensExpireAt - ? Carbon::now()->diff(static::$personalAccessTokensExpireAt) - : new DateInterval('P1Y'); + return static::$personalAccessTokensExpireIn ?? new DateInterval('P1Y'); } static::$personalAccessTokensExpireAt = $date; + static::$personalAccessTokensExpireIn = Carbon::now()->diff($date); return new static; } From 48b953439be5c6ed487f54ddebd9e13ebbfdb659 Mon Sep 17 00:00:00 2001 From: Thijs Kok Date: Fri, 29 Oct 2021 16:01:39 +0200 Subject: [PATCH 230/353] [10.x] Add custom encryption key for JWT tokens (#1501) * Added Passport custom encryption key * Refactored encryptUsing method * StyleCI fixes * formatting Co-authored-by: Taylor Otwell --- src/ApiTokenCookieFactory.php | 2 +- src/Guards/TokenGuard.php | 2 +- src/Passport.php | 36 +++++++++++++++++++++ tests/Unit/ApiTokenCookieFactoryTest.php | 27 ++++++++++++++++ tests/Unit/TokenGuardTest.php | 41 ++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/ApiTokenCookieFactory.php b/src/ApiTokenCookieFactory.php index 23a6cd989..3d7d83d02 100644 --- a/src/ApiTokenCookieFactory.php +++ b/src/ApiTokenCookieFactory.php @@ -77,6 +77,6 @@ protected function createToken($userId, $csrfToken, Carbon $expiration) 'sub' => $userId, 'csrf' => $csrfToken, 'expiry' => $expiration->getTimestamp(), - ], $this->encrypter->getKey()); + ], Passport::tokenEncryptionKey($this->encrypter)); } } diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 7d81ed068..00cbe4863 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -269,7 +269,7 @@ protected function decodeJwtTokenCookie($request) { return (array) JWT::decode( CookieValuePrefix::remove($this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies)), - $this->encrypter->getKey(), + Passport::tokenEncryptionKey($this->encrypter), ['HS256'] ); } diff --git a/src/Passport.php b/src/Passport.php index eafffb849..8b6fc42b0 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -5,6 +5,7 @@ use Carbon\Carbon; use DateInterval; use DateTimeInterface; +use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Support\Facades\Route; use League\OAuth2\Server\ResourceServer; use Mockery; @@ -161,10 +162,19 @@ class Passport public static $unserializesCookies = false; /** + * Indicates if client secrets will be hashed. + * * @var bool */ public static $hashesClientSecrets = false; + /** + * The callback that should be used to generate JWT encryption keys. + * + * @var callable + */ + public static $tokenEncryptionKeyCallback; + /** * Indicates the scope should inherit its parent scope. * @@ -640,6 +650,32 @@ public static function hashClientSecrets() return new static; } + /** + * Specify the callback that should be invoked to generate encryption keys for encrypting JWT tokens. + * + * @param callable $callback + * @return static + */ + public static function encryptTokensUsing($callback) + { + static::$tokenEncryptionKeyCallback = $callback; + + return new static; + } + + /** + * Generate an encryption key for encrypting JWT tokens. + * + * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter + * @return string + */ + public static function tokenEncryptionKey(Encrypter $encrypter) + { + return is_callable(static::$tokenEncryptionKeyCallback) ? + (static::$tokenEncryptionKeyCallback)($encrypter) : + $encrypter->getKey(); + } + /** * Configure Passport to not register its migrations. * diff --git a/tests/Unit/ApiTokenCookieFactoryTest.php b/tests/Unit/ApiTokenCookieFactoryTest.php index 5451bcb1d..1a82bbfbf 100644 --- a/tests/Unit/ApiTokenCookieFactoryTest.php +++ b/tests/Unit/ApiTokenCookieFactoryTest.php @@ -3,8 +3,10 @@ namespace Laravel\Passport\Tests\Unit; use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; use Illuminate\Encryption\Encrypter; use Laravel\Passport\ApiTokenCookieFactory; +use Laravel\Passport\Passport; use Mockery as m; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Cookie; @@ -33,4 +35,29 @@ public function test_cookie_can_be_successfully_created() $this->assertInstanceOf(Cookie::class, $cookie); } + + public function test_cookie_can_be_successfully_created_when_using_a_custom_encryption_key() + { + Passport::encryptTokensUsing(function (EncrypterContract $encrypter) { + return $encrypter->getKey().'.mykey'; + }); + + $config = m::mock(Repository::class); + $config->shouldReceive('get')->with('session')->andReturn([ + 'lifetime' => 120, + 'path' => '/', + 'domain' => null, + 'secure' => true, + 'same_site' => 'lax', + ]); + $encrypter = new Encrypter(str_repeat('a', 16)); + $factory = new ApiTokenCookieFactory($config, $encrypter); + + $cookie = $factory->make(1, 'token'); + + $this->assertInstanceOf(Cookie::class, $cookie); + + // Revert to the default encryption method + Passport::encryptTokensUsing(null); + } } diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index a7f4b8556..b586eff99 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -6,6 +6,7 @@ use Firebase\JWT\JWT; use Illuminate\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Encryption\Encrypter; use Illuminate\Http\Request; @@ -229,6 +230,46 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() $this->assertNull($guard->user($request)); } + public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_when_using_a_custom_encryption_key() + { + Passport::encryptTokensUsing(function (EncrypterContract $encrypter) { + return $encrypter->getKey().'.mykey'; + }); + + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = new Encrypter(str_repeat('a', 16)); + + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + + $request = Request::create('/'); + $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); + $request->cookies->set('laravel_token', + $encrypter->encrypt(CookieValuePrefix::create('laravel_token', $encrypter->getKey()).JWT::encode([ + 'sub' => 1, + 'aud' => 1, + 'csrf' => 'token', + 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), + ], Passport::tokenEncryptionKey($encrypter)), false) + ); + + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); + + $user = $guard->user($request); + + $this->assertEquals($expectedUser, $user); + + // Revert to the default encryption method + Passport::encryptTokensUsing(null); + } + public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() { $resourceServer = m::mock(ResourceServer::class); From 1c69a010930a3ce8db348967d8ad9585be4d7d4d Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 2 Nov 2021 17:45:51 +0100 Subject: [PATCH 231/353] Update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc1aa951a..86df1cc65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.1.4...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.2.0...10.x) + + +## [v10.2.0 (2021-11-02)](https://github.com/laravel/passport/compare/v10.1.4...v10.2.0) + +### Added +- Add custom encryption key for JWT tokens ([#1501](https://github.com/laravel/passport/pull/1501)) + +### Changed +- Refactor expiry dates to intervals ([#1500](https://github.com/laravel/passport/pull/1500)) ## [v10.1.4 (2021-10-19)](https://github.com/laravel/passport/compare/v10.1.3...v10.1.4) From 0f02c6cb446ab56ad429b27250c1fd1eac6cc5de Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 26 Nov 2021 15:57:17 +0100 Subject: [PATCH 232/353] [10.x] Update test for Laravel 9 (#1509) * Update test for Laravel 9 * wip * wip --- src/Console/KeysCommand.php | 6 ++- tests/Feature/KeysCommandTest.php | 29 +++++++++++ tests/Feature/PassportTestCase.php | 4 +- tests/Unit/KeysCommandTest.php | 81 ------------------------------ 4 files changed, 37 insertions(+), 83 deletions(-) create mode 100644 tests/Feature/KeysCommandTest.php delete mode 100644 tests/Unit/KeysCommandTest.php diff --git a/src/Console/KeysCommand.php b/src/Console/KeysCommand.php index 36ff6e6c6..30490c441 100644 --- a/src/Console/KeysCommand.php +++ b/src/Console/KeysCommand.php @@ -29,7 +29,7 @@ class KeysCommand extends Command /** * Execute the console command. * - * @return void + * @return int */ public function handle() { @@ -40,6 +40,8 @@ public function handle() if ((file_exists($publicKey) || file_exists($privateKey)) && ! $this->option('force')) { $this->error('Encryption keys already exist. Use the --force option to overwrite them.'); + + return 1; } else { if (class_exists(LegacyRSA::class)) { $keys = (new LegacyRSA)->createKey($this->input ? (int) $this->option('length') : 4096); @@ -55,5 +57,7 @@ public function handle() $this->info('Encryption keys generated successfully.'); } + + return 0; } } diff --git a/tests/Feature/KeysCommandTest.php b/tests/Feature/KeysCommandTest.php new file mode 100644 index 000000000..e7d528f82 --- /dev/null +++ b/tests/Feature/KeysCommandTest.php @@ -0,0 +1,29 @@ +assertFileExists(self::PUBLIC_KEY); + $this->assertFileExists(self::PRIVATE_KEY); + } + + public function testPrivateAndPublicKeysShouldNotBeGeneratedTwice() + { + $this->artisan('passport:keys') + ->assertFailed() + ->expectsOutput('Encryption keys already exist. Use the --force option to overwrite them.'); + } +} diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index d7da023cb..610bfef37 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -12,7 +12,7 @@ abstract class PassportTestCase extends TestCase { use RefreshDatabase; - const KEYS = __DIR__.'/keys'; + const KEYS = __DIR__.'/../keys'; const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; const PRIVATE_KEY = self::KEYS.'/oauth-private.key'; @@ -24,6 +24,8 @@ protected function setUp(): void Passport::routes(); + Passport::loadKeysFrom(self::KEYS); + @unlink(self::PUBLIC_KEY); @unlink(self::PRIVATE_KEY); diff --git a/tests/Unit/KeysCommandTest.php b/tests/Unit/KeysCommandTest.php deleted file mode 100644 index 991d21564..000000000 --- a/tests/Unit/KeysCommandTest.php +++ /dev/null @@ -1,81 +0,0 @@ -makePartial() - ->shouldReceive('info') - ->with('Encryption keys generated successfully.') - ->getMock(); - - Container::getInstance()->instance('path.storage', self::KEYS); - - $command->handle(); - - $this->assertFileExists(self::PUBLIC_KEY); - $this->assertFileExists(self::PRIVATE_KEY); - } - - public function testPrivateAndPublicKeysAreGeneratedInCustomPath() - { - Passport::loadKeysFrom(self::KEYS); - - $command = m::mock(KeysCommand::class) - ->makePartial() - ->shouldReceive('info') - ->with('Encryption keys generated successfully.') - ->getMock(); - - $command->handle(); - - $this->assertFileExists(self::PUBLIC_KEY); - $this->assertFileExists(self::PRIVATE_KEY); - - return $command; - } - - /** - * @depends testPrivateAndPublicKeysAreGeneratedInCustomPath - */ - public function testPrivateAndPublicKeysShouldNotBeGeneratedTwice($command) - { - $command->shouldReceive('option') - ->with('force') - ->andReturn(false); - - $command->shouldReceive('error') - ->with('Encryption keys already exist. Use the --force option to overwrite them.'); - - $command->handle(); - } -} From 187580ab87352b1b5bc524aee62d32ff5183dce0 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Fri, 26 Nov 2021 16:38:14 +0100 Subject: [PATCH 233/353] [11.x] Allow authenticated client to be retrieved from the guard (#1508) * Allow authenticated client to be retrieved from the guard * Make token guard macroable * Use previously resolved client when available * Add tests ensuring client and user are only pulled from the database once --- src/Guards/TokenGuard.php | 91 +++++++++++++++---- src/PassportServiceProvider.php | 20 ++--- tests/Unit/TokenGuardTest.php | 151 ++++++++++++++++++++++---------- 3 files changed, 190 insertions(+), 72 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index d60265208..640c6961e 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -4,12 +4,15 @@ use Exception; use Firebase\JWT\JWT; +use Illuminate\Auth\GuardHelpers; use Illuminate\Container\Container; +use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Http\Request; +use Illuminate\Support\Traits\Macroable; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\PassportUserProvider; @@ -20,8 +23,10 @@ use Nyholm\Psr7\Factory\Psr17Factory; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; -class TokenGuard +class TokenGuard implements Guard { + use GuardHelpers, Macroable; + /** * The resource server instance. * @@ -57,6 +62,20 @@ class TokenGuard */ protected $encrypter; + /** + * The request instance. + * + * @var \Illuminate\Http\Request + */ + protected $request; + + /** + * The currently authenticated client. + * + * @var \Laravel\Passport\Client|null + */ + protected $client; + /** * Create a new token guard instance. * @@ -65,6 +84,7 @@ class TokenGuard * @param \Laravel\Passport\TokenRepository $tokens * @param \Laravel\Passport\ClientRepository $clients * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter + * @param \Illuminate\Http\Request $request * @return void */ public function __construct( @@ -72,49 +92,75 @@ public function __construct( PassportUserProvider $provider, TokenRepository $tokens, ClientRepository $clients, - Encrypter $encrypter + Encrypter $encrypter, + Request $request ) { $this->server = $server; $this->tokens = $tokens; $this->clients = $clients; $this->provider = $provider; $this->encrypter = $encrypter; + $this->request = $request; } /** * Get the user for the incoming request. * - * @param \Illuminate\Http\Request $request * @return mixed */ - public function user(Request $request) + public function user() { - if ($request->bearerToken()) { - return $this->authenticateViaBearerToken($request); - } elseif ($request->cookie(Passport::cookie())) { - return $this->authenticateViaCookie($request); + if (! is_null($this->user)) { + return $this->user; + } + + if ($this->request->bearerToken()) { + return $this->user = $this->authenticateViaBearerToken($this->request); + } elseif ($this->request->cookie(Passport::cookie())) { + return $this->user = $this->authenticateViaCookie($this->request); } } + /** + * Validate a user's credentials. + * + * @param array $credentials + * @return bool + */ + public function validate(array $credentials = []) + { + return ! is_null((new static( + $this->server, + $this->provider, + $this->tokens, + $this->clients, + $this->encrypter, + $credentials['request'], + ))->user()); + } + /** * Get the client for the incoming request. * - * @param \Illuminate\Http\Request $request * @return mixed */ - public function client(Request $request) + public function client() { - if ($request->bearerToken()) { - if (! $psr = $this->getPsrRequestViaBearerToken($request)) { + if (! is_null($this->client)) { + return $this->client; + } + + if ($this->request->bearerToken()) { + if (! $psr = $this->getPsrRequestViaBearerToken($this->request)) { return; } - return $this->clients->findActive( + return $this->client = $this->clients->findActive( $psr->getAttribute('oauth_client_id') ); - } elseif ($request->cookie(Passport::cookie())) { - if ($token = $this->getTokenViaCookie($request)) { - return $this->clients->findActive($token['aud']); + } elseif ($this->request->cookie(Passport::cookie())) { + if ($token = $this->getTokenViaCookie($this->request)) { + return $this->client = $this->clients->findActive($token['aud']); } } } @@ -285,6 +331,19 @@ protected function getTokenFromRequest($request) return $token; } + /** + * Set the current request instance. + * + * @param \Illuminate\Http\Request $request + * @return $this + */ + public function setRequest(Request $request) + { + $this->request = $request; + + return $this; + } + /** * Determine if the cookie contents should be serialized. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index de02ca4ee..0dcc65663 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -4,7 +4,6 @@ use DateInterval; use Illuminate\Auth\Events\Logout; -use Illuminate\Auth\RequestGuard; use Illuminate\Config\Repository as Config; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cookie; @@ -341,19 +340,18 @@ protected function registerGuard() * Make an instance of the token guard. * * @param array $config - * @return \Illuminate\Auth\RequestGuard + * @return \Laravel\Passport\Guards\TokenGuard */ protected function makeGuard(array $config) { - return new RequestGuard(function ($request) use ($config) { - return (new TokenGuard( - $this->app->make(ResourceServer::class), - new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']), - $this->app->make(TokenRepository::class), - $this->app->make(ClientRepository::class), - $this->app->make('encrypter') - ))->user($request); - }, $this->app['request']); + return new TokenGuard( + $this->app->make(ResourceServer::class), + new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']), + $this->app->make(TokenRepository::class), + $this->app->make(ClientRepository::class), + $this->app->make('encrypter'), + $this->app->make('request') + ); } /** diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index b586eff99..0528f3839 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -37,11 +37,40 @@ public function test_user_can_be_pulled_via_bearer_token() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + $request = Request::create('/'); + $request->headers->set('Authorization', 'Bearer token'); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); + $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); + $tokens->shouldReceive('find')->once()->with('token')->andReturn($token = m::mock()); + $clients->shouldReceive('revoked')->with(1)->andReturn(false); + $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); + + $user = $guard->user(); + + $this->assertInstanceOf(TokenGuardTestUser::class, $user); + $this->assertEquals($token, $user->token()); + } + + public function test_user_is_resolved_only_once() + { + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = m::mock(Encrypter::class); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); @@ -52,10 +81,15 @@ public function test_user_can_be_pulled_via_bearer_token() $clients->shouldReceive('revoked')->with(1)->andReturn(false); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); - $user = $guard->user($request); + $user = $guard->user(); + + $userProvider->shouldReceive('retrieveById')->never(); + + $user2 = $guard->user(); $this->assertInstanceOf(TokenGuardTestUser::class, $user); $this->assertEquals($token, $user->token()); + $this->assertSame($user, $user2); } public function test_no_user_is_returned_when_oauth_throws_exception() @@ -71,19 +105,19 @@ public function test_no_user_is_returned_when_oauth_throws_exception() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); // Assert that `validateAuthenticatedRequest` isn't called twice on failure. - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_null_is_returned_if_no_user_is_found() @@ -98,18 +132,18 @@ public function test_null_is_returned_if_no_user_is_found() ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(null); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header() @@ -124,8 +158,6 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -137,10 +169,12 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( ], str_repeat('a', 16)), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -157,8 +191,6 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); $request->cookies->set('laravel_token', @@ -170,10 +202,12 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( ], str_repeat('a', 16)), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -186,8 +220,6 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'wrong_token'); $request->cookies->set('laravel_token', @@ -199,9 +231,11 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() ], str_repeat('a', 16))) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_cookie_xsrf_is_verified_against_xsrf_token_header() @@ -212,8 +246,6 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt('wrong_token', false)); $request->cookies->set('laravel_token', @@ -225,9 +257,11 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() ], str_repeat('a', 16))) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_when_using_a_custom_encryption_key() @@ -246,8 +280,6 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); $request->cookies->set('laravel_token', @@ -259,10 +291,12 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ ], Passport::tokenEncryptionKey($encrypter)), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); @@ -278,8 +312,6 @@ public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->cookies->set('XSRF-TOKEN', $encrypter->encrypt('token', false)); $request->cookies->set('laravel_token', @@ -291,9 +323,11 @@ public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() ], str_repeat('a', 16))) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_expired_cookies_may_not_be_used() @@ -304,8 +338,6 @@ public function test_expired_cookies_may_not_be_used() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -317,9 +349,11 @@ public function test_expired_cookies_may_not_be_used() ], str_repeat('a', 16))) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_csrf_check_can_be_disabled() @@ -334,8 +368,6 @@ public function test_csrf_check_can_be_disabled() ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - Passport::ignoreCsrfToken(); $request = Request::create('/'); @@ -347,10 +379,12 @@ public function test_csrf_check_can_be_disabled() ], str_repeat('a', 16)), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -363,18 +397,45 @@ public function test_client_can_be_pulled_via_bearer_token() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + $request = Request::create('/'); + $request->headers->set('Authorization', 'Bearer token'); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); + + $client = $guard->client(); + + $this->assertInstanceOf(TokenGuardTestClient::class, $client); + } + + public function test_client_is_resolved_only_once() + { + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = m::mock(Encrypter::class); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); - $client = $guard->client($request); + $client = $guard->client(); + + $clients->shouldReceive('findActive')->never(); + + $client2 = $guard->client(); $this->assertInstanceOf(TokenGuardTestClient::class, $client); + $this->assertSame($client, $client2); } public function test_no_client_is_returned_when_oauth_throws_exception() @@ -390,19 +451,19 @@ public function test_no_client_is_returned_when_oauth_throws_exception() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); // Assert that `validateAuthenticatedRequest` isn't called twice on failure. - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); } public function test_null_is_returned_if_no_client_is_found() @@ -413,16 +474,16 @@ public function test_null_is_returned_if_no_client_is_found() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $clients->shouldReceive('findActive')->with(1)->andReturn(null); - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); } public function test_clients_may_be_retrieved_from_cookies() @@ -433,8 +494,6 @@ public function test_clients_may_be_retrieved_from_cookies() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -446,9 +505,11 @@ public function test_clients_may_be_retrieved_from_cookies() ], str_repeat('a', 16)), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $clients->shouldReceive('findActive')->with(1)->andReturn($expectedClient = new TokenGuardTestClient); - $client = $guard->client($request); + $client = $guard->client(); $this->assertEquals($expectedClient, $client); } From 9e1bbadc7474744f64a606c2696fabd64194ab6a Mon Sep 17 00:00:00 2001 From: Kyryl Bogach Date: Wed, 1 Dec 2021 14:53:00 +0100 Subject: [PATCH 234/353] Fix str_replace error when third parameter ($subject) is null (#1511) * Fix str_replace error when third parameter ($subject) is null in PHP 8.1.0 str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in /var/www/html/vendor/laravel/passport/src/PassportServiceProvider.php line 268 * Use single quotes to fix style error --- src/PassportServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index daeb04422..0418d43ca 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -265,7 +265,7 @@ protected function registerResourceServer() */ protected function makeCryptKey($type) { - $key = str_replace('\\n', "\n", $this->app->make(Config::class)->get('passport.'.$type.'_key')); + $key = str_replace('\\n', "\n", $this->app->make(Config::class)->get('passport.'.$type.'_key') ?? ''); if (! $key) { $key = 'file://'.Passport::keyPath('oauth-'.$type.'.key'); From a2634286f98de77a203e6d57b231d6c30c840569 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 7 Dec 2021 17:21:39 +0100 Subject: [PATCH 235/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86df1cc65..c0e338ac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.2.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.2.1...10.x) + + +## [v10.2.1 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.0...v10.2.1) + +### Fixed +- Fix `str_replace` error when third parameter ($subject) is null ([#1511](https://github.com/laravel/passport/pull/1511)) ## [v10.2.0 (2021-11-02)](https://github.com/laravel/passport/compare/v10.1.4...v10.2.0) From d239c9829062da1c91919c8ce25b99ef3c90ea01 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 7 Dec 2021 16:24:22 +0000 Subject: [PATCH 236/353] Apply fixes from StyleCI --- tests/Feature/PassportTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index abffa7efd..8daeb4e6c 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -4,8 +4,8 @@ use Illuminate\Contracts\Config\Repository; use Illuminate\Foundation\Testing\RefreshDatabase; -use Laravel\Passport\PassportServiceProvider; use Laravel\Passport\Passport; +use Laravel\Passport\PassportServiceProvider; use Orchestra\Testbench\TestCase; abstract class PassportTestCase extends TestCase From c24402ebced91e7ada334e6e48ab119b494bacea Mon Sep 17 00:00:00 2001 From: ruben Date: Tue, 7 Dec 2021 16:47:26 +0000 Subject: [PATCH 237/353] fix: Internal method return types, php 8.1 tests compatibility --- src/Bridge/Scope.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Bridge/Scope.php b/src/Bridge/Scope.php index 0ea899741..50aaf02b9 100644 --- a/src/Bridge/Scope.php +++ b/src/Bridge/Scope.php @@ -25,6 +25,7 @@ public function __construct($name) * * @return mixed */ + #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->getIdentifier(); From 7981abed1a0979afd4a5a8bec81624b8127a287f Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 7 Dec 2021 17:57:03 +0100 Subject: [PATCH 238/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0e338ac3..410ee4dd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.2.1...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.2.2...10.x) + + +## [v10.2.2 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.1...v10.2.2) + +### Fixed +- Fix jsonSerialize PHP 8.1 issue ([#1512](https://github.com/laravel/passport/pull/1512)) ## [v10.2.1 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.0...v10.2.1) From 9a431c5535f8637ba4bfa9fb07351f4226f11c63 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 11 Jan 2022 21:21:02 +0100 Subject: [PATCH 239/353] Update tests.yml --- .github/workflows/tests.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5d48d657..2d0bcbc33 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,8 +13,13 @@ jobs: strategy: fail-fast: true matrix: - php: [7.3, 7.4, 8.0, 8.1] - laravel: [^8.0] + php: [7.3, 7.4, '8.0', 8.1] + laravel: [8, 9] + exclude: + - php: 7.3 + laravel: 9 + - php: 7.4 + laravel: 9 name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} @@ -32,7 +37,7 @@ jobs: - name: Install dependencies run: | - composer require "illuminate/contracts=${{ matrix.laravel }}" --no-update + composer require "illuminate/contracts=^${{ matrix.laravel }}" --no-update composer update --prefer-dist --no-interaction --no-progress - name: Execute tests From fe865e3b165ca203e8498e1b82ee3493b6c2c304 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 11 Jan 2022 21:21:48 +0100 Subject: [PATCH 240/353] Update tests.yml --- .github/workflows/tests.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2d0bcbc33..e5d48d657 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,13 +13,8 @@ jobs: strategy: fail-fast: true matrix: - php: [7.3, 7.4, '8.0', 8.1] - laravel: [8, 9] - exclude: - - php: 7.3 - laravel: 9 - - php: 7.4 - laravel: 9 + php: [7.3, 7.4, 8.0, 8.1] + laravel: [^8.0] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} @@ -37,7 +32,7 @@ jobs: - name: Install dependencies run: | - composer require "illuminate/contracts=^${{ matrix.laravel }}" --no-update + composer require "illuminate/contracts=${{ matrix.laravel }}" --no-update composer update --prefer-dist --no-interaction --no-progress - name: Execute tests From b9e0b9869272d87febff38583796b68307c3dacb Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 12 Jan 2022 19:10:09 +0100 Subject: [PATCH 241/353] Laravel v9 support (#1516) * Laravel 9 support * Update composer.json * Update tests.yml --- .github/workflows/tests.yml | 11 ++++++++--- composer.json | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5d48d657..2d0bcbc33 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,8 +13,13 @@ jobs: strategy: fail-fast: true matrix: - php: [7.3, 7.4, 8.0, 8.1] - laravel: [^8.0] + php: [7.3, 7.4, '8.0', 8.1] + laravel: [8, 9] + exclude: + - php: 7.3 + laravel: 9 + - php: 7.4 + laravel: 9 name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} @@ -32,7 +37,7 @@ jobs: - name: Install dependencies run: | - composer require "illuminate/contracts=${{ matrix.laravel }}" --no-update + composer require "illuminate/contracts=^${{ matrix.laravel }}" --no-update composer update --prefer-dist --no-interaction --no-progress - name: Execute tests diff --git a/composer.json b/composer.json index 0726c28c7..bea4a04e3 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,15 @@ "php": "^7.3|^8.0", "ext-json": "*", "firebase/php-jwt": "^5.0", - "illuminate/auth": "^8.2", - "illuminate/console": "^8.2", - "illuminate/container": "^8.2", - "illuminate/contracts": "^8.2", - "illuminate/cookie": "^8.2", - "illuminate/database": "^8.2", - "illuminate/encryption": "^8.2", - "illuminate/http": "^8.2", - "illuminate/support": "^8.2", + "illuminate/auth": "^8.2|^9.0", + "illuminate/console": "^8.2|^9.0", + "illuminate/container": "^8.2|^9.0", + "illuminate/contracts": "^8.2|^9.0", + "illuminate/cookie": "^8.2|^9.0", + "illuminate/database": "^8.2|^9.0", + "illuminate/encryption": "^8.2|^9.0", + "illuminate/http": "^8.2|^9.0", + "illuminate/support": "^8.2|^9.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", @@ -34,7 +34,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^6.0", + "orchestra/testbench": "^6.0|^7.0", "phpunit/phpunit": "^9.3" }, "autoload": { From b4a829e52f57e871f6c40717b9c9770cac5ad795 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 12 Jan 2022 19:12:12 +0100 Subject: [PATCH 242/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 410ee4dd2..134dc91e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.2.2...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.3.0...10.x) + + +## [v10.3.0 (2022-01-12)](https://github.com/laravel/passport/compare/v10.2.2...v10.3.0) + +### Changed +- Laravel 9 Support ([#1516](https://github.com/laravel/passport/pull/1516)) ## [v10.2.2 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.1...v10.2.2) From ba1996cdaf25c88bb8cf851442afa0ec6870a3a1 Mon Sep 17 00:00:00 2001 From: yaroslawww <23663794+yaroslawww@users.noreply.github.com> Date: Fri, 21 Jan 2022 16:51:20 +0200 Subject: [PATCH 243/353] [10.x] Allow to use custom authorization server response (#1521) * Allow to use custom authorization server response * Update src/Passport.php Remove direct initialisation as "null" Co-authored-by: Dries Vints * Update Passport.php Co-authored-by: Dries Vints Co-authored-by: Taylor Otwell --- src/Passport.php | 7 +++ src/PassportServiceProvider.php | 3 +- tests/Feature/AccessTokenControllerTest.php | 57 +++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/Passport.php b/src/Passport.php index 8b6fc42b0..fd5f7c8a8 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -182,6 +182,13 @@ class Passport */ public static $withInheritedScopes = false; + /** + * The authorization server response type. + * + * @var \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface|null + */ + public static $authorizationServerResponseType; + /** * Enable the implicit grant type. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 0418d43ca..e87b51846 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -212,7 +212,8 @@ public function makeAuthorizationServer() $this->app->make(Bridge\AccessTokenRepository::class), $this->app->make(Bridge\ScopeRepository::class), $this->makeCryptKey('private'), - app('encrypter')->getKey() + app('encrypter')->getKey(), + Passport::$authorizationServerResponseType ); } diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index cb1052482..451107d30 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -10,6 +10,7 @@ use Laravel\Passport\ClientRepository; use Laravel\Passport\Database\Factories\ClientFactory; use Laravel\Passport\HasApiTokens; +use Laravel\Passport\Passport; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Configuration; @@ -270,9 +271,65 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() $this->assertSame(0, Token::count()); } + + public function testGettingCustomResponseType() + { + $this->withoutExceptionHandling(); + Passport::$authorizationServerResponseType = new IdTokenResponse('foo_bar_open_id_token'); + + $user = new User(); + $user->email = 'foo@gmail.com'; + $user->password = $this->app->make(Hasher::class)->make('foobar123'); + $user->save(); + + /** @var Client $client */ + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + + $response = $this->post( + '/oauth/token', + [ + 'grant_type' => 'client_credentials', + 'client_id' => $client->id, + 'client_secret' => $client->secret, + ] + ); + + $response->assertOk(); + + $decodedResponse = $response->decodeResponseJson()->json(); + + $this->assertArrayHasKey('id_token', $decodedResponse); + $this->assertSame('foo_bar_open_id_token', $decodedResponse['id_token']); + } } class User extends \Illuminate\Foundation\Auth\User { use HasApiTokens; } + +class IdTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerTokenResponse +{ + /** + * @var string Id token. + */ + protected $idToken; + + /** + * @param string $idToken + */ + public function __construct($idToken) + { + $this->idToken = $idToken; + } + + /** + * @inheritdoc + */ + protected function getExtraParams(\League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessToken) + { + return [ + 'id_token' => $this->idToken, + ]; + } +} From d511a3ca9ff97e65ff5de8a73a9c070c204f3b5a Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Mon, 24 Jan 2022 18:51:06 +0100 Subject: [PATCH 244/353] [11.x] Stub client on guard when calling Passport::actingAsClient() (#1519) * Allow token guard client to be set programmatically * Set the client on the TokenGuard when mocking the client * Apply fixes from StyleCI --- src/Guards/TokenGuard.php | 14 ++++++++++++++ src/Passport.php | 7 ++++++- tests/Feature/ActingAsClientTest.php | 10 ++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 640c6961e..a10a1fed5 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -13,6 +13,7 @@ use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Http\Request; use Illuminate\Support\Traits\Macroable; +use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Laravel\Passport\PassportUserProvider; @@ -353,4 +354,17 @@ public static function serialized() { return EncryptCookies::serialized('XSRF-TOKEN'); } + + /** + * Set the client for the current request. + * + * @param \Laravel\Passport\Client $client + * @return $this + */ + public function setClient(Client $client) + { + $this->client = $client; + + return $this; + } } diff --git a/src/Passport.php b/src/Passport.php index b1815116c..bec7ce9fb 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -388,9 +388,10 @@ public static function actingAs($user, $scopes = [], $guard = 'api') * * @param \Laravel\Passport\Client $client * @param array $scopes + * @param string $guard * @return \Laravel\Passport\Client */ - public static function actingAsClient($client, $scopes = []) + public static function actingAsClient($client, $scopes = [], $guard = 'api') { $token = app(self::tokenModel()); @@ -414,6 +415,10 @@ public static function actingAsClient($client, $scopes = []) app()->instance(TokenRepository::class, $mock); + app('auth')->guard($guard)->setClient($client); + + app('auth')->shouldUse($guard); + return $client; } diff --git a/tests/Feature/ActingAsClientTest.php b/tests/Feature/ActingAsClientTest.php index 8fc99b777..f0a92c7d7 100644 --- a/tests/Feature/ActingAsClientTest.php +++ b/tests/Feature/ActingAsClientTest.php @@ -7,9 +7,8 @@ use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Passport; -use Orchestra\Testbench\TestCase; -class ActingAsClientTest extends TestCase +class ActingAsClientTest extends PassportTestCase { public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredentialsMiddleware() { @@ -46,4 +45,11 @@ public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredential $response->assertSuccessful(); $response->assertSee('bar'); } + + public function testActingAsClientSetsTheClientOnTheGuard() + { + Passport::actingAsClient($client = new Client()); + + $this->assertSame($client, app('auth')->client()); + } } From 779e34f0152f42fb76b258d814956313fa38857c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 25 Jan 2022 21:06:06 +0100 Subject: [PATCH 245/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 134dc91e1..14eb7302b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.3.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.3.1...10.x) + + +## [v10.3.1 (2022-01-25)](https://github.com/laravel/passport/compare/v10.3.0...v10.3.1) + +### Changed +- Allow to use custom authorization server response ([#1521](https://github.com/laravel/passport/pull/1521)) ## [v10.3.0 (2022-01-12)](https://github.com/laravel/passport/compare/v10.2.2...v10.3.0) From c56d3e0a066ae31b0baf082a2672bda935d48cf7 Mon Sep 17 00:00:00 2001 From: Jonathan Mitchell Date: Thu, 3 Feb 2022 18:20:48 -0800 Subject: [PATCH 246/353] Minor documentation tweak to UPGRADE.md (#1526) * Update UPGRADE.md I just went through the steps of upgrading passport from v8 to v10 and hit a minor snag that could have been solved by a tweak to the documentation. When upgrading from v8 to v9 it says place two Passport static calls "within the `boot` method of your `AppServiceProvider`" When upgrading from v9 to v10 it says you can remove the calls from your `AuthServiceProvider`. I don't claim to know where those calls belonged in the first place, so this proposal just updates the documentation to list them both. * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 3f1c91239..4df35ceb5 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -16,7 +16,7 @@ Laravel 8.0 is now the minimum required version. PR: https://github.com/laravel/passport/pull/1325 -The personal client configuration methods have been removed from the `Passport` class since they are no longer necessary. You should remove calls to these methods from your `AuthServiceProvider`. +The personal client configuration methods have been removed from the `Passport` class since they are no longer necessary. You should remove any calls to these methods from your application's service providers. ## Upgrading To 9.0 From 8.x From 409e30849da4f8488ce09d1d18c9055944b0a66c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 8 Feb 2022 15:13:38 +0100 Subject: [PATCH 247/353] Create update-changelog.yml --- .github/workflows/update-changelog.yml | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/update-changelog.yml diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 000000000..0200e2b94 --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,29 @@ +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.ref_name }} + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.tag_name }} + release-notes: ${{ github.event.release.body }} + compare-url-target-revision: ${{ github.event.release.target_commitish }} + + - name: Commit updated CHANGELOG + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: ${{ github.event.release.target_commitish }} + commit_message: Update CHANGELOG.md + file_pattern: CHANGELOG.md From c56207e9a37c849da0164842a609a9f38747e95b Mon Sep 17 00:00:00 2001 From: Antonio Pauletich Date: Tue, 15 Feb 2022 22:44:15 +0100 Subject: [PATCH 248/353] [10.x] Fix Faker deprecations (#1530) When using this factory in feature tests with `$this->withoutDeprecationHandling();` call the test fails as the deprecation gets converted to an exception: ``` Since fakerphp/faker 1.14: Accessing property "company" is deprecated, use "company()" instead. ``` --- database/factories/ClientFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index 332285ec5..afdc227da 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -25,9 +25,9 @@ public function definition() { return $this->ensurePrimaryKeyIsSet([ 'user_id' => null, - 'name' => $this->faker->company, + 'name' => $this->faker->company(), 'secret' => Str::random(40), - 'redirect' => $this->faker->url, + 'redirect' => $this->faker->url(), 'personal_access_client' => false, 'password_client' => false, 'revoked' => false, From de6e1fda1322b72764c15aef28bd099f01d61aeb Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 22 Feb 2022 16:10:13 +0000 Subject: [PATCH 249/353] Update CHANGELOG.md --- CHANGELOG.md | 138 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14eb7302b..5b2668ff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,267 +1,286 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.3.1...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.3.2...10.x) +## [v10.3.2](https://github.com/laravel/passport/compare/v10.3.1...v10.3.2) - 2022-02-22 + +### Fixed + +- Fix Faker deprecations by @X-Coder264 in https://github.com/laravel/passport/pull/1530 ## [v10.3.1 (2022-01-25)](https://github.com/laravel/passport/compare/v10.3.0...v10.3.1) ### Changed -- Allow to use custom authorization server response ([#1521](https://github.com/laravel/passport/pull/1521)) +- Allow to use custom authorization server response ([#1521](https://github.com/laravel/passport/pull/1521)) ## [v10.3.0 (2022-01-12)](https://github.com/laravel/passport/compare/v10.2.2...v10.3.0) ### Changed -- Laravel 9 Support ([#1516](https://github.com/laravel/passport/pull/1516)) +- Laravel 9 Support ([#1516](https://github.com/laravel/passport/pull/1516)) ## [v10.2.2 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.1...v10.2.2) ### Fixed -- Fix jsonSerialize PHP 8.1 issue ([#1512](https://github.com/laravel/passport/pull/1512)) +- Fix jsonSerialize PHP 8.1 issue ([#1512](https://github.com/laravel/passport/pull/1512)) ## [v10.2.1 (2021-12-07)](https://github.com/laravel/passport/compare/v10.2.0...v10.2.1) ### Fixed -- Fix `str_replace` error when third parameter ($subject) is null ([#1511](https://github.com/laravel/passport/pull/1511)) +- Fix `str_replace` error when third parameter ($subject) is null ([#1511](https://github.com/laravel/passport/pull/1511)) ## [v10.2.0 (2021-11-02)](https://github.com/laravel/passport/compare/v10.1.4...v10.2.0) ### Added + - Add custom encryption key for JWT tokens ([#1501](https://github.com/laravel/passport/pull/1501)) ### Changed -- Refactor expiry dates to intervals ([#1500](https://github.com/laravel/passport/pull/1500)) +- Refactor expiry dates to intervals ([#1500](https://github.com/laravel/passport/pull/1500)) ## [v10.1.4 (2021-10-19)](https://github.com/laravel/passport/compare/v10.1.3...v10.1.4) ### Fixed -- Ensure client model factory always creates models with a primary key ([#1492](https://github.com/laravel/passport/pull/1492) +- Ensure client model factory always creates models with a primary key ([#1492](https://github.com/laravel/passport/pull/1492) ## [v10.1.3 (2021-04-06)](https://github.com/laravel/passport/compare/v10.1.2...v10.1.3) ### Changed + - Use app helper ([3d1e6bb](https://github.com/laravel/passport/commit/3d1e6bbdedf71efb147f3b5205259e8b20c2e6ad)) - + ### Fixed -- Fix binding ([e3478de](https://github.com/laravel/passport/commit/e3478dedd938671b7598239cc8554f77de9ab9c7)) +- Fix binding ([e3478de](https://github.com/laravel/passport/commit/e3478dedd938671b7598239cc8554f77de9ab9c7)) ## [v10.1.2 (2021-03-02)](https://github.com/laravel/passport/compare/v10.1.1...v10.1.2) ### Fixed -- Backport phpseclib v2 ([#1418](https://github.com/laravel/passport/pull/1418)) +- Backport phpseclib v2 ([#1418](https://github.com/laravel/passport/pull/1418)) ## [v10.1.1 (2021-02-23)](https://github.com/laravel/passport/compare/v10.1.0...v10.1.1) ### Changed -- Update to phpseclib v3 ([#1410](https://github.com/laravel/passport/pull/1410)) +- Update to phpseclib v3 ([#1410](https://github.com/laravel/passport/pull/1410)) ## [v10.1.0 (2020-11-26)](https://github.com/laravel/passport/compare/v10.0.1...v10.1.0) ### Added + - PHP 8 Support ([#1373](https://github.com/laravel/passport/pull/1373)) ### Removed -- Remove Vue components ([#1352](https://github.com/laravel/passport/pull/1352)) +- Remove Vue components ([#1352](https://github.com/laravel/passport/pull/1352)) ## [v10.0.1 (2020-09-15)](https://github.com/laravel/passport/compare/v10.0.0...v10.0.1) ### Fixed -- Use newFactory to properly reference factory ([#1349](https://github.com/laravel/passport/pull/1349)) +- Use newFactory to properly reference factory ([#1349](https://github.com/laravel/passport/pull/1349)) ## [v10.0.0 (2020-09-08)](https://github.com/laravel/passport/compare/v9.3.2...v10.0.0) ### Added + - Support Laravel 8 & drop PHP 7.2 support ([#1336](https://github.com/laravel/passport/pull/1336)) ### Changed + - `forceFill` new auth code attributes ([#1266](https://github.com/laravel/passport/pull/1266)) - Use only one PSR 7 implementation ([#1330](https://github.com/laravel/passport/pull/1330)) ### Removed + - Remove old static personal client methods ([#1325](https://github.com/laravel/passport/pull/1325)) - Remove Guzzle dependency ([#1327](https://github.com/laravel/passport/pull/1327)) - ## [v9.3.2 (2020-07-27)](https://github.com/laravel/passport/compare/v9.3.1...v9.3.2) ### Fixes -- Fix cookie handling for security release ([#1322](https://github.com/laravel/passport/pull/1322), [75f1ad2](https://github.com/laravel/passport/commit/75f1ad218ddf4500f2beb9e5c2fb186530e8ddb6)) +- Fix cookie handling for security release ([#1322](https://github.com/laravel/passport/pull/1322), [75f1ad2](https://github.com/laravel/passport/commit/75f1ad218ddf4500f2beb9e5c2fb186530e8ddb6)) ## [v9.3.1 (2020-07-21)](https://github.com/laravel/passport/compare/v9.3.0...v9.3.1) ### Fixed + - Use custom models in purge command if set ([#1316](https://github.com/laravel/passport/pull/1316)) - Apply table responsive on table class ([#1318](https://github.com/laravel/passport/pull/1318)) - ## [v9.3.0 (2020-06-30)](https://github.com/laravel/passport/compare/v9.2.2...v9.3.0) ### Added -- Guzzle 7 support ([#1311](https://github.com/laravel/passport/pull/1311)) +- Guzzle 7 support ([#1311](https://github.com/laravel/passport/pull/1311)) ## [v9.2.2 (2020-06-25)](https://github.com/laravel/passport/compare/v9.2.1...v9.2.2) ### Fixed + - Fix maxlength for token names ([#1300](https://github.com/laravel/passport/pull/1300)) - Improve `passport:install` command ([#1294](https://github.com/laravel/passport/pull/1294)) - ## [v9.2.1 (2020-05-14)](https://github.com/laravel/passport/compare/v9.2.0...v9.2.1) ### Fixed + - Fix actingAsClient token relation ([#1268](https://github.com/laravel/passport/pull/1268)) - Fix HashCommand ([bedf02c](https://github.com/laravel/passport/commit/bedf02c8bb8fb9ca373e34f0ceefb2e8c5bf006b)) - ## [v9.2.0 (2020-05-12](https://github.com/laravel/passport/compare/v9.1.0...v9.2.0) ### Added + - Allow to change Models database connection ([#1255](https://github.com/laravel/passport/pull/1255), [7ab3bdb](https://github.com/laravel/passport/commit/7ab3bdbdb9bf162f2da9d8c445523dc63c862248)) ### Fixed -- Nonstandard ID in the token's relationship with the user ([#1267](https://github.com/laravel/passport/pull/1267)) +- Nonstandard ID in the token's relationship with the user ([#1267](https://github.com/laravel/passport/pull/1267)) ## [v9.1.0 (2020-05-08](https://github.com/laravel/passport/compare/v9.0.1...v9.1.0) ### Added + - Implement secret modal ([#1258](https://github.com/laravel/passport/pull/1258)) - Warn about one-time-hashed-secret ([#1259](https://github.com/laravel/passport/pull/1259)) - Add force option to hash command ([#1251](https://github.com/laravel/passport/pull/1251)) ### Fixed -- Implement personal access client config ([#1260](https://github.com/laravel/passport/pull/1260)) +- Implement personal access client config ([#1260](https://github.com/laravel/passport/pull/1260)) ## [v9.0.1 (2020-05-06)](https://github.com/laravel/passport/compare/v9.0.0...v9.0.1) ### Fixed + - Fix displaying secret in Vue component ([#1244](https://github.com/laravel/passport/pull/1244)) - Moved provider check to bearer token only ([#1246](https://github.com/laravel/passport/pull/1246)) - Fix create client call ([aff9d09](https://github.com/laravel/passport/commit/aff9d0933737354d04df98cfc431fa20309be03a)) - ## [v9.0.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.5.0...v9.0.0) ### Added + - Allow client credentials secret to be hashed ([#1145](https://github.com/laravel/passport/pull/1145), [ccbcfeb](https://github.com/laravel/passport/commit/ccbcfeb5301e8f757395ba0e43980615acf4385e), [1c40ae0](https://github.com/laravel/passport/commit/1c40ae07503aeb23173d48f3a6e5757cafcfd71b)) - Implement `passport:hash` command ([#1238](https://github.com/laravel/passport/pull/1238)) - Initial support for multiple providers ([#1220](https://github.com/laravel/passport/pull/1220)) ### Changed + - Client credentials middleware should allow any valid client ([#1132](https://github.com/laravel/passport/pull/1132)) - Switch from `getKey()` to `getAuthIdentifier()` to match Laravel core ([#1134](https://github.com/laravel/passport/pull/1134)) - Use Hasher interface instead of HashManager ([#1157](https://github.com/laravel/passport/pull/1157)) - Bump league server dependency ([#1237](https://github.com/laravel/passport/pull/1237)) ### Removed + - Remove deprecated functionality ([#1235](https://github.com/laravel/passport/pull/1235)) - Drop support for old JWT versions ([#1236](https://github.com/laravel/passport/pull/1236)) - ## [v8.5.0 (2020-05-05)](https://github.com/laravel/passport/compare/v8.4.4...v8.5.0) ### Added -- Automatic configuration of client UUIDs ([#1231](https://github.com/laravel/passport/pull/1231)) +- Automatic configuration of client UUIDs ([#1231](https://github.com/laravel/passport/pull/1231)) ## [v8.4.4 (2020-04-21)](https://github.com/laravel/passport/compare/v8.4.3...v8.4.4) ### Fixed -- Fix 500 Internal Server Error response ([#1222](https://github.com/laravel/passport/pull/1222)) +- Fix 500 Internal Server Error response ([#1222](https://github.com/laravel/passport/pull/1222)) ## [v8.4.3 (2020-03-31)](https://github.com/laravel/passport/compare/v8.4.2...v8.4.3) ### Fixed -- Fix resolveInheritedScopes ([#1207](https://github.com/laravel/passport/pull/1207)) +- Fix resolveInheritedScopes ([#1207](https://github.com/laravel/passport/pull/1207)) ## [v8.4.2 (2020-03-24)](https://github.com/laravel/passport/compare/v8.4.1...v8.4.2) ### Fixed -- `mergeConfigFrom` already checked if app is running with config cached ([#1205](https://github.com/laravel/passport/pull/1205)) +- `mergeConfigFrom` already checked if app is running with config cached ([#1205](https://github.com/laravel/passport/pull/1205)) ## [v8.4.1 (2020-03-04)](https://github.com/laravel/passport/compare/v8.4.0...v8.4.1) ### Fixed + - Forget session keys on invalid match ([#1192](https://github.com/laravel/passport/pull/1192)) - Update dependencies for PSR request ([#1201](https://github.com/laravel/passport/pull/1201)) - ## [v8.4.0 (2020-02-12)](https://github.com/laravel/passport/compare/v8.3.1...v8.4.0) ### Changed + - Implement auth token for access requests ([#1188](https://github.com/laravel/passport/pull/1188)) ### Fixed -- Revoke refresh tokens when auth tokens get revoked ([#1186](https://github.com/laravel/passport/pull/1186)) +- Revoke refresh tokens when auth tokens get revoked ([#1186](https://github.com/laravel/passport/pull/1186)) ## [v8.3.1 (2020-01-29)](https://github.com/laravel/passport/compare/v8.3.0...v8.3.1) ### Fixed -- Remove foreign keys ([20e9b66](https://github.com/laravel/passport/commit/20e9b66fcd003ba41301fc5de23b9892e307051a)) +- Remove foreign keys ([20e9b66](https://github.com/laravel/passport/commit/20e9b66fcd003ba41301fc5de23b9892e307051a)) ## [v8.3.0 (2020-01-28)](https://github.com/laravel/passport/compare/v8.2.0...v8.3.0) ### Added + - Add a Passport Client factory to Passport publishing ([#1171](https://github.com/laravel/passport/pull/1171)) ### Changed -- Use bigIncrements and indexes on relationships ([#1169](https://github.com/laravel/passport/pull/1169), [140a693](https://github.com/laravel/passport/commit/140a693a079f5611b3342360cde00b10e94162c1)) +- Use bigIncrements and indexes on relationships ([#1169](https://github.com/laravel/passport/pull/1169), [140a693](https://github.com/laravel/passport/commit/140a693a079f5611b3342360cde00b10e94162c1)) ## [v8.2.0 (2020-01-07)](https://github.com/laravel/passport/compare/v8.1.0...v8.2.0) ### Added + - Update ClientCommand to support public clients ([#1151](https://github.com/laravel/passport/pull/1151)) - Purge Command for revoked and/or expired tokens and auth codes ([#1159](https://github.com/laravel/passport/pull/1159), [6c1ea42](https://github.com/laravel/passport/commit/6c1ea42e66100b15ecad89b0e1c5ccaa12b4331b)) ### Changed -- Replace deprecated package and namespaces ([#1158](https://github.com/laravel/passport/pull/1158)) +- Replace deprecated package and namespaces ([#1158](https://github.com/laravel/passport/pull/1158)) ## [v8.1.0 (2019-12-30)](https://github.com/laravel/passport/compare/v8.0.2...v8.1.0) ### Added + - Allow access to HTTP response status code on OAuthServerException ([#1148](https://github.com/laravel/passport/pull/1148)) - Modify UserRepository to check for 'findAndValidateForPassport' method ([#1144](https://github.com/laravel/passport/pull/1144)) - ## [v8.0.2 (2019-11-26)](https://github.com/laravel/passport/compare/v8.0.1...v8.0.2) ### Changed -- Add abstract CheckCredentials middleware and allows to create ([#1127](https://github.com/laravel/passport/pull/1127)) +- Add abstract CheckCredentials middleware and allows to create ([#1127](https://github.com/laravel/passport/pull/1127)) ## [v8.0.1 (2019-11-19)](https://github.com/laravel/passport/compare/v8.0.0...v8.0.1) ### Fixed -- Fix `actingAsClient` testing method ([#1119](https://github.com/laravel/passport/pull/1119)) +- Fix `actingAsClient` testing method ([#1119](https://github.com/laravel/passport/pull/1119)) ## [v8.0.0 (2019-10-29)](https://github.com/laravel/passport/compare/v7.5.1...v8.0.0) ### Added + - Add ability to customize the `RefreshToken` ([#966](https://github.com/laravel/passport/pull/966)) - Add support for "public" clients ([#1065](https://github.com/laravel/passport/pull/1065)) ### Changed + - Rework HandlesOAuthErrors trait to middleware ([#937](https://github.com/laravel/passport/pull/937)) - Use a renderable exception for OAuth errors ([#1066](https://github.com/laravel/passport/pull/1066)) - Use diactoros 2.0 and psr-http-factory ([aadf603](https://github.com/laravel/passport/commit/aadf603c1f45cfa4bbf954bfc3abc30cdd572683)) @@ -272,162 +291,171 @@ - Upgrade to league/oauth2-server 8.0 ([97e3026](https://github.com/laravel/passport/commit/97e3026790d953d7a67fe487e30775cd995e93df)) ### Fixed + - Fix exception will thrown if token belongs to first party clients ([#1040](https://github.com/laravel/passport/pull/1040)) - Fix auth codes table customization ([#1044](https://github.com/laravel/passport/pull/1044)) - Add key type to refresh token model ([e400c2b](https://github.com/laravel/passport/commit/e400c2b665f66b5669e792e42b6d1479cff23df7)) - ## [v7.5.1 (2019-10-08)](https://github.com/laravel/passport/compare/v7.5.0...v7.5.1) ### Fixed -- Cast returned client identifier value to string ([#1091](https://github.com/laravel/passport/pull/1091)) +- Cast returned client identifier value to string ([#1091](https://github.com/laravel/passport/pull/1091)) ## [v7.5.0 (2019-09-24)](https://github.com/laravel/passport/compare/v7.4.1...v7.5.0) ### Added -- Add `actingAsClient` method for tests ([#1083](https://github.com/laravel/passport/pull/1083)) +- Add `actingAsClient` method for tests ([#1083](https://github.com/laravel/passport/pull/1083)) ## [v7.4.1 (2019-09-10)](https://github.com/laravel/passport/compare/v7.4.0...v7.4.1) ### Fixed -- Fixed key types for models ([#1078](https://github.com/laravel/passport/pull/1078), [a9a885d3](https://github.com/laravel/passport/commit/a9a885d3c2344ec133ed42a0268e503a76810982)) +- Fixed key types for models ([#1078](https://github.com/laravel/passport/pull/1078), [a9a885d3](https://github.com/laravel/passport/commit/a9a885d3c2344ec133ed42a0268e503a76810982)) ## [v7.4.0 (2019-08-20)](https://github.com/laravel/passport/compare/v7.3.5...v7.4.0) ### Added + - Let Passport support inherited parent scopes ([#1068](https://github.com/laravel/passport/pull/1068)) - Accept requests with the encrypted X-XSRF-TOKEN HTTP header ([#1069](https://github.com/laravel/passport/pull/1069)) - ## [v7.3.5 (2019-08-06)](https://github.com/laravel/passport/compare/v7.3.4...v7.3.5) ### Fixed -- Use `bigInteger` column type for `user_id` columns ([#1057](https://github.com/laravel/passport/pull/1057)) +- Use `bigInteger` column type for `user_id` columns ([#1057](https://github.com/laravel/passport/pull/1057)) ## [v7.3.4 (2019-07-30)](https://github.com/laravel/passport/compare/v7.3.3...v7.3.4) ### Changed -- Remove old 5.9 constraints ([58eb99c](https://github.com/laravel/passport/commit/58eb99cac0668ba61f3c9dc03694848f0ac7035a)) +- Remove old 5.9 constraints ([58eb99c](https://github.com/laravel/passport/commit/58eb99cac0668ba61f3c9dc03694848f0ac7035a)) ## [v7.3.3 (2019-07-29)](https://github.com/laravel/passport/compare/v7.3.2...v7.3.3) ### Changed -- Update version constraints for Laravel 6.0 ([609b5e8](https://github.com/laravel/passport/commit/609b5e829bf65dbeffb83dc8c324275fe0ebf30c)) +- Update version constraints for Laravel 6.0 ([609b5e8](https://github.com/laravel/passport/commit/609b5e829bf65dbeffb83dc8c324275fe0ebf30c)) ## [v7.3.2 (2019-07-11)](https://github.com/laravel/passport/compare/v7.3.1...v7.3.2) ### Fixed -- Merge default Passport configuration ([#1039](https://github.com/laravel/passport/pull/1039), [e260c86](https://github.com/laravel/passport/commit/e260c865c218f00e4ad0c445dc45852e254d60c7)) +- Merge default Passport configuration ([#1039](https://github.com/laravel/passport/pull/1039), [e260c86](https://github.com/laravel/passport/commit/e260c865c218f00e4ad0c445dc45852e254d60c7)) ## [v7.3.1 (2019-07-02)](https://github.com/laravel/passport/compare/v7.3.0...v7.3.1) ### Changed -- Change server property type in `CheckClientCredentialForAnyScope` ([#1034](https://github.com/laravel/passport/pull/1034)) +- Change server property type in `CheckClientCredentialForAnyScope` ([#1034](https://github.com/laravel/passport/pull/1034)) ## [v7.3.0 (2019-05-28)](https://github.com/laravel/passport/compare/v7.2.2...v7.3.0) ### Added + - Allow first party clients to skip the authorization prompt ([#1022](https://github.com/laravel/passport/pull/1022)) ### Fixed -- Fix AccessToken docblock ([#996](https://github.com/laravel/passport/pull/996)) +- Fix AccessToken docblock ([#996](https://github.com/laravel/passport/pull/996)) ## [v7.2.2 (2019-03-13)](https://github.com/laravel/passport/compare/v7.2.1...v7.2.2) ### Fixed -- Allow installs of zend-diactoros 2 ([c0c3fca](https://github.com/laravel/passport/commit/c0c3fca80d8f5af90dcbf65e62bdd1abee9ac25d)) +- Allow installs of zend-diactoros 2 ([c0c3fca](https://github.com/laravel/passport/commit/c0c3fca80d8f5af90dcbf65e62bdd1abee9ac25d)) ## [v7.2.1 (2019-03-12)](https://github.com/laravel/passport/compare/v7.2.0...v7.2.1) ### Fixed -- Change `wasRecentlyCreated` to `false` ([#979](https://github.com/laravel/passport/pull/979)) +- Change `wasRecentlyCreated` to `false` ([#979](https://github.com/laravel/passport/pull/979)) ## [v7.2.0 (2019-02-14)](https://github.com/laravel/passport/compare/v7.1.0...v7.2.0) ### Changed + - Changed the way to get action path from `url()` to `route()` ([#950](https://github.com/laravel/passport/pull/950)) - Allow `'*'` scope to be used with Client Credentials ([#949](https://github.com/laravel/passport/pull/949)) ### Fixed -- Replace `fire()` with `dispatch()` ([#952](https://github.com/laravel/passport/pull/952)) +- Replace `fire()` with `dispatch()` ([#952](https://github.com/laravel/passport/pull/952)) ## [v7.1.0 (2019-01-22)](https://github.com/laravel/passport/compare/v7.0.5...v7.1.0) ### Added + - Added `redirect_uri` and `user_id` options to cli ([#921](https://github.com/laravel/passport/pull/921), [8b8570c](https://github.com/laravel/passport/commit/8b8570cc297ac7216d8f8caebb78a1e916093458)) - Add `ext-json` dependency ([#940](https://github.com/laravel/passport/pull/940)) ### Changed + - Make name an optional question ([#926](https://github.com/laravel/passport/pull/926)) ### Fixed + - Do not auto increment `AuthCode` ID ([#929](https://github.com/laravel/passport/pull/929)) - Allow multiple redirects when creating clients ([#928](https://github.com/laravel/passport/pull/928)) - Add responses for destroy methods ([#942](https://github.com/laravel/passport/pull/942)) - ## [v7.0.5 (2019-01-02)](https://github.com/laravel/passport/compare/v7.0.4...v7.0.5) ### Fixed -- Rename property ([#920](https://github.com/laravel/passport/pull/920)) +- Rename property ([#920](https://github.com/laravel/passport/pull/920)) ## [v7.0.4 (2018-12-31)](https://github.com/laravel/passport/compare/v7.0.3...v7.0.4) ### Added + - Add middleware CheckClientCredentialsForAnyScope ([#855](https://github.com/laravel/passport/pull/855)) - Support a default scope when no scope was requested by the client ([#879](https://github.com/laravel/passport/pull/879)) - Allow setting expiration of personal access tokens ([#919](https://github.com/laravel/passport/pull/919)) ### Changed + - Change auth code table to the model's table ([#865](https://github.com/laravel/passport/pull/865)) - Made whereRevoked consistent ([#868](https://github.com/laravel/passport/pull/868)) - Use unsignedInteger column type for `client_id` columns ([47f0021](https://github.com/laravel/passport/commit/47f00212c2f9b26ef6b90444facb8d8178b7dae6)) ### Fixed -- Prevent passing empty string variable to retrieveById method ([#861](https://github.com/laravel/passport/pull/861)) +- Prevent passing empty string variable to retrieveById method ([#861](https://github.com/laravel/passport/pull/861)) ## [v7.0.3 (2018-10-22)](https://github.com/laravel/passport/compare/v7.0.2...v7.0.3) ### Added + - Add names to routes for re-usability ([#846](https://github.com/laravel/passport/pull/846)) - Add user relationship to client model ([#851](https://github.com/laravel/passport/pull/851), [3213be8](https://github.com/laravel/passport/commit/3213be8c7c449037d1e5507f9b5ef1fb3ddb16a2)) - Add the ability to retrieve current client ([#854](https://github.com/laravel/passport/pull/854)) ### Fixed -- Fix migrations tag publish ([#832](https://github.com/laravel/passport/pull/832)) +- Fix migrations tag publish ([#832](https://github.com/laravel/passport/pull/832)) ## [v7.0.2 (2018-09-25)](https://github.com/laravel/passport/compare/v7.0.1...v7.0.2) ### Changed + - `Authcode` model is now used for persisting new authcodes ([#808](https://github.com/laravel/passport/pull/808)) - `resources/assets` directory was flattened ([#813](https://github.com/laravel/passport/pull/813)) ### Fixed -- Personal client exception ([#831](https://github.com/laravel/passport/pull/831), [7bb53d1](https://github.com/laravel/passport/commit/7bb53d1ae4f8f375cc9461d232053958740002da)) +- Personal client exception ([#831](https://github.com/laravel/passport/pull/831), [7bb53d1](https://github.com/laravel/passport/commit/7bb53d1ae4f8f375cc9461d232053958740002da)) ## [v7.0.1 (2018-08-13)](https://github.com/laravel/passport/compare/v7.0.0...v7.0.1) ### Added -- Add option to enable cookie serialization ([9012496](https://github.com/laravel/passport/commit/90124969cdd4ff39d4cd5a608c23bbe16e772f7e)) +- Add option to enable cookie serialization ([9012496](https://github.com/laravel/passport/commit/90124969cdd4ff39d4cd5a608c23bbe16e772f7e)) ## [v7.0.0 (2018-08-13)](https://github.com/laravel/passport/compare/v6.0.7...v7.0.0) ### Changed + - Don't serialize by default ([29e9d53](https://github.com/laravel/passport/commit/29e9d5312f3b11381f1fd472bde1fbbd73122cf1)) From 1039d8b4aa71c45dbea2f140b131cae8802237e7 Mon Sep 17 00:00:00 2001 From: Markus Machatschek Date: Wed, 23 Feb 2022 16:04:04 +0100 Subject: [PATCH 250/353] Use anonymous migrations (#1531) --- composer.json | 18 +++++++++--------- ...01_000001_create_oauth_auth_codes_table.php | 4 ++-- ...000002_create_oauth_access_tokens_table.php | 4 ++-- ...00003_create_oauth_refresh_tokens_table.php | 4 ++-- ...06_01_000004_create_oauth_clients_table.php | 4 ++-- ...ate_oauth_personal_access_clients_table.php | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index bea4a04e3..3a2df2535 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,15 @@ "php": "^7.3|^8.0", "ext-json": "*", "firebase/php-jwt": "^5.0", - "illuminate/auth": "^8.2|^9.0", - "illuminate/console": "^8.2|^9.0", - "illuminate/container": "^8.2|^9.0", - "illuminate/contracts": "^8.2|^9.0", - "illuminate/cookie": "^8.2|^9.0", - "illuminate/database": "^8.2|^9.0", - "illuminate/encryption": "^8.2|^9.0", - "illuminate/http": "^8.2|^9.0", - "illuminate/support": "^8.2|^9.0", + "illuminate/auth": "^8.37|^9.0", + "illuminate/console": "^8.37|^9.0", + "illuminate/container": "^8.37|^9.0", + "illuminate/contracts": "^8.37|^9.0", + "illuminate/cookie": "^8.37|^9.0", + "illuminate/database": "^8.37|^9.0", + "illuminate/encryption": "^8.37|^9.0", + "illuminate/http": "^8.37|^9.0", + "illuminate/support": "^8.37|^9.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 0eabf059c..195685f7a 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOauthAuthCodesTable extends Migration +return new class extends Migration { /** * The database schema. @@ -59,4 +59,4 @@ public function getConnection() { return config('passport.storage.database.connection'); } -} +}; diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 67c682d5f..c8ecd7227 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOauthAccessTokensTable extends Migration +return new class extends Migration { /** * The database schema. @@ -61,4 +61,4 @@ public function getConnection() { return config('passport.storage.database.connection'); } -} +}; diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index b4ac09544..998b63158 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOauthRefreshTokensTable extends Migration +return new class extends Migration { /** * The database schema. @@ -57,4 +57,4 @@ public function getConnection() { return config('passport.storage.database.connection'); } -} +}; diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 6ce3d9974..51e597c2b 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOauthClientsTable extends Migration +return new class extends Migration { /** * The database schema. @@ -63,4 +63,4 @@ public function down() { $this->schema->dropIfExists('oauth_clients'); } -} +}; diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index c408248f5..e12920ab7 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOauthPersonalAccessClientsTable extends Migration +return new class extends Migration { /** * The database schema. @@ -56,4 +56,4 @@ public function getConnection() { return config('passport.storage.database.connection'); } -} +}; From 3ef9e2b8d7b1ccab128084fe51b95ff06c9e2d72 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 8 Mar 2022 16:31:48 +0000 Subject: [PATCH 251/353] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b2668ff8..12d407416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.3.2...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.3.3...10.x) + +## [v10.3.3](https://github.com/laravel/passport/compare/v10.3.2...v10.3.3) - 2022-03-08 + +### Changed + +- Use anonymous migrations by @mmachatschek in https://github.com/laravel/passport/pull/1531 ## [v10.3.2](https://github.com/laravel/passport/compare/v10.3.1...v10.3.2) - 2022-02-22 From 61832d38eb788a0953d70a756557de2ff9af1a3c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 17 Mar 2022 10:54:22 +0100 Subject: [PATCH 252/353] Update .styleci.yml --- .styleci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.styleci.yml b/.styleci.yml index 215fbcfe3..e101e8c60 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -1,4 +1,5 @@ php: preset: laravel + version: 8.1 js: true css: true From f1741c3c1ade298aeb4ed03242af2b5ae2dc47b6 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 17 Mar 2022 11:06:46 +0100 Subject: [PATCH 253/353] Update .styleci.yml --- .styleci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.styleci.yml b/.styleci.yml index e101e8c60..215fbcfe3 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -1,5 +1,4 @@ php: preset: laravel - version: 8.1 js: true css: true From 31e4ec6a66b9b92dc5b67cea7c2ee03c7c135064 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 23 Mar 2022 13:35:12 +0100 Subject: [PATCH 254/353] Update update-changelog.yml --- .github/workflows/update-changelog.yml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 0200e2b94..eaeaf1f88 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -6,24 +6,4 @@ on: jobs: update: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.ref_name }} - - - name: Update Changelog - uses: stefanzweifel/changelog-updater-action@v1 - with: - latest-version: ${{ github.event.release.tag_name }} - release-notes: ${{ github.event.release.body }} - compare-url-target-revision: ${{ github.event.release.target_commitish }} - - - name: Commit updated CHANGELOG - uses: stefanzweifel/git-auto-commit-action@v4 - with: - branch: ${{ github.event.release.target_commitish }} - commit_message: Update CHANGELOG.md - file_pattern: CHANGELOG.md + uses: laravel/.github/.github/workflows/update-changelog.yml@main From 5bb6637cb5bf397381be4542719ea3694c808dcd Mon Sep 17 00:00:00 2001 From: David Kanenwisher Date: Wed, 30 Mar 2022 09:42:50 -0500 Subject: [PATCH 255/353] Upgrade firebase/php-jwt to ^6.0 (#1538) The firebase/php-jwt recently had to make breaking changes to resolve a security flaw in their library. This change upgrades that library and fixes the code that broke with the upgrade. --- composer.json | 2 +- src/ApiTokenCookieFactory.php | 2 +- src/Guards/TokenGuard.php | 4 ++-- tests/Unit/TokenGuardTest.php | 18 +++++++++--------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index 3a2df2535..0ebd9386e 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require": { "php": "^7.3|^8.0", "ext-json": "*", - "firebase/php-jwt": "^5.0", + "firebase/php-jwt": "^6.0", "illuminate/auth": "^8.37|^9.0", "illuminate/console": "^8.37|^9.0", "illuminate/container": "^8.37|^9.0", diff --git a/src/ApiTokenCookieFactory.php b/src/ApiTokenCookieFactory.php index 3d7d83d02..ffed5d1e3 100644 --- a/src/ApiTokenCookieFactory.php +++ b/src/ApiTokenCookieFactory.php @@ -77,6 +77,6 @@ protected function createToken($userId, $csrfToken, Carbon $expiration) 'sub' => $userId, 'csrf' => $csrfToken, 'expiry' => $expiration->getTimestamp(), - ], Passport::tokenEncryptionKey($this->encrypter)); + ], Passport::tokenEncryptionKey($this->encrypter), 'HS256'); } } diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 00cbe4863..921223edd 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -4,6 +4,7 @@ use Exception; use Firebase\JWT\JWT; +use Firebase\JWT\Key; use Illuminate\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Encryption\Encrypter; @@ -269,8 +270,7 @@ protected function decodeJwtTokenCookie($request) { return (array) JWT::decode( CookieValuePrefix::remove($this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies)), - Passport::tokenEncryptionKey($this->encrypter), - ['HS256'] + new Key(Passport::tokenEncryptionKey($this->encrypter), 'HS256') ); } diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index b586eff99..83608d861 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -134,7 +134,7 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16)), false) + ], str_repeat('a', 16), 'HS256'), false) ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); @@ -167,7 +167,7 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16)), false) + ], str_repeat('a', 16), 'HS256'), false) ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); @@ -196,7 +196,7 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16))) + ], str_repeat('a', 16), 'HS256')) ); $userProvider->shouldReceive('retrieveById')->never(); @@ -222,7 +222,7 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16))) + ], str_repeat('a', 16), 'HS256')) ); $userProvider->shouldReceive('retrieveById')->never(); @@ -256,7 +256,7 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], Passport::tokenEncryptionKey($encrypter)), false) + ], Passport::tokenEncryptionKey($encrypter), 'HS256'), false) ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); @@ -288,7 +288,7 @@ public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16))) + ], str_repeat('a', 16), 'HS256')) ); $userProvider->shouldReceive('retrieveById')->never(); @@ -314,7 +314,7 @@ public function test_expired_cookies_may_not_be_used() 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->subMinutes(10)->getTimestamp(), - ], str_repeat('a', 16))) + ], str_repeat('a', 16), 'HS256')) ); $userProvider->shouldReceive('retrieveById')->never(); @@ -344,7 +344,7 @@ public function test_csrf_check_can_be_disabled() 'sub' => 1, 'aud' => 1, 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16)), false) + ], str_repeat('a', 16), 'HS256'), false) ); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); @@ -443,7 +443,7 @@ public function test_clients_may_be_retrieved_from_cookies() 'aud' => 1, 'csrf' => 'token', 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), - ], str_repeat('a', 16)), false) + ], str_repeat('a', 16), 'HS256'), false) ); $clients->shouldReceive('findActive')->with(1)->andReturn($expectedClient = new TokenGuardTestClient); From 1d6280e7280c11cbfc8e550db80d531fd55f599b Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 5 Apr 2022 15:30:12 +0000 Subject: [PATCH 256/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12d407416..f6e972891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.3.3...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.4.0...10.x) + +## [v10.4.0](https://github.com/laravel/passport/compare/v10.3.3...v10.4.0) - 2022-03-30 + +### Changed + +- Upgrade firebase/php-jwt to ^6.0 by @prufrock in https://github.com/laravel/passport/pull/1538 ## [v10.3.3](https://github.com/laravel/passport/compare/v10.3.2...v10.3.3) - 2022-03-08 From abd3f11fb368a7cd5d3ac31f88d5f09aadf24789 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 Apr 2022 11:06:34 +0200 Subject: [PATCH 257/353] Create pull-requests.yml --- .github/workflows/pull-requests.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/pull-requests.yml diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/.github/workflows/pull-requests.yml @@ -0,0 +1 @@ + From c9591e4df43321834c549d1cec0a5483797c5ef2 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 Apr 2022 11:15:58 +0200 Subject: [PATCH 258/353] Update pull-requests.yml --- .github/workflows/pull-requests.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index 8b1378917..156b46eb4 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -1 +1,13 @@ +name: Pull Requests +on: + pull_request_target: + types: + - opened + +permissions: + pull-requests: write + +jobs: + uneditable: + uses: laravel/.github/.github/workflows/pull-requests.yml@main From 499d68d3dcbd7680562379c2a6ee616200e558e5 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 8 Apr 2022 15:37:16 +0200 Subject: [PATCH 259/353] Update tests.yml (#1540) --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2d0bcbc33..64514f889 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,6 +32,7 @@ jobs: with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick + ini-values: error_reporting=E_ALL tools: composer:v2 coverage: none From 6e39bb046f08e45d70dcd6ca97e5b6689e5f3051 Mon Sep 17 00:00:00 2001 From: vic Date: Sat, 16 Apr 2022 06:37:53 -0700 Subject: [PATCH 260/353] [ADD] new URI Rule to validate URI and use it to RedirectRule (#1544) --- src/Http/Rules/RedirectRule.php | 5 +++-- src/Http/Rules/UriRule.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/Http/Rules/UriRule.php diff --git a/src/Http/Rules/RedirectRule.php b/src/Http/Rules/RedirectRule.php index dd8b99720..ab0346c23 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Validation\Factory; use Illuminate\Contracts\Validation\Rule; +use Laravel\Passport\Http\Rules\UriRule; class RedirectRule implements Rule { @@ -31,7 +32,7 @@ public function __construct(Factory $validator) public function passes($attribute, $value) { foreach (explode(',', $value) as $redirect) { - $validator = $this->validator->make(['redirect' => $redirect], ['redirect' => 'url']); + $validator = $this->validator->make(['redirect' => $redirect], ['redirect' => new UriRule]); if ($validator->fails()) { return false; @@ -46,6 +47,6 @@ public function passes($attribute, $value) */ public function message() { - return 'One or more redirects have an invalid url format.'; + return 'One or more redirects have an invalid URI format.'; } } diff --git a/src/Http/Rules/UriRule.php b/src/Http/Rules/UriRule.php new file mode 100644 index 000000000..f6d02c65e --- /dev/null +++ b/src/Http/Rules/UriRule.php @@ -0,0 +1,28 @@ + Date: Sat, 16 Apr 2022 13:38:08 +0000 Subject: [PATCH 261/353] Apply fixes from StyleCI --- src/Http/Rules/RedirectRule.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/Rules/RedirectRule.php b/src/Http/Rules/RedirectRule.php index ab0346c23..e14d11c3d 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -4,7 +4,6 @@ use Illuminate\Contracts\Validation\Factory; use Illuminate\Contracts\Validation\Rule; -use Laravel\Passport\Http\Rules\UriRule; class RedirectRule implements Rule { From 3498c408dee47b3b0081960d975de3b9644d77e8 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 19 Apr 2022 15:37:59 +0000 Subject: [PATCH 262/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e972891..543b8f20b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.4.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v10.4.1...10.x) + +## [v10.4.1](https://github.com/laravel/passport/compare/v10.4.0...v10.4.1) - 2022-04-16 + +### Changed + +- Add new URI Rule to validate URI and use it to RedirectRule. by @victorbalssa in https://github.com/laravel/passport/pull/1544 ## [v10.4.0](https://github.com/laravel/passport/compare/v10.3.3...v10.4.0) - 2022-03-30 From 9c6e8c11b9a0cc116e70df0f9d86bf409872e043 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 8 Jun 2022 11:31:47 +0200 Subject: [PATCH 263/353] Update pull-requests.yml --- .github/workflows/pull-requests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index 156b46eb4..18b32b326 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -1,9 +1,8 @@ -name: Pull Requests +name: pull requests on: pull_request_target: - types: - - opened + types: [opened] permissions: pull-requests: write From 75fd509928952ccbaff47e609d4f0e657a2c22cf Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 8 Jun 2022 11:32:00 +0200 Subject: [PATCH 264/353] Update update-changelog.yml --- .github/workflows/update-changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index eaeaf1f88..1625bda10 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -1,4 +1,4 @@ -name: "Update Changelog" +name: update changelog on: release: From ed6f6c1d7582d4650bd9ccdf37ee950f11383940 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Wed, 13 Jul 2022 16:39:47 +0200 Subject: [PATCH 265/353] [11.x] Fix scope inheritance when using Passport::actingAs() (#1551) * Fix scope inheritance when using Passport::actingAs() * Update Passport.php Co-authored-by: Taylor Otwell --- src/Passport.php | 6 ++---- tests/Feature/ActingAsTest.php | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index bec7ce9fb..67851b866 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -364,11 +364,9 @@ public static function ignoreCsrfToken($ignoreCsrfToken = true) */ public static function actingAs($user, $scopes = [], $guard = 'api') { - $token = Mockery::mock(self::tokenModel())->shouldIgnoreMissing(false); + $token = app(self::tokenModel()); - foreach ($scopes as $scope) { - $token->shouldReceive('can')->with($scope)->andReturn(true); - } + $token->scopes = $scopes; $user->withAccessToken($token); diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index aa1b3ecea..bf0b95319 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Routing\Registrar; use Illuminate\Foundation\Auth\User; +use Illuminate\Support\Facades\Route; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Http\Middleware\CheckForAnyScope; use Laravel\Passport\Http\Middleware\CheckScopes; @@ -64,6 +65,40 @@ public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware( $response->assertSuccessful(); $response->assertSee('bar'); } + + public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddlewareWithInheritance() + { + Passport::$withInheritedScopes = true; + + $this->withoutExceptionHandling(); + + Route::middleware(CheckScopes::class.':foo:bar,baz:qux')->get('/foo', function () { + return 'bar'; + }); + + Passport::actingAs(new PassportUser(), ['foo', 'baz']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } + + public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddlewareWithInheritance() + { + Passport::$withInheritedScopes = true; + + $this->withoutExceptionHandling(); + + Route::middleware(CheckForAnyScope::class.':foo:baz,baz:qux')->get('/foo', function () { + return 'bar'; + }); + + Passport::actingAs(new PassportUser(), ['foo']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } } class PassportUser extends User From 836f5506aaf1095c8f4dc7c358ce83a85c3f5fde Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 16 Aug 2022 16:29:05 +0200 Subject: [PATCH 266/353] Drop PHP 7.x and Laravel v8 (#1558) --- .github/workflows/tests.yml | 9 ++------- composer.json | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 64514f889..d6cf7f407 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,13 +13,8 @@ jobs: strategy: fail-fast: true matrix: - php: [7.3, 7.4, '8.0', 8.1] - laravel: [8, 9] - exclude: - - php: 7.3 - laravel: 9 - - php: 7.4 - laravel: 9 + php: ['8.0', 8.1] + laravel: [9] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} diff --git a/composer.json b/composer.json index 124b5e58d..6762200af 100644 --- a/composer.json +++ b/composer.json @@ -14,18 +14,18 @@ } ], "require": { - "php": "^7.3|^8.0", + "php": "^8.0", "ext-json": "*", "firebase/php-jwt": "^6.0", - "illuminate/auth": "^8.37|^9.0", - "illuminate/console": "^8.37|^9.0", - "illuminate/container": "^8.37|^9.0", - "illuminate/contracts": "^8.37|^9.0", - "illuminate/cookie": "^8.37|^9.0", - "illuminate/database": "^8.37|^9.0", - "illuminate/encryption": "^8.37|^9.0", - "illuminate/http": "^8.37|^9.0", - "illuminate/support": "^8.37|^9.0", + "illuminate/auth": "^9.0", + "illuminate/console": "^9.0", + "illuminate/container": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/cookie": "^9.0", + "illuminate/database": "^9.0", + "illuminate/encryption": "^9.0", + "illuminate/http": "^9.0", + "illuminate/support": "^9.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", @@ -34,7 +34,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^6.0|^7.0", + "orchestra/testbench": "^7.0", "phpunit/phpunit": "^9.3" }, "autoload": { From 516cddbb817a01a176cea413a2df0976844572c3 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 16 Aug 2022 16:47:51 +0200 Subject: [PATCH 267/353] Remove deprecated properties (#1560) --- src/Passport.php | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index 67851b866..f3c11d969 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -35,15 +35,6 @@ class Passport // ]; - /** - * The date when access tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $tokensExpireAt; - /** * The interval when access tokens expire. * @@ -51,15 +42,6 @@ class Passport */ public static $tokensExpireIn; - /** - * The date when refresh tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $refreshTokensExpireAt; - /** * The date when refresh tokens expire. * @@ -67,15 +49,6 @@ class Passport */ public static $refreshTokensExpireIn; - /** - * The date when personal access tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $personalAccessTokensExpireAt; - /** * The date when personal access tokens expire. * @@ -282,7 +255,6 @@ public static function tokensExpireIn(DateTimeInterface $date = null) return static::$tokensExpireIn ?? new DateInterval('P1Y'); } - static::$tokensExpireAt = $date; static::$tokensExpireIn = Carbon::now()->diff($date); return new static; @@ -300,7 +272,6 @@ public static function refreshTokensExpireIn(DateTimeInterface $date = null) return static::$refreshTokensExpireIn ?? new DateInterval('P1Y'); } - static::$refreshTokensExpireAt = $date; static::$refreshTokensExpireIn = Carbon::now()->diff($date); return new static; @@ -318,7 +289,6 @@ public static function personalAccessTokensExpireIn(DateTimeInterface $date = nu return static::$personalAccessTokensExpireIn ?? new DateInterval('P1Y'); } - static::$personalAccessTokensExpireAt = $date; static::$personalAccessTokensExpireIn = Carbon::now()->diff($date); return new static; From a17975f438b86f494f29f7ebfcd44c7d8562af12 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 19 Aug 2022 13:53:39 +0200 Subject: [PATCH 268/353] wip --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c151df28..7dbaac2af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.4.1...master) +## [Unreleased](https://github.com/laravel/passport/compare/v10.4.1...11.x) ## [v10.4.1](https://github.com/laravel/passport/compare/v10.4.0...v10.4.1) - 2022-04-16 From a57723e58faaa70c5629d2a15f7ecc291e98fd73 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 19 Aug 2022 17:00:43 +0200 Subject: [PATCH 269/353] Passport v11 upgrade guide (#1561) * Passport v11 upgrade guide * Update UPGRADE.md Co-authored-by: Taylor Otwell --- UPGRADE.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 4df35ceb5..643f7640d 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -2,6 +2,50 @@ ## General Notes +## Upgrading To 11.0 From 10.x + +### Minimum PHP Version + +PHP 8.0 is now the minimum required version. + +### Minimum Laravel Version + +Laravel 9.0 is now the minimum required version. + +### Reverting Model DB Connection Customization + +PR: https://github.com/laravel/passport/pull/1412 + +Customizing model database connections through the migration files has been reverted. This was first introduced in [this PR](https://github.com/laravel/passport/pull/1255). + +If you need to customize the database connection for a model you should override the models [as explained in the documentation](https://laravel.com/docs/9.x/passport#overriding-default-models). + +### Allow Timestamps On Token model + +PR: https://github.com/laravel/passport/pull/1425 + +Timestamps are now allowed on the `Token` model. If you specifically didn't want these model's timestamps to be updated then you may override the `Token` model [as explained in the documentation](https://laravel.com/docs/9.x/passport#overriding-default-models). + +### Refactor Routes To Dedicated File + +PR: https://github.com/laravel/passport/pull/1464 + +Passport's routes have been moved to a dedicated route file. You can remove the `Passport::routes()` call from your application's service provider. + +If you previously relied on overwriting routes using `routes($callback = null, array $options = [])` you may now achieve the same behavior by simply overwriting the routes in your application's own `web.php` route file. + +### Stubbing Client In Tests + +PR: https://github.com/laravel/passport/pull/1519 + +Previously, a stubbed client created via `Passport::actingAsClient(...)` wasn't retrieved when calling the `->client()` method on the API guard. This has been fixed in Passport v11 to reflect real-world situations and you may need to accommodate for this behavior in your tests. + +### Scope Inheritance In Tests + +PR: https://github.com/laravel/passport/pull/1551 + +Previously, scopes weren't inherited when using `Passport::actingAs(...)`. This has been fixed in Passport v11 to reflect real-world situations and you may need to accommodate for this behavior in your tests. + ## Upgrading To 10.0 From 9.x ### Minimum PHP Version From dd00df75cc10f14186f71edb39a8839627ef837e Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 19 Aug 2022 17:05:01 +0200 Subject: [PATCH 270/353] [11.x] Remove deprecated functionality and simplify some feature tests (#1559) * Drop JWT v3 * wip --- src/Http/Controllers/AccessTokenController.php | 15 +-------------- src/PersonalAccessTokenFactory.php | 4 +--- tests/Feature/AccessTokenControllerTest.php | 15 +++------------ tests/Unit/AccessTokenControllerTest.php | 7 ++----- 4 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index 3667c2d92..7c3b395bc 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -3,7 +3,6 @@ namespace Laravel\Passport\Http\Controllers; use Laravel\Passport\TokenRepository; -use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; @@ -26,28 +25,16 @@ class AccessTokenController */ protected $tokens; - /** - * The JWT parser instance. - * - * @var \Lcobucci\JWT\Parser - * - * @deprecated This property will be removed in a future Passport version. - */ - protected $jwt; - /** * Create a new controller instance. * * @param \League\OAuth2\Server\AuthorizationServer $server * @param \Laravel\Passport\TokenRepository $tokens - * @param \Lcobucci\JWT\Parser $jwt * @return void */ public function __construct(AuthorizationServer $server, - TokenRepository $tokens, - JwtParser $jwt) + TokenRepository $tokens) { - $this->jwt = $jwt; $this->server = $server; $this->tokens = $tokens; } diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index b849d069f..65817a7a1 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -35,8 +35,6 @@ class PersonalAccessTokenFactory * The JWT token parser instance. * * @var \Lcobucci\JWT\Parser - * - * @deprecated This property will be removed in a future Passport version. */ protected $jwt; @@ -126,7 +124,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ * @param array $response * @return \Laravel\Passport\Token */ - protected function findAccessToken(array $response) + public function findAccessToken(array $response) { return $this->tokens->find( $this->jwt->parse($response['access_token'])->claims()->get('jti') diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 451107d30..073f65d62 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -7,13 +7,11 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Laravel\Passport\Client; -use Laravel\Passport\ClientRepository; use Laravel\Passport\Database\Factories\ClientFactory; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Passport; +use Laravel\Passport\PersonalAccessTokenFactory; use Laravel\Passport\Token; -use Laravel\Passport\TokenRepository; -use Lcobucci\JWT\Configuration; class AccessTokenControllerTest extends PassportTestCase { @@ -78,10 +76,7 @@ public function testGettingAccessTokenWithClientCredentialsGrant() $expiresInSeconds = 31536000; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $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->claims()->get('jti')); + $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); $this->assertInstanceOf(Token::class, $token); $this->assertTrue($token->client->is($client)); $this->assertFalse($token->revoked); @@ -171,11 +166,7 @@ public function testGettingAccessTokenWithPasswordGrant() $expiresInSeconds = 31536000; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $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->claims()->get('jti')); + $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); $this->assertInstanceOf(Token::class, $token); $this->assertFalse($token->revoked); $this->assertTrue($token->user->is($user)); diff --git a/tests/Unit/AccessTokenControllerTest.php b/tests/Unit/AccessTokenControllerTest.php index 0e451fc97..bcd72cb55 100644 --- a/tests/Unit/AccessTokenControllerTest.php +++ b/tests/Unit/AccessTokenControllerTest.php @@ -5,7 +5,6 @@ use Laravel\Passport\Exceptions\OAuthServerException; use Laravel\Passport\Http\Controllers\AccessTokenController; use Laravel\Passport\TokenRepository; -use Lcobucci\JWT\Parser; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; use Mockery as m; @@ -26,7 +25,6 @@ public function test_a_token_can_be_issued() $request = m::mock(ServerRequestInterface::class); $response = m::type(ResponseInterface::class); $tokens = m::mock(TokenRepository::class); - $jwt = m::mock(Parser::class); $psrResponse = new Response(); $psrResponse->getBody()->write(json_encode(['access_token' => 'access-token'])); @@ -36,7 +34,7 @@ public function test_a_token_can_be_issued() ->with($request, $response) ->andReturn($psrResponse); - $controller = new AccessTokenController($server, $tokens, $jwt); + $controller = new AccessTokenController($server, $tokens); $this->assertSame('{"access_token":"access-token"}', $controller->issueToken($request)->getContent()); } @@ -44,14 +42,13 @@ public function test_a_token_can_be_issued() public function test_exceptions_are_handled() { $tokens = m::mock(TokenRepository::class); - $jwt = m::mock(Parser::class); $server = m::mock(AuthorizationServer::class); $server->shouldReceive('respondToAccessTokenRequest')->with( m::type(ServerRequestInterface::class), m::type(ResponseInterface::class) )->andThrow(LeagueException::invalidCredentials()); - $controller = new AccessTokenController($server, $tokens, $jwt); + $controller = new AccessTokenController($server, $tokens); $this->expectException(OAuthServerException::class); From dac2be68174104d9d56051144d2c3b634f37d54d Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 23 Aug 2022 15:07:40 +0000 Subject: [PATCH 271/353] Update CHANGELOG --- CHANGELOG.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbaac2af..e8e4a60c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,30 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.4.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.0.0...11.x) + +## [v11.0.0](https://github.com/laravel/passport/compare/v10.4.1...v11.0.0) - 2022-08-19 + +### Added + +- Allow authenticated client to be retrieved from the guard by @axlon in https://github.com/laravel/passport/pull/1508 + +### Changed + +- Revert model DB connection customization by @driesvints in https://github.com/laravel/passport/pull/1412 +- Allow timestamps on Token model by @driesvints in https://github.com/laravel/passport/pull/1425 +- Improve authenticateViaBearerToken() performance by @alecpl in https://github.com/laravel/passport/pull/1447 +- Refactor routes to dedicated file by @driesvints in https://github.com/laravel/passport/pull/1464 + +### Fixed + +- Stub client on guard when calling Passport::actingAsClient() by @axlon in https://github.com/laravel/passport/pull/1519 +- Fix scope inheritance when using Passport::actingAs() by @axlon in https://github.com/laravel/passport/pull/1551 + +### Removed + +- Drop PHP 7.x and Laravel v8 by @driesvints in https://github.com/laravel/passport/pull/1558 +- Remove deprecated properties by @driesvints in https://github.com/laravel/passport/pull/1560 +- Remove deprecated functionality and simplify some feature tests by @driesvints in https://github.com/laravel/passport/pull/1559 ## [v10.4.1](https://github.com/laravel/passport/compare/v10.4.0...v10.4.1) - 2022-04-16 From 5629f1ac822dc1abb59c292aab8c454f67080ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Garc=C3=ADa?= Date: Wed, 24 Aug 2022 15:20:26 +0100 Subject: [PATCH 272/353] [11.x] Custom days and hours to passport purge command (#1563) * Custom days and hours to passport purge command * lint fix * formatting Co-authored-by: Ruben Garcia Co-authored-by: Taylor Otwell --- src/Console/PurgeCommand.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 7854c6ab2..e42a6ad0d 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -15,7 +15,8 @@ class PurgeCommand extends Command */ protected $signature = 'passport:purge {--revoked : Only purge revoked tokens and authentication codes} - {--expired : Only purge expired tokens and authentication codes}'; + {--expired : Only purge expired tokens and authentication codes} + {--hours= : The number of hours to retain expired tokens}'; /** * The console command description. @@ -29,7 +30,9 @@ class PurgeCommand extends Command */ public function handle() { - $expired = Carbon::now()->subDays(7); + $expired = $this->option('hours') + ? Carbon::now()->subHours($this->option('hours')) + : Carbon::now()->subDays(7); if (($this->option('revoked') && $this->option('expired')) || (! $this->option('revoked') && ! $this->option('expired'))) { From e312f36e35e695877c4f4eee54c9cc1dcca20eef Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Mon, 29 Aug 2022 15:56:25 +0200 Subject: [PATCH 273/353] [11.x] Allow for bootstrapping without loading routes (#1564) * Allow for bootstrapping without loading routes * Update Passport.php Co-authored-by: Taylor Otwell --- src/Passport.php | 19 +++++++++++++++++++ src/PassportServiceProvider.php | 16 +++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Passport.php b/src/Passport.php index f3c11d969..6e577ebea 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -161,6 +161,13 @@ class Passport */ public static $authorizationServerResponseType; + /** + * Indicates if Passport routes will be registered. + * + * @var bool + */ + public static $registersRoutes = true; + /** * Enable the implicit grant type. * @@ -630,6 +637,18 @@ public static function tokenEncryptionKey(Encrypter $encrypter) $encrypter->getKey(); } + /** + * Configure Passport to not register its routes. + * + * @return static + */ + public static function ignoreRoutes() + { + static::$registersRoutes = false; + + return new static; + } + /** * Configure Passport to not register its migrations. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 7ce8834a5..236e7d874 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -50,13 +50,15 @@ public function boot() */ protected function registerRoutes() { - Route::group([ - 'as' => 'passport.', - 'prefix' => config('passport.path', 'oauth'), - 'namespace' => 'Laravel\Passport\Http\Controllers', - ], function () { - $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); - }); + if (Passport::$registersRoutes) { + Route::group([ + 'as' => 'passport.', + 'prefix' => config('passport.path', 'oauth'), + 'namespace' => 'Laravel\Passport\Http\Controllers', + ], function () { + $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); + }); + } } /** From 8aeec7106a9a2f7c98fc1989e8de072e76b565f7 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 30 Aug 2022 15:24:46 +0000 Subject: [PATCH 274/353] Update CHANGELOG --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8e4a60c9..c2f07ebc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.0.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.0.1...11.x) + +## [v11.0.1](https://github.com/laravel/passport/compare/v11.0.0...v11.0.1) - 2022-08-29 + +### Changed + +- Custom days and hours to passport purge command by @rubengg86 in https://github.com/laravel/passport/pull/1563 +- Allow for bootstrapping without loading routes by @axlon in https://github.com/laravel/passport/pull/1564 ## [v11.0.0](https://github.com/laravel/passport/compare/v10.4.1...v11.0.0) - 2022-08-19 From cae735ae430bd882e6469839ca814ae9e378d870 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 1 Sep 2022 14:59:37 +0000 Subject: [PATCH 275/353] [11.x] Support prompting re-consent when redirecting for authorization (#1567) * Support prompting re-consent * Update AuthorizationController.php Co-authored-by: Taylor Otwell --- .../Controllers/AuthorizationController.php | 27 +++++++--- tests/Unit/AuthorizationControllerTest.php | 53 ++++++++++++++++++- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 22e08ef23..5eb2d5db8 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -63,14 +63,11 @@ public function authorize(ServerRequestInterface $psrRequest, }); $scopes = $this->parseScopes($authRequest); + $user = $request->user(); + $client = $clients->find($authRequest->getClient()->getIdentifier()); - $token = $tokens->findValidToken( - $user = $request->user(), - $client = $clients->find($authRequest->getClient()->getIdentifier()) - ); - - if (($token && $token->scopes === collect($scopes)->pluck('id')->all()) || - $client->skipsAuthorization()) { + if ($request->get('prompt') !== 'consent' && + ($client->skipsAuthorization() || $this->hasValidToken($tokens, $user, $client, $scopes))) { return $this->approveRequest($authRequest, $user); } @@ -101,6 +98,22 @@ protected function parseScopes($authRequest) ); } + /** + * Determine if a valid token exists for the given user, client, and scopes. + * + * @param \Laravel\Passport\TokenRepository $tokens + * @param \Illuminate\Database\Eloquent\Model $user + * @param \Laravel\Passport\Client $client + * @param array $scopes + * @return bool + */ + protected function hasValidToken($tokens, $user, $client, $scopes) + { + $token = $tokens->findValidToken($user, $client); + + return $token && $token->scopes === collect($scopes)->pluck('id')->all(); + } + /** * Approve the authorization request. * diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index a8672cf10..8631e06df 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -46,6 +46,7 @@ public function test_authorization_view_is_presented() $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); $request->shouldReceive('user')->andReturn($user = m::mock()); + $request->shouldReceive('get')->with('prompt')->andReturn(null); $authRequest->shouldReceive('getClient->getIdentifier')->andReturn(1); $authRequest->shouldReceive('getScopes')->andReturn([new Scope('scope-1')]); @@ -116,6 +117,7 @@ public function test_request_is_approved_if_valid_token_exists() $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); @@ -123,11 +125,13 @@ public function test_request_is_approved_if_valid_token_exists() $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); $clients = m::mock(ClientRepository::class); - $clients->shouldReceive('find')->with(1)->andReturn('client'); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + + $client->shouldReceive('skipsAuthorization')->andReturn(false); $tokens = m::mock(TokenRepository::class); $tokens->shouldReceive('findValidToken') - ->with($user, 'client') + ->with($user, $client) ->andReturn($token = m::mock(Token::class)); $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['scope-1']); @@ -158,6 +162,7 @@ public function test_request_is_approved_if_client_can_skip_authorization() $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); @@ -178,4 +183,48 @@ public function test_request_is_approved_if_client_can_skip_authorization() m::mock(ServerRequestInterface::class), $request, $clients, $tokens )->getContent()); } + + public function test_authorization_view_is_presented_if_request_has_prompt_equals_to_consent() + { + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(ResponseFactory::class); + + $controller = new AuthorizationController($server, $response); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->withSomeOfArgs('authToken'); + $session->shouldReceive('put')->with('authRequest', $authRequest); + $request->shouldReceive('user')->andReturn($user = m::mock()); + $request->shouldReceive('get')->with('prompt')->andReturn('consent'); + + $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); + $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); + + $clients = m::mock(ClientRepository::class); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + $client->shouldReceive('skipsAuthorization')->andReturn(false); + + $tokens = m::mock(TokenRepository::class); + $tokens->shouldNotReceive('findValidToken'); + + $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { + $this->assertSame('passport::authorize', $view); + $this->assertEquals($client, $data['client']); + $this->assertEquals($user, $data['user']); + $this->assertSame('description', $data['scopes'][0]->description); + + return 'view'; + }); + + $this->assertSame('view', $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + )); + } } From 89cc1976a25e2fa53ba8a3773e101189149852fa Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Mon, 5 Sep 2022 14:35:34 +0000 Subject: [PATCH 276/353] Support disabling prompt when redirecting for authorization (#1569) --- .../Controllers/AuthorizationController.php | 24 +++++++++++ tests/Unit/AuthorizationControllerTest.php | 43 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 5eb2d5db8..09e561bc0 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -71,6 +71,10 @@ public function authorize(ServerRequestInterface $psrRequest, return $this->approveRequest($authRequest, $user); } + if ($request->get('prompt') === 'none') { + return $this->denyRequest($authRequest, $user); + } + $request->session()->put('authToken', $authToken = Str::random()); $request->session()->put('authRequest', $authRequest); @@ -133,4 +137,24 @@ protected function approveRequest($authRequest, $user) ); }); } + + /** + * Deny the authorization request. + * + * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest + * @param \Illuminate\Database\Eloquent\Model $user + * @return \Illuminate\Http\Response + */ + protected function denyRequest($authRequest, $user) + { + $authRequest->setUser(new User($user->getAuthIdentifier())); + + $authRequest->setAuthorizationApproved(false); + + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); + } } diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index 8631e06df..f91483431 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -227,4 +227,47 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal m::mock(ServerRequestInterface::class), $request, $clients, $tokens )); } + + public function test_authorization_denied_if_request_has_prompt_equals_to_none() + { + $this->expectException('Laravel\Passport\Exceptions\OAuthServerException'); + + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(ResponseFactory::class); + + $controller = new AuthorizationController($server, $response); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + $server->shouldReceive('completeAuthorizationRequest') + ->with($authRequest, m::type(ResponseInterface::class)) + ->once() + ->andThrow('League\OAuth2\Server\Exception\OAuthServerException'); + + $request = m::mock(Request::class); + $request->shouldReceive('user')->andReturn($user = m::mock()); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); + $request->shouldReceive('get')->with('prompt')->andReturn('none'); + + $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); + $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); + $authRequest->shouldReceive('setUser')->once()->andReturnNull(); + $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(false); + + $clients = m::mock(ClientRepository::class); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + $client->shouldReceive('skipsAuthorization')->andReturn(false); + + $tokens = m::mock(TokenRepository::class); + $tokens->shouldReceive('findValidToken') + ->with($user, $client) + ->andReturnNull(); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + ); + } } From 721df114d5a036d8fb3f542b83ab2879ecea7d69 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 6 Sep 2022 16:00:05 +0000 Subject: [PATCH 277/353] Update CHANGELOG --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2f07ebc9..74086e1bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.0.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.1.0...11.x) + +## [v11.1.0](https://github.com/laravel/passport/compare/v11.0.1...v11.1.0) - 2022-09-05 + +### Added + +- Support prompting re-consent when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1567 +- Support disabling prompt when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1569 ## [v11.0.1](https://github.com/laravel/passport/compare/v11.0.0...v11.0.1) - 2022-08-29 From fb2a4029c6cf4df1ce0cf79ddbb874508f7a73e9 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Wed, 7 Sep 2022 13:14:45 +0000 Subject: [PATCH 278/353] Let OAuth2 server handle denying the request (#1572) --- .../ApproveAuthorizationController.php | 12 +- .../DenyAuthorizationController.php | 34 ++--- .../RetrievesAuthRequestFromSession.php | 2 - .../Unit/DenyAuthorizationControllerTest.php | 131 +++--------------- 4 files changed, 41 insertions(+), 138 deletions(-) diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index 90023d5e2..6a2d41511 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -8,7 +8,7 @@ class ApproveAuthorizationController { - use ConvertsPsrResponses, RetrievesAuthRequestFromSession; + use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; /** * The authorization server. @@ -40,8 +40,12 @@ public function approve(Request $request) $authRequest = $this->getAuthRequestFromSession($request); - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); + $authRequest->setAuthorizationApproved(true); + + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); } } diff --git a/src/Http/Controllers/DenyAuthorizationController.php b/src/Http/Controllers/DenyAuthorizationController.php index 613dfd465..3a46e6174 100644 --- a/src/Http/Controllers/DenyAuthorizationController.php +++ b/src/Http/Controllers/DenyAuthorizationController.php @@ -2,30 +2,30 @@ namespace Laravel\Passport\Http\Controllers; -use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; -use Illuminate\Support\Arr; +use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response as Psr7Response; class DenyAuthorizationController { - use RetrievesAuthRequestFromSession; + use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; /** - * The response factory implementation. + * The authorization server. * - * @var \Illuminate\Contracts\Routing\ResponseFactory + * @var \League\OAuth2\Server\AuthorizationServer */ - protected $response; + protected $server; /** * Create a new controller instance. * - * @param \Illuminate\Contracts\Routing\ResponseFactory $response + * @param \League\OAuth2\Server\AuthorizationServer $server * @return void */ - public function __construct(ResponseFactory $response) + public function __construct(AuthorizationServer $server) { - $this->response = $response; + $this->server = $server; } /** @@ -40,16 +40,12 @@ public function deny(Request $request) $authRequest = $this->getAuthRequestFromSession($request); - $clientUris = Arr::wrap($authRequest->getClient()->getRedirectUri()); + $authRequest->setAuthorizationApproved(false); - if (! in_array($uri = $authRequest->getRedirectUri(), $clientUris)) { - $uri = Arr::first($clientUris); - } - - $separator = $authRequest->getGrantTypeId() === 'implicit' ? '#' : (strstr($uri, '?') ? '&' : '?'); - - return $this->response->redirectTo( - $uri.$separator.'error=access_denied&state='.$request->input('state') - ); + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); } } diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index b1296277c..0a23e1ec4 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -42,8 +42,6 @@ protected function getAuthRequestFromSession(Request $request) } $authRequest->setUser(new User($request->user()->getAuthIdentifier())); - - $authRequest->setAuthorizationApproved(true); }); } } diff --git a/tests/Unit/DenyAuthorizationControllerTest.php b/tests/Unit/DenyAuthorizationControllerTest.php index cfb5e01cc..366cc8636 100644 --- a/tests/Unit/DenyAuthorizationControllerTest.php +++ b/tests/Unit/DenyAuthorizationControllerTest.php @@ -2,12 +2,13 @@ namespace Laravel\Passport\Tests\Unit; -use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Laravel\Passport\Http\Controllers\DenyAuthorizationController; +use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use Mockery as m; use PHPUnit\Framework\TestCase; +use Psr\Http\Message\ResponseInterface; class DenyAuthorizationControllerTest extends TestCase { @@ -18,130 +19,34 @@ protected function tearDown(): void public function test_authorization_can_be_denied() { - $response = m::mock(ResponseFactory::class); + $this->expectException('Laravel\Passport\Exceptions\OAuthServerException'); - $controller = new DenyAuthorizationController($response); + $server = m::mock(AuthorizationServer::class); + $controller = new DenyAuthorizationController($server); $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( + $session->shouldReceive('get') + ->once() + ->with('authRequest') + ->andReturn($authRequest = m::mock( AuthorizationRequest::class - )); + )); $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(false); - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); + $server->shouldReceive('completeAuthorizationRequest') + ->with($authRequest, m::type(ResponseInterface::class)) + ->andThrow('League\OAuth2\Server\Exception\OAuthServerException'); - $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_with_multiple_redirect_uris() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn(['http://localhost.localdomain', 'http://localhost']); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_implicit() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('implicit'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); - - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost#error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_with_existing_query_string() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost?action=some_action'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost?action=some_action'); - - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost?action=some_action&error=access_denied&state=state', $controller->deny($request)); + $controller->deny($request); } public function test_auth_request_should_exist() @@ -149,9 +54,9 @@ public function test_auth_request_should_exist() $this->expectException('Exception'); $this->expectExceptionMessage('Authorization request was not present in the session.'); - $response = m::mock(ResponseFactory::class); + $server = m::mock(AuthorizationServer::class); - $controller = new DenyAuthorizationController($response); + $controller = new DenyAuthorizationController($server); $request = m::mock(Request::class); @@ -164,7 +69,7 @@ public function test_auth_request_should_exist() $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturnNull(); - $response->shouldReceive('redirectTo')->never(); + $server->shouldReceive('completeAuthorizationRequest')->never(); $controller->deny($request); } From 7a514ccb1ef3e83be285ad0a0a83b03d701f8c3f Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 13 Sep 2022 15:06:14 +0000 Subject: [PATCH 279/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74086e1bd..134492a21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.1.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.2.0...11.x) + +## [v11.2.0](https://github.com/laravel/passport/compare/v11.1.0...v11.2.0) - 2022-09-07 + +### Changed + +- Let OAuth2 server handle the denying response by @hafezdivandari in https://github.com/laravel/passport/pull/1572 ## [v11.1.0](https://github.com/laravel/passport/compare/v11.0.1...v11.1.0) - 2022-09-05 From 5a26d6cbf56544c9f56994c6978f8fbe4d82bb33 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Thu, 29 Sep 2022 17:52:25 +0200 Subject: [PATCH 280/353] Improve token guard return type (#1579) --- src/Guards/TokenGuard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 7d3751f5f..7e478ce2e 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -144,7 +144,7 @@ public function validate(array $credentials = []) /** * Get the client for the incoming request. * - * @return mixed + * @return \Laravel\Passport\Client|null */ public function client() { From 3a4d6e524cc2fe0c45d56c728aa1973a7a3d5d69 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 4 Oct 2022 14:11:06 +0000 Subject: [PATCH 281/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 134492a21..8042749e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.2.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.2.1...11.x) + +## [v11.2.1](https://github.com/laravel/passport/compare/v11.2.0...v11.2.1) - 2022-09-29 + +### Fixed + +- Improve token guard return type by @axlon in https://github.com/laravel/passport/pull/1579 ## [v11.2.0](https://github.com/laravel/passport/compare/v11.1.0...v11.2.0) - 2022-09-07 From 741595738b80f64ec35ad82de477adee925fff7e Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Wed, 5 Oct 2022 18:57:02 +0330 Subject: [PATCH 282/353] [11.x] Support prompting login when redirecting for authorization (#1577) * Support prompting login when redirecting for authorization * use fragment on redirect uri for implicit grant * bind StatefulGuard * formatting Co-authored-by: Taylor Otwell --- routes/web.php | 11 +- .../Controllers/AuthorizationController.php | 66 ++++++++- src/PassportServiceProvider.php | 6 + tests/Unit/AuthorizationControllerTest.php | 135 +++++++++++++++++- 4 files changed, 204 insertions(+), 14 deletions(-) diff --git a/routes/web.php b/routes/web.php index dfe69dc9e..c9d78fb1e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -8,17 +8,18 @@ 'middleware' => 'throttle', ]); +Route::get('/authorize', [ + 'uses' => 'AuthorizationController@authorize', + 'as' => 'authorizations.authorize', + 'middleware' => 'web', +]); + Route::middleware(['web', 'auth'])->group(function () { Route::post('/token/refresh', [ 'uses' => 'TransientTokenController@refresh', 'as' => 'token.refresh', ]); - Route::get('/authorize', [ - 'uses' => 'AuthorizationController@authorize', - 'as' => 'authorizations.authorize', - ]); - Route::post('/authorize', [ 'uses' => 'ApproveAuthorizationController@approve', 'as' => 'authorizations.approve', diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 09e561bc0..597a5c103 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -2,6 +2,8 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Illuminate\Support\Str; @@ -10,6 +12,7 @@ use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\AuthorizationServer; +use League\OAuth2\Server\Exception\OAuthServerException; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; @@ -31,17 +34,28 @@ class AuthorizationController */ protected $response; + /** + * The guard implementation. + * + * @var \Illuminate\Contracts\Auth\StatefulGuard + */ + protected $guard; + /** * Create a new controller instance. * * @param \League\OAuth2\Server\AuthorizationServer $server * @param \Illuminate\Contracts\Routing\ResponseFactory $response + * @param \Illuminate\Contracts\Auth\StatefulGuard $guard * @return void */ - public function __construct(AuthorizationServer $server, ResponseFactory $response) + public function __construct(AuthorizationServer $server, + ResponseFactory $response, + StatefulGuard $guard) { $this->server = $server; $this->response = $response; + $this->guard = $guard; } /** @@ -62,6 +76,23 @@ public function authorize(ServerRequestInterface $psrRequest, return $this->server->validateAuthorizationRequest($psrRequest); }); + if ($this->guard->guest()) { + return $request->get('prompt') === 'none' + ? $this->denyRequest($authRequest) + : $this->promptForLogin($request); + } + + if ($request->get('prompt') === 'login' && + ! $request->session()->get('promptedForLogin', false)) { + $this->guard->logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + return $this->promptForLogin($request); + } + + $request->session()->forget('promptedForLogin'); + $scopes = $this->parseScopes($authRequest); $user = $request->user(); $client = $clients->find($authRequest->getClient()->getIdentifier()); @@ -142,11 +173,26 @@ protected function approveRequest($authRequest, $user) * Deny the authorization request. * * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \Illuminate\Database\Eloquent\Model $user + * @param \Illuminate\Database\Eloquent\Model|null $user * @return \Illuminate\Http\Response */ - protected function denyRequest($authRequest, $user) + protected function denyRequest($authRequest, $user = null) { + if (is_null($user)) { + $uri = $authRequest->getRedirectUri() + ?? (is_array($authRequest->getClient()->getRedirectUri()) + ? $authRequest->getClient()->getRedirectUri()[0] + : $authRequest->getClient()->getRedirectUri()); + + $separator = $authRequest->getGrantTypeId() === 'implicit' ? '#' : '?'; + + $uri = $uri.(str_contains($uri, $separator) ? '&' : $separator).'state='.$authRequest->getState(); + + return $this->withErrorHandling(function () use ($uri) { + throw OAuthServerException::accessDenied('Unauthenticated', $uri); + }); + } + $authRequest->setUser(new User($user->getAuthIdentifier())); $authRequest->setAuthorizationApproved(false); @@ -157,4 +203,18 @@ protected function denyRequest($authRequest, $user) ); }); } + + /** + * Prompt the user to login by throwing an AuthenticationException. + * + * @param \Illuminate\Http\Request $request + * + * @throws \Illuminate\Auth\AuthenticationException + */ + protected function promptForLogin($request) + { + $request->session()->put('promptedForLogin', true); + + throw new AuthenticationException; + } } diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 236e7d874..efe1361eb 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -5,6 +5,7 @@ use DateInterval; use Illuminate\Auth\Events\Logout; use Illuminate\Config\Repository as Config; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\Event; @@ -14,6 +15,7 @@ use Laravel\Passport\Bridge\PersonalAccessGrant; use Laravel\Passport\Bridge\RefreshTokenRepository; use Laravel\Passport\Guards\TokenGuard; +use Laravel\Passport\Http\Controllers\AuthorizationController; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Parser; use League\OAuth2\Server\AuthorizationServer; @@ -134,6 +136,10 @@ public function register() Passport::setClientUuids($this->app->make(Config::class)->get('passport.client_uuids', false)); + $this->app->when(AuthorizationController::class) + ->needs(StatefulGuard::class) + ->give(fn () => Auth::guard(config('passport.guard', null))); + $this->registerAuthorizationServer(); $this->registerClientRepository(); $this->registerJWTParser(); diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index f91483431..f9d0d825e 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Laravel\Passport\Bridge\Scope; @@ -36,15 +37,18 @@ public function test_authorization_view_is_presented() $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $response, $guard); + $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->andReturn($authRequest = m::mock()); $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $request->shouldReceive('user')->andReturn($user = m::mock()); $request->shouldReceive('get')->with('prompt')->andReturn(null); @@ -77,9 +81,11 @@ public function test_authorization_exceptions_are_handled() { $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $response, $guard); + $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->andThrow(LeagueException::invalidCredentials()); $request = m::mock(Request::class); @@ -103,8 +109,11 @@ public function test_request_is_approved_if_valid_token_exists() $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(false); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -114,6 +123,8 @@ public function test_request_is_approved_if_valid_token_exists() ->andReturn($psrResponse); $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); @@ -148,8 +159,11 @@ public function test_request_is_approved_if_client_can_skip_authorization() $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(false); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -159,6 +173,8 @@ public function test_request_is_approved_if_client_can_skip_authorization() ->andReturn($psrResponse); $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); @@ -192,8 +208,11 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); @@ -201,6 +220,7 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $request->shouldReceive('user')->andReturn($user = m::mock()); $request->shouldReceive('get')->with('prompt')->andReturn('consent'); @@ -238,8 +258,11 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $response, $guard); - $controller = new AuthorizationController($server, $response); + $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); $server->shouldReceive('completeAuthorizationRequest') @@ -248,6 +271,8 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() ->andThrow('League\OAuth2\Server\Exception\OAuthServerException'); $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldReceive('get')->with('prompt')->andReturn('none'); @@ -270,4 +295,102 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() m::mock(ServerRequestInterface::class), $request, $clients, $tokens ); } + + public function test_authorization_denied_if_unauthenticated_and_request_has_prompt_equals_to_none() + { + $server = m::mock(AuthorizationServer::class); + $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(true); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + $server->shouldNotReceive('completeAuthorizationRequest'); + + $request = m::mock(Request::class); + $request->shouldNotReceive('user'); + $request->shouldReceive('get')->with('prompt')->andReturn('none'); + + $authRequest->shouldNotReceive('setUser'); + $authRequest->shouldReceive('setAuthorizationApproved')->with(false); + $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('getState')->andReturn('state'); + $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + + try { + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + ); + } catch (\Laravel\Passport\Exceptions\OAuthServerException $e) { + $this->assertStringStartsWith( + 'http://localhost?state=state&error=access_denied&error_description=', + $e->render($request)->headers->get('location') + ); + } + } + + public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_login() + { + $this->expectException('Illuminate\Auth\AuthenticationException'); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(false); + $server->shouldReceive('validateAuthorizationRequest')->once(); + $guard->shouldReceive('logout')->once(); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('invalidate')->once(); + $session->shouldReceive('regenerateToken')->once(); + $session->shouldReceive('get')->with('promptedForLogin', false)->once()->andReturn(false); + $session->shouldReceive('put')->with('promptedForLogin', true)->once(); + $session->shouldNotReceive('forget')->with('promptedForLogin'); + $request->shouldReceive('get')->with('prompt')->andReturn('login'); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + ); + } + + public function test_user_should_be_authenticated() + { + $this->expectException('Illuminate\Auth\AuthenticationException'); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(ResponseFactory::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $response, $guard); + + $guard->shouldReceive('guest')->andReturn(true); + $server->shouldReceive('validateAuthorizationRequest')->once(); + + $request = m::mock(Request::class); + $request->shouldNotReceive('user'); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->with('promptedForLogin', true)->once(); + $session->shouldNotReceive('forget')->with('promptedForLogin'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + ); + } } From 22281ff77c33ec6f474b5a2ada166e33543629cd Mon Sep 17 00:00:00 2001 From: TosID Date: Mon, 17 Oct 2022 16:15:54 +0200 Subject: [PATCH 283/353] Update PurgeCommand.php (#1586) I get a lot confused when I use this command it always return seven days :) now return hours instead of days. --- src/Console/PurgeCommand.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index e42a6ad0d..26a35916b 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -40,7 +40,9 @@ public function handle() Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); - $this->info('Purged revoked items and items expired for more than seven days.'); + $this->option('hours') + ? $this->info('Purged revoked items and items expired for more than '.$this->option('hours').' hours.') + : $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); @@ -52,7 +54,9 @@ public function handle() Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); - $this->info('Purged items expired for more than seven days.'); + $this->option('hours') + ? $this->info('Purged items expired for more than '.$this->option('hours').' hours.') + : $this->info('Purged items expired for more than seven days.'); } } } From c73285f05de3fb808091da47769ccb53f69e4fb1 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 17 Oct 2022 14:16:15 +0000 Subject: [PATCH 284/353] Apply fixes from StyleCI --- src/Console/PurgeCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 26a35916b..9d9e66bcf 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -41,8 +41,8 @@ public function handle() Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); $this->option('hours') - ? $this->info('Purged revoked items and items expired for more than '.$this->option('hours').' hours.') - : $this->info('Purged revoked items and items expired for more than seven days.'); + ? $this->info('Purged revoked items and items expired for more than '.$this->option('hours').' hours.') + : $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); @@ -55,8 +55,8 @@ public function handle() Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); $this->option('hours') - ? $this->info('Purged items expired for more than '.$this->option('hours').' hours.') - : $this->info('Purged items expired for more than seven days.'); + ? $this->info('Purged items expired for more than '.$this->option('hours').' hours.') + : $this->info('Purged items expired for more than seven days.'); } } } From 3bc63674619d2edf14440267149137b51ab54f87 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Tue, 18 Oct 2022 18:07:57 +0200 Subject: [PATCH 285/353] Fix ClientRepository doc blocks (#1587) --- src/ClientRepository.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 6a6af3902..aaef295d7 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -37,7 +37,7 @@ public function __construct($personalAccessClientId = null, $personalAccessClien /** * Get a client by the given ID. * - * @param int $id + * @param int|string $id * @return \Laravel\Passport\Client|null */ public function find($id) @@ -50,7 +50,7 @@ public function find($id) /** * Get an active client by the given ID. * - * @param int $id + * @param int|string $id * @return \Laravel\Passport\Client|null */ public function findActive($id) @@ -63,7 +63,7 @@ public function findActive($id) /** * Get a client instance for the given ID and user ID. * - * @param int $clientId + * @param int|string $clientId * @param mixed $userId * @return \Laravel\Passport\Client|null */ @@ -221,7 +221,7 @@ public function regenerateSecret(Client $client) /** * Determine if the given client is revoked. * - * @param int $id + * @param int|string $id * @return bool */ public function revoked($id) From 4c2105887c724fe05fc4cd9b7d6c8d8df30e1bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Nabia=C5=82ek?= Date: Sat, 22 Oct 2022 18:38:00 +0200 Subject: [PATCH 286/353] Update docblock (#1588) --- src/ClientRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index aaef295d7..aebe33b11 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -128,7 +128,7 @@ public function personalAccessClient() /** * Store a new client. * - * @param int $userId + * @param int|null $userId * @param string $name * @param string $redirect * @param string|null $provider From 620fc16d16ccd70b3c10d1395e1dd856c09a0ddd Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 25 Oct 2022 16:38:35 +0000 Subject: [PATCH 287/353] Update CHANGELOG --- CHANGELOG.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8042749e7..9deec5ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.2.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.3.0...11.x) + +## [v11.3.0](https://github.com/laravel/passport/compare/v11.2.1...v11.3.0) - 2022-10-22 + +### Added + +- Support prompting login when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1577 + +### Changed + +- Update PurgeCommand.php by @fatoskurtishi in https://github.com/laravel/passport/pull/1586 +- Fix ClientRepository doc blocks by @axlon in https://github.com/laravel/passport/pull/1587 +- Update docblock by @mnabialek in https://github.com/laravel/passport/pull/1588 ## [v11.2.1](https://github.com/laravel/passport/compare/v11.2.0...v11.2.1) - 2022-09-29 From 298ea64aa42c14a35146b1d902df95655a0cb35e Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 2 Nov 2022 11:01:22 +0100 Subject: [PATCH 288/353] Test on PHP 8.2 (#1592) * Test on PHP 8.2 * Update composer.json --- .github/workflows/tests.yml | 5 ++++- composer.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d6cf7f407..fce193c8c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,6 +2,9 @@ name: tests on: push: + branches: + - master + - '*.x' pull_request: schedule: - cron: '0 0 * * *' @@ -13,7 +16,7 @@ jobs: strategy: fail-fast: true matrix: - php: ['8.0', 8.1] + php: ['8.0', 8.1, 8.2] laravel: [9] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} diff --git a/composer.json b/composer.json index 6762200af..bf44d9bd2 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require": { "php": "^8.0", "ext-json": "*", - "firebase/php-jwt": "^6.0", + "firebase/php-jwt": "^6.3.1", "illuminate/auth": "^9.0", "illuminate/console": "^9.0", "illuminate/container": "^9.0", From 662325a90b8c3184c548eaf66ce971925f2b90dc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 23 Nov 2022 10:06:21 +0100 Subject: [PATCH 289/353] Create issues.yml --- .github/workflows/issues.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/issues.yml diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 000000000..9634a0edb --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,12 @@ +name: issues + +on: + issues: + types: [labeled] + +permissions: + issues: write + +jobs: + help-wanted: + uses: laravel/.github/.github/workflows/issues.yml@main From 835febbfe875ba97306c026fdaa94f58f167363e Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Fri, 2 Dec 2022 21:50:16 +0330 Subject: [PATCH 290/353] Add auth guard to routes (#1603) --- config/passport.php | 13 +++++++++++++ routes/web.php | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/config/passport.php b/config/passport.php index 79c59acb1..06053cd12 100644 --- a/config/passport.php +++ b/config/passport.php @@ -2,6 +2,19 @@ return [ + /* + |-------------------------------------------------------------------------- + | Passport Guard + |-------------------------------------------------------------------------- + | + | Here you may specify which authentication guard Passport will use when + | authenticating users. This value should correspond with one of your + | guards that is already present in your "auth" configuration file. + | + */ + + 'guard' => 'web', + /* |-------------------------------------------------------------------------- | Encryption Keys diff --git a/routes/web.php b/routes/web.php index c9d78fb1e..fa2ecf3fe 100644 --- a/routes/web.php +++ b/routes/web.php @@ -14,7 +14,9 @@ 'middleware' => 'web', ]); -Route::middleware(['web', 'auth'])->group(function () { +$guard = config('passport.guard', null); + +Route::middleware(['web', $guard ? 'auth:'.$guard : 'auth'])->group(function () { Route::post('/token/refresh', [ 'uses' => 'TransientTokenController@refresh', 'as' => 'token.refresh', From 78c9d3a0f38fa28b9be9dbf0282cc766354e0e52 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 6 Dec 2022 16:25:16 +0000 Subject: [PATCH 291/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9deec5ce8..da644c483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.3.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.3.1...11.x) + +## [v11.3.1](https://github.com/laravel/passport/compare/v11.3.0...v11.3.1) - 2022-12-02 + +### Changed + +- Add auth guard to routes by @hafezdivandari in https://github.com/laravel/passport/pull/1603 ## [v11.3.0](https://github.com/laravel/passport/compare/v11.2.1...v11.3.0) - 2022-10-22 From 13329bee36a414323f5e545c5d5355c38cb6639c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 28 Dec 2022 13:30:41 +0100 Subject: [PATCH 292/353] Update tests.yml --- .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 fce193c8c..432efe7bd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ on: jobs: tests: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: true @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 From 2d746b752b08e47f6b5bd69d8e76fbe477e23532 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Tue, 3 Jan 2023 09:40:19 +0000 Subject: [PATCH 293/353] Adds types to migrations (#1594) --- .../2016_06_01_000001_create_oauth_auth_codes_table.php | 8 ++------ ...2016_06_01_000002_create_oauth_access_tokens_table.php | 8 ++------ ...016_06_01_000003_create_oauth_refresh_tokens_table.php | 8 ++------ .../2016_06_01_000004_create_oauth_clients_table.php | 8 ++------ ..._000005_create_oauth_personal_access_clients_table.php | 8 ++------ 5 files changed, 10 insertions(+), 30 deletions(-) diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 1826c0945..7b93b406a 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -8,10 +8,8 @@ { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); @@ -25,10 +23,8 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('oauth_auth_codes'); } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 045ca1b22..598798eef 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -8,10 +8,8 @@ { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); @@ -27,10 +25,8 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('oauth_access_tokens'); } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 3da3f7659..b007904ce 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -8,10 +8,8 @@ { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); @@ -23,10 +21,8 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('oauth_refresh_tokens'); } diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 8961c3a32..776ccfab2 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -8,10 +8,8 @@ { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('oauth_clients', function (Blueprint $table) { $table->bigIncrements('id'); @@ -29,10 +27,8 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('oauth_clients'); } diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index 8a99f467c..7c9d1e8f1 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -8,10 +8,8 @@ { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('oauth_personal_access_clients', function (Blueprint $table) { $table->bigIncrements('id'); @@ -22,10 +20,8 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('oauth_personal_access_clients'); } From e7df6ac5cf95ff476f5fb7965b27bd4d3c5d49b3 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 3 Jan 2023 17:29:04 +0000 Subject: [PATCH 294/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da644c483..1e37a1987 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.3.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.4.0...11.x) + +## [v11.4.0](https://github.com/laravel/passport/compare/v11.3.1...v11.4.0) - 2023-01-03 + +### Changed + +- Uses PHP Native Type Declarations 🐘 by @nunomaduro in https://github.com/laravel/passport/pull/1594 ## [v11.3.1](https://github.com/laravel/passport/compare/v11.3.0...v11.3.1) - 2022-12-02 From 3c17574d58f8a796fadee4d5cc946b89b4ec260f Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 9 Jan 2023 16:13:26 +0100 Subject: [PATCH 295/353] Update tests.yml --- .github/workflows/tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 432efe7bd..d61da8afa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,10 @@ jobs: fail-fast: true matrix: php: ['8.0', 8.1, 8.2] - laravel: [9] + laravel: [9, 10] + exclude: + - php: '8.0' + laravel: 10 name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} From 87dcab8ba37ba3a8c0d4958d251ab87a5c95b329 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 9 Jan 2023 17:46:42 +0100 Subject: [PATCH 296/353] Update composer.json (#1615) --- composer.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index bf44d9bd2..364339a7f 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,15 @@ "php": "^8.0", "ext-json": "*", "firebase/php-jwt": "^6.3.1", - "illuminate/auth": "^9.0", - "illuminate/console": "^9.0", - "illuminate/container": "^9.0", - "illuminate/contracts": "^9.0", - "illuminate/cookie": "^9.0", - "illuminate/database": "^9.0", - "illuminate/encryption": "^9.0", - "illuminate/http": "^9.0", - "illuminate/support": "^9.0", + "illuminate/auth": "^9.0|^10.0", + "illuminate/console": "^9.0|^10.0", + "illuminate/container": "^9.0|^10.0", + "illuminate/contracts": "^9.0|^10.0", + "illuminate/cookie": "^9.0|^10.0", + "illuminate/database": "^9.0|^10.0", + "illuminate/encryption": "^9.0|^10.0", + "illuminate/http": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", @@ -34,7 +34,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.0", + "orchestra/testbench": "^7.0|^8.0", "phpunit/phpunit": "^9.3" }, "autoload": { From e97f05d1ac1c8b7db0fd7202631d7c098da73f28 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 10 Jan 2023 19:54:34 +0000 Subject: [PATCH 297/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e37a1987..ff3b6d66b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.4.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.5.0...11.x) + +## [v11.5.0](https://github.com/laravel/passport/compare/v11.4.0...v11.5.0) - 2023-01-09 + +### Added + +- Laravel v10 Support by @driesvints in https://github.com/laravel/passport/pull/1615 ## [v11.4.0](https://github.com/laravel/passport/compare/v11.3.1...v11.4.0) - 2023-01-03 From b20282266211a0a19b0294d3459b5fd268807a6c Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Mon, 16 Jan 2023 18:22:08 +0330 Subject: [PATCH 298/353] Get authenticated user from the guard (#1617) --- src/Http/Controllers/AuthorizationController.php | 8 ++++---- src/TokenRepository.php | 4 ++-- tests/Unit/AuthorizationControllerTest.php | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 597a5c103..afaa9e2fd 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -94,7 +94,7 @@ public function authorize(ServerRequestInterface $psrRequest, $request->session()->forget('promptedForLogin'); $scopes = $this->parseScopes($authRequest); - $user = $request->user(); + $user = $this->guard->user(); $client = $clients->find($authRequest->getClient()->getIdentifier()); if ($request->get('prompt') !== 'consent' && @@ -137,7 +137,7 @@ protected function parseScopes($authRequest) * Determine if a valid token exists for the given user, client, and scopes. * * @param \Laravel\Passport\TokenRepository $tokens - * @param \Illuminate\Database\Eloquent\Model $user + * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param \Laravel\Passport\Client $client * @param array $scopes * @return bool @@ -153,7 +153,7 @@ protected function hasValidToken($tokens, $user, $client, $scopes) * Approve the authorization request. * * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \Illuminate\Database\Eloquent\Model $user + * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return \Illuminate\Http\Response */ protected function approveRequest($authRequest, $user) @@ -173,7 +173,7 @@ protected function approveRequest($authRequest, $user) * Deny the authorization request. * * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \Illuminate\Database\Eloquent\Model|null $user + * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @return \Illuminate\Http\Response */ protected function denyRequest($authRequest, $user = null) diff --git a/src/TokenRepository.php b/src/TokenRepository.php index 8f992b37c..b68f339b8 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -54,7 +54,7 @@ public function forUser($userId) /** * Get a valid token instance for the given user and client. * - * @param \Illuminate\Database\Eloquent\Model $user + * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param \Laravel\Passport\Client $client * @return \Laravel\Passport\Token|null */ @@ -107,7 +107,7 @@ public function isAccessTokenRevoked($id) /** * Find a valid token for the given user and client. * - * @param \Illuminate\Database\Eloquent\Model $user + * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param \Laravel\Passport\Client $client * @return \Laravel\Passport\Token|null */ diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index f9d0d825e..03f581913 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -42,6 +42,7 @@ public function test_authorization_view_is_presented() $controller = new AuthorizationController($server, $response, $guard); $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $server->shouldReceive('validateAuthorizationRequest')->andReturn($authRequest = m::mock()); $request = m::mock(Request::class); @@ -49,7 +50,6 @@ public function test_authorization_view_is_presented() $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); $session->shouldReceive('forget')->with('promptedForLogin')->once(); - $request->shouldReceive('user')->andReturn($user = m::mock()); $request->shouldReceive('get')->with('prompt')->andReturn(null); $authRequest->shouldReceive('getClient->getIdentifier')->andReturn(1); @@ -114,6 +114,7 @@ public function test_request_is_approved_if_valid_token_exists() $controller = new AuthorizationController($server, $response, $guard); $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -125,7 +126,6 @@ public function test_request_is_approved_if_valid_token_exists() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('forget')->with('promptedForLogin')->once(); - $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); $request->shouldReceive('get')->with('prompt')->andReturn(null); @@ -164,6 +164,7 @@ public function test_request_is_approved_if_client_can_skip_authorization() $controller = new AuthorizationController($server, $response, $guard); $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -175,7 +176,6 @@ public function test_request_is_approved_if_client_can_skip_authorization() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('forget')->with('promptedForLogin')->once(); - $request->shouldReceive('user')->once()->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); $request->shouldReceive('get')->with('prompt')->andReturn(null); @@ -213,6 +213,7 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $controller = new AuthorizationController($server, $response, $guard); $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $server->shouldReceive('validateAuthorizationRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); @@ -221,7 +222,6 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); $session->shouldReceive('forget')->with('promptedForLogin')->once(); - $request->shouldReceive('user')->andReturn($user = m::mock()); $request->shouldReceive('get')->with('prompt')->andReturn('consent'); $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); @@ -263,6 +263,7 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() $controller = new AuthorizationController($server, $response, $guard); $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $server->shouldReceive('validateAuthorizationRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); $server->shouldReceive('completeAuthorizationRequest') @@ -273,7 +274,6 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('forget')->with('promptedForLogin')->once(); - $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldReceive('get')->with('prompt')->andReturn('none'); From b0b0758eac20aeaa229204cbc7fa8fd6ee9f9e09 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 17 Jan 2023 16:29:11 +0000 Subject: [PATCH 299/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff3b6d66b..09354db4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.5.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.5.1...11.x) + +## [v11.5.1](https://github.com/laravel/passport/compare/v11.5.0...v11.5.1) - 2023-01-16 + +### Fixed + +- Get authenticated user from the guard by @hafezdivandari in https://github.com/laravel/passport/pull/1617 ## [v11.5.0](https://github.com/laravel/passport/compare/v11.4.0...v11.5.0) - 2023-01-09 From 3ac7b1e8f9814e47af5a9d5ab88c415060d5c782 Mon Sep 17 00:00:00 2001 From: "P. De Bleye" Date: Sun, 22 Jan 2023 18:37:04 +0100 Subject: [PATCH 300/353] Update ClientCommand.php's user_id description (#1619) * Update ClientCommand.php's user_id description We get a fair amount of confused passport users on the laravel discord wondering what this user_id is even for. It might help to indicate that the input is optional. * Update ClientCommand.php Co-authored-by: Taylor Otwell --- src/Console/ClientCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index f645cf613..15f2f9227 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -133,7 +133,7 @@ protected function createClientCredentialsClient(ClientRepository $clients) protected function createAuthCodeClient(ClientRepository $clients) { $userId = $this->option('user_id') ?: $this->ask( - 'Which user ID should the client be assigned to?' + 'Which user ID should the client be assigned to? (Optional)' ); $name = $this->option('name') ?: $this->ask( From b7bc60c9df4b7ba42bc193e36f392880865250ee Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:32:58 +0100 Subject: [PATCH 301/353] Fix doc block for `withAccessToken()` (#1620) --- src/HasApiTokens.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HasApiTokens.php b/src/HasApiTokens.php index 71853fed0..025c7f2e1 100644 --- a/src/HasApiTokens.php +++ b/src/HasApiTokens.php @@ -71,7 +71,7 @@ public function createToken($name, array $scopes = []) /** * Set the current access token for the user. * - * @param \Laravel\Passport\Token $accessToken + * @param \Laravel\Passport\Token|\Laravel\Passport\TransientToken $accessToken * @return $this */ public function withAccessToken($accessToken) From 1d8204e40c63bb6cbb981907fdbeb5c69a4fbae9 Mon Sep 17 00:00:00 2001 From: "Lucas Moraes (Panik)" Date: Tue, 31 Jan 2023 10:41:55 -0300 Subject: [PATCH 302/353] [11.x] Get model PK instead of forcibly id column (#1626) * Get model PK instead of forcibly id column * Get model PK instead of forcibly id column in tests * Get model PK instead of forcibly id column in command * Get model PK instead of forcibly id column in repository * Get model PK instead of forcibly id column in Passport * stub extending from model * Fix namespace order * Get model PK instead of forcibly id column in blade --- resources/views/authorize.blade.php | 4 ++-- src/ClientRepository.php | 2 +- src/Console/ClientCommand.php | 2 +- src/Passport.php | 2 +- src/PersonalAccessTokenFactory.php | 2 +- tests/Feature/AccessTokenControllerTest.php | 24 +++++++++---------- tests/Unit/PersonalAccessTokenFactoryTest.php | 3 ++- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/resources/views/authorize.blade.php b/resources/views/authorize.blade.php index ecbdcaa58..d0a4a991c 100644 --- a/resources/views/authorize.blade.php +++ b/resources/views/authorize.blade.php @@ -68,7 +68,7 @@ @csrf - + @@ -79,7 +79,7 @@ @method('DELETE') - + diff --git a/src/ClientRepository.php b/src/ClientRepository.php index aebe33b11..402deb057 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -167,7 +167,7 @@ public function createPersonalAccessClient($userId, $name, $redirect) { return tap($this->create($userId, $name, $redirect, null, true), function ($client) { $accessClient = Passport::personalAccessClient(); - $accessClient->client_id = $client->id; + $accessClient->client_id = $client->getKey(); $accessClient->save(); }); } diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 15f2f9227..c46f63bc6 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -167,7 +167,7 @@ protected function outputClientDetails(Client $client) $this->line(''); } - $this->line('Client ID: '.$client->id); + $this->line('Client ID: '.$client->getKey()); $this->line('Client secret: '.$client->plainSecret); } } diff --git a/src/Passport.php b/src/Passport.php index 6e577ebea..eb85e0a81 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -370,7 +370,7 @@ public static function actingAsClient($client, $scopes = [], $guard = 'api') { $token = app(self::tokenModel()); - $token->client_id = $client->id; + $token->client_id = $client->getKey(); $token->setRelation('client', $client); $token->scopes = $scopes; diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 65817a7a1..15ac840ad 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -98,7 +98,7 @@ protected function createRequest($client, $userId, array $scopes) return (new ServerRequest('POST', 'not-important'))->withParsedBody([ 'grant_type' => 'personal_access', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $secret, 'user_id' => $userId, 'scope' => implode(' ', $scopes), diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 073f65d62..54cb4ffd9 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -50,13 +50,13 @@ public function testGettingAccessTokenWithClientCredentialsGrant() $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'client_credentials', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret, ] ); @@ -93,13 +93,13 @@ public function testGettingAccessTokenWithClientCredentialsGrantInvalidClientSec $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'client_credentials', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret.'foo', ] ); @@ -137,13 +137,13 @@ public function testGettingAccessTokenWithPasswordGrant() $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'password', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret, 'username' => $user->email, 'password' => $password, @@ -184,13 +184,13 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'password', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret, 'username' => $user->email, 'password' => $password.'foo', @@ -227,13 +227,13 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'password', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret.'foo', 'username' => $user->email, 'password' => $password, @@ -274,13 +274,13 @@ public function testGettingCustomResponseType() $user->save(); /** @var Client $client */ - $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->id]); + $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); $response = $this->post( '/oauth/token', [ 'grant_type' => 'client_credentials', - 'client_id' => $client->id, + 'client_id' => $client->getKey(), 'client_secret' => $client->secret, ] ); diff --git a/tests/Unit/PersonalAccessTokenFactoryTest.php b/tests/Unit/PersonalAccessTokenFactoryTest.php index f4731bd6b..33e576465 100644 --- a/tests/Unit/PersonalAccessTokenFactoryTest.php +++ b/tests/Unit/PersonalAccessTokenFactoryTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\PersonalAccessTokenFactory; use Laravel\Passport\PersonalAccessTokenResult; @@ -56,7 +57,7 @@ public function test_access_token_can_be_created() } } -class PersonalAccessTokenFactoryTestClientStub +class PersonalAccessTokenFactoryTestClientStub extends Client { public $id = 1; From 9ee5bd94abf0698f414dcfcb179b2b311a72c13e Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 31 Jan 2023 15:42:22 +0000 Subject: [PATCH 303/353] Update CHANGELOG --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09354db4f..a7e1056ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.5.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.6.0...11.x) + +## [v11.6.0](https://github.com/laravel/passport/compare/v11.5.1...v11.6.0) - 2023-01-31 + +### Changed + +- Update ClientCommand.php's user_id description by @Smoggert in https://github.com/laravel/passport/pull/1619 +- Get model PK instead of forcibly id column by @lucaspanik in https://github.com/laravel/passport/pull/1626 + +### Fixed + +- Fix doc block for `withAccessToken()` by @axlon in https://github.com/laravel/passport/pull/1620 ## [v11.5.1](https://github.com/laravel/passport/compare/v11.5.0...v11.5.1) - 2023-01-16 From d8cc34766635da552a9ddff80248c5505f19bd04 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:45:23 +0100 Subject: [PATCH 304/353] Indicate current token can be `TransientToken` (#1627) --- src/HasApiTokens.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HasApiTokens.php b/src/HasApiTokens.php index 025c7f2e1..f68bc1ee0 100644 --- a/src/HasApiTokens.php +++ b/src/HasApiTokens.php @@ -9,7 +9,7 @@ trait HasApiTokens /** * The current access token for the authentication user. * - * @var \Laravel\Passport\Token + * @var \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null */ protected $accessToken; @@ -36,7 +36,7 @@ public function tokens() /** * Get the current access token being used by the user. * - * @return \Laravel\Passport\Token|null + * @return \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null */ public function token() { From 31ed56954f044ffd6dcef237d5087955376693ff Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 7 Feb 2023 16:08:23 +0000 Subject: [PATCH 305/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7e1056ab..669cd76ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.6.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.6.1...11.x) + +## [v11.6.1](https://github.com/laravel/passport/compare/v11.6.0...v11.6.1) - 2023-02-03 + +### Changed + +- Indicate current token can be `TransientToken` by @axlon in https://github.com/laravel/passport/pull/1627 ## [v11.6.0](https://github.com/laravel/passport/compare/v11.5.1...v11.6.0) - 2023-01-31 From 5b57dbc9fc5e350d70b5c612fd53c65dd0bbebb2 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:24:40 +0100 Subject: [PATCH 306/353] Add support for `EncryptCookies` middleware (#1628) --- src/Guards/TokenGuard.php | 6 ++++- src/Passport.php | 31 ++++++++++++++++++++++++++ tests/Unit/TokenGuardTest.php | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 7e478ce2e..6798ca393 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -295,8 +295,12 @@ protected function getTokenViaCookie($request) */ protected function decodeJwtTokenCookie($request) { + $jwt = $request->cookie(Passport::cookie()); + return (array) JWT::decode( - CookieValuePrefix::remove($this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies)), + Passport::$decryptsCookies + ? CookieValuePrefix::remove($this->encrypter->decrypt($jwt, Passport::$unserializesCookies)) + : $jwt, new Key(Passport::tokenEncryptionKey($this->encrypter), 'HS256') ); } diff --git a/src/Passport.php b/src/Passport.php index eb85e0a81..3fddf8762 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -133,6 +133,13 @@ class Passport */ public static $unserializesCookies = false; + /** + * Indicates if Passport should decrypt cookies. + * + * @var bool + */ + public static $decryptsCookies = true; + /** * Indicates if client secrets will be hashed. * @@ -684,4 +691,28 @@ public static function withoutCookieSerialization() return new static; } + + /** + * Instruct Passport to enable cookie encryption. + * + * @return static + */ + public static function withCookieEncryption() + { + static::$decryptsCookies = true; + + return new static; + } + + /** + * Instruct Passport to disable cookie encryption. + * + * @return static + */ + public static function withoutCookieEncryption() + { + static::$decryptsCookies = false; + + return new static; + } } diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index c29cc1015..614393898 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -304,6 +304,48 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ Passport::encryptTokensUsing(null); } + public function test_users_may_be_retrieved_from_cookies_without_encryption() + { + Passport::withoutCookieEncryption(); + Passport::encryptTokensUsing(function (EncrypterContract $encrypter) { + return $encrypter->getKey().'.mykey'; + }); + + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = new Encrypter(str_repeat('a', 16)); + + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + + $request = Request::create('/'); + $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); + $request->cookies->set('laravel_token', + JWT::encode([ + 'sub' => 1, + 'aud' => 1, + 'csrf' => 'token', + 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), + ], Passport::tokenEncryptionKey($encrypter), 'HS256') + ); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); + + $user = $guard->user(); + + $this->assertEquals($expectedUser, $user); + + // Revert to the default encryption method + Passport::withCookieEncryption(); + Passport::encryptTokensUsing(null); + } + public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() { $resourceServer = m::mock(ResourceServer::class); From 174a12a8d80476c16bcae78b404395154721d815 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 14 Feb 2023 16:51:43 +0000 Subject: [PATCH 307/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 669cd76ce..b1f86d622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.6.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.7.0...11.x) + +## [v11.7.0](https://github.com/laravel/passport/compare/v11.6.1...v11.7.0) - 2023-02-08 + +### Added + +- Add support for `EncryptCookies` middleware by @axlon in https://github.com/laravel/passport/pull/1628 ## [v11.6.1](https://github.com/laravel/passport/compare/v11.6.0...v11.6.1) - 2023-02-03 From 08b1dabfdddbdf2472ef193609f75f475208ec90 Mon Sep 17 00:00:00 2001 From: Chris Page Date: Tue, 14 Feb 2023 21:08:49 +0000 Subject: [PATCH 308/353] Added AuthenticationException to extend the behaviour of Laravel's default exception handler (#1633) Co-authored-by: Chris Page --- src/Exceptions/AuthenticationException.php | 9 +++++++++ src/Http/Controllers/AuthorizationController.php | 4 ++-- src/Http/Middleware/CheckClientCredentials.php | 4 ++-- .../Middleware/CheckClientCredentialsForAnyScope.php | 4 ++-- src/Http/Middleware/CheckCredentials.php | 6 +++--- src/Http/Middleware/CheckForAnyScope.php | 4 ++-- src/Http/Middleware/CheckScopes.php | 4 ++-- tests/Unit/AuthorizationControllerTest.php | 5 +++-- tests/Unit/CheckClientCredentialsForAnyScopeTest.php | 3 ++- tests/Unit/CheckClientCredentialsTest.php | 3 ++- tests/Unit/CheckForAnyScopeTest.php | 5 +++-- tests/Unit/CheckScopesTest.php | 5 +++-- 12 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 src/Exceptions/AuthenticationException.php diff --git a/src/Exceptions/AuthenticationException.php b/src/Exceptions/AuthenticationException.php new file mode 100644 index 000000000..75ec03dbf --- /dev/null +++ b/src/Exceptions/AuthenticationException.php @@ -0,0 +1,9 @@ +expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); @@ -368,7 +369,7 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log public function test_user_should_be_authenticated() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); $response = m::mock(ResponseFactory::class); diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 754d9a7de..807bf93d4 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -85,7 +86,7 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 36e410dd5..0a30b19ea 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -84,7 +85,7 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index cf9e04c5b..e567feeb0 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckForAnyScope as CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -47,7 +48,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -60,7 +61,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index 3eb172b9b..21e8b40bf 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -46,7 +47,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -59,7 +60,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); From e305ff0488f3e125f3f22e1576d613dd1d95ac7e Mon Sep 17 00:00:00 2001 From: Jon Erickson Date: Thu, 16 Feb 2023 14:02:39 -0700 Subject: [PATCH 309/353] [11.x] Custom authorization view response (#1629) * Implements authorization view response contract that allows for being overridden with custom views * Updated namespace * Updated namespace * Moved individual arguments to an array of parameters and one argument * Removed authorize return type * Remove old return statement * Add IntelliJ IDE files to gitignore * Formatting * Update tests * Update rest of tests with new response class * Style fixes and make sure parameters pushed to authorization view are in an array. * Remove parameters from authorization view function * Update .gitignore * Update src/Contracts/AuthorizationViewResponse.php Co-authored-by: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> * Update src/Http/Responses/AuthorizationViewResponse.php Co-authored-by: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> * Updated doc block return types * formatting * remove extra line --------- Co-authored-by: Dries Vints Co-authored-by: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Co-authored-by: Taylor Otwell --- src/Contracts/AuthorizationViewResponse.php | 16 +++++ .../Controllers/AuthorizationController.php | 25 ++++--- .../Responses/AuthorizationViewResponse.php | 68 +++++++++++++++++++ src/Passport.php | 15 ++++ src/PassportServiceProvider.php | 2 + tests/Unit/AuthorizationControllerTest.php | 53 +++++++-------- 6 files changed, 139 insertions(+), 40 deletions(-) create mode 100644 src/Contracts/AuthorizationViewResponse.php create mode 100644 src/Http/Responses/AuthorizationViewResponse.php diff --git a/src/Contracts/AuthorizationViewResponse.php b/src/Contracts/AuthorizationViewResponse.php new file mode 100644 index 000000000..6594c6624 --- /dev/null +++ b/src/Contracts/AuthorizationViewResponse.php @@ -0,0 +1,16 @@ +server = $server; - $this->response = $response; $this->guard = $guard; + $this->response = $response; } /** @@ -65,7 +64,7 @@ public function __construct(AuthorizationServer $server, * @param \Illuminate\Http\Request $request * @param \Laravel\Passport\ClientRepository $clients * @param \Laravel\Passport\TokenRepository $tokens - * @return \Illuminate\Http\Response + * @return \Laravel\Passport\Contracts\AuthorizationViewResponse */ public function authorize(ServerRequestInterface $psrRequest, Request $request, @@ -109,7 +108,7 @@ public function authorize(ServerRequestInterface $psrRequest, $request->session()->put('authToken', $authToken = Str::random()); $request->session()->put('authRequest', $authRequest); - return $this->response->view('passport::authorize', [ + return $this->response->withParameters([ 'client' => $client, 'user' => $user, 'scopes' => $scopes, diff --git a/src/Http/Responses/AuthorizationViewResponse.php b/src/Http/Responses/AuthorizationViewResponse.php new file mode 100644 index 000000000..36761d486 --- /dev/null +++ b/src/Http/Responses/AuthorizationViewResponse.php @@ -0,0 +1,68 @@ +view = $view; + } + + /** + * Add parameters to response. + * + * @param array $parameters + * @return $this + */ + public function withParameters($parameters = []) + { + $this->parameters = $parameters; + + return $this; + } + + /** + * Create an HTTP response that represents the object. + * + * @param \Illuminate\Http\Request $request + * @return \Symfony\Component\HttpFoundation\Response + */ + public function toResponse($request) + { + if (! is_callable($this->view) || is_string($this->view)) { + return response()->view($this->view, $this->parameters); + } + + $response = call_user_func($this->view, $this->parameters); + + if ($response instanceof Responsable) { + return $response->toResponse($request); + } + + return $response; + } +} diff --git a/src/Passport.php b/src/Passport.php index 3fddf8762..706a7543a 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -6,6 +6,8 @@ use DateInterval; use DateTimeInterface; use Illuminate\Contracts\Encryption\Encrypter; +use Laravel\Passport\Contracts\AuthorizationViewResponse as AuthorizationViewResponseContract; +use Laravel\Passport\Http\Responses\AuthorizationViewResponse; use League\OAuth2\Server\ResourceServer; use Mockery; use Psr\Http\Message\ServerRequestInterface; @@ -644,6 +646,19 @@ public static function tokenEncryptionKey(Encrypter $encrypter) $encrypter->getKey(); } + /** + * Specify which view should be used as the authorization view. + * + * @param callable|string $view + * @return void + */ + public static function authorizationView($view) + { + app()->singleton(AuthorizationViewResponseContract::class, function ($app) use ($view) { + return new AuthorizationViewResponse($view); + }); + } + /** * Configure Passport to not register its routes. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index efe1361eb..64ed0b925 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -145,6 +145,8 @@ public function register() $this->registerJWTParser(); $this->registerResourceServer(); $this->registerGuard(); + + Passport::authorizationView('passport::authorize'); } /** diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index ec79a08b8..fe6e7f3ea 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -3,7 +3,6 @@ namespace Laravel\Passport\Tests\Unit; use Illuminate\Contracts\Auth\StatefulGuard; -use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Laravel\Passport\Bridge\Scope; use Laravel\Passport\Client; @@ -11,6 +10,7 @@ use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\OAuthServerException; use Laravel\Passport\Http\Controllers\AuthorizationController; +use Laravel\Passport\Http\Responses\AuthorizationViewResponse; use Laravel\Passport\Passport; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -37,10 +37,10 @@ public function test_authorization_view_is_presented() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); @@ -58,21 +58,20 @@ public function test_authorization_view_is_presented() $clients = m::mock(ClientRepository::class); $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); - $client->shouldReceive('skipsAuthorization')->andReturn(false); - $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { - $this->assertSame('passport::authorize', $view); + $tokens = m::mock(TokenRepository::class); + $tokens->shouldReceive('findValidToken')->with($user, $client)->andReturnNull(); + + $response->shouldReceive('withParameters')->once()->andReturnUsing(function ($data) use ($client, $user, $request) { $this->assertEquals($client, $data['client']); $this->assertEquals($user, $data['user']); + $this->assertEquals($request, $data['request']); $this->assertSame('description', $data['scopes'][0]->description); return 'view'; }); - $tokens = m::mock(TokenRepository::class); - $tokens->shouldReceive('findValidToken')->with($user, $client)->andReturnNull(); - $this->assertSame('view', $controller->authorize( m::mock(ServerRequestInterface::class), $request, $clients, $tokens )); @@ -81,10 +80,10 @@ public function test_authorization_view_is_presented() public function test_authorization_exceptions_are_handled() { $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->andThrow(LeagueException::invalidCredentials()); @@ -109,10 +108,10 @@ public function test_request_is_approved_if_valid_token_exists() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); @@ -159,10 +158,10 @@ public function test_request_is_approved_if_client_can_skip_authorization() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); @@ -208,10 +207,10 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); @@ -235,10 +234,10 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $tokens = m::mock(TokenRepository::class); $tokens->shouldNotReceive('findValidToken'); - $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { - $this->assertSame('passport::authorize', $view); + $response->shouldReceive('withParameters')->once()->andReturnUsing(function ($data) use ($client, $user, $request) { $this->assertEquals($client, $data['client']); $this->assertEquals($user, $data['user']); + $this->assertEquals($request, $data['request']); $this->assertSame('description', $data['scopes'][0]->description); return 'view'; @@ -258,10 +257,10 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); @@ -300,10 +299,10 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() public function test_authorization_denied_if_unauthenticated_and_request_has_prompt_equals_to_none() { $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(true); $server->shouldReceive('validateAuthorizationRequest') @@ -341,10 +340,10 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->once(); @@ -372,10 +371,10 @@ public function test_user_should_be_authenticated() $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response, $guard); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(true); $server->shouldReceive('validateAuthorizationRequest')->once(); From 2008d86244297a9fa291faf63f59d0949bddf91e Mon Sep 17 00:00:00 2001 From: "TONY.W" <33448724+TonyWong9527@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:08:51 +0800 Subject: [PATCH 310/353] laravel10 The Eloquent model's deprecated $dates property has been removed.application should now use the $casts property (#1636) Co-authored-by: tony --- src/Token.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Token.php b/src/Token.php index 6f5d7b94f..a84cbba20 100644 --- a/src/Token.php +++ b/src/Token.php @@ -42,15 +42,7 @@ class Token extends Model protected $casts = [ 'scopes' => 'array', 'revoked' => 'bool', - ]; - - /** - * The attributes that should be mutated to dates. - * - * @var array - */ - protected $dates = [ - 'expires_at', + 'expires_at' => 'datetime', ]; /** From ab51e2b013a020ac3f28e772ced15730baf77a45 Mon Sep 17 00:00:00 2001 From: driesvints Date: Fri, 17 Feb 2023 09:10:16 +0000 Subject: [PATCH 311/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1f86d622..94fe37c2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.7.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.0...11.x) + +## [v11.8.0](https://github.com/laravel/passport/compare/v11.7.0...v11.8.0) - 2023-02-17 + +- Move AuthenticationException into the scope of Laravel Passport by @chrispage1 in https://github.com/laravel/passport/pull/1633 +- Custom authorization view response by @JonErickson in https://github.com/laravel/passport/pull/1629 +- Fix deprecated $dates property by @TonyWong9527 in https://github.com/laravel/passport/pull/1636 ## [v11.7.0](https://github.com/laravel/passport/compare/v11.6.1...v11.7.0) - 2023-02-08 From db543b0cc13ed3f56f1bffda04707fbe2a8c7ab5 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 20 Feb 2023 10:20:04 +0100 Subject: [PATCH 312/353] Revert "Added AuthenticationException to extend the behaviour of Laravel's default exception handler (#1633)" This reverts commit 08b1dabfdddbdf2472ef193609f75f475208ec90. --- src/Exceptions/AuthenticationException.php | 9 --------- src/Http/Controllers/AuthorizationController.php | 4 ++-- src/Http/Middleware/CheckClientCredentials.php | 4 ++-- .../Middleware/CheckClientCredentialsForAnyScope.php | 4 ++-- src/Http/Middleware/CheckCredentials.php | 6 +++--- src/Http/Middleware/CheckForAnyScope.php | 4 ++-- src/Http/Middleware/CheckScopes.php | 4 ++-- tests/Unit/AuthorizationControllerTest.php | 5 ++--- tests/Unit/CheckClientCredentialsForAnyScopeTest.php | 3 +-- tests/Unit/CheckClientCredentialsTest.php | 3 +-- tests/Unit/CheckForAnyScopeTest.php | 5 ++--- tests/Unit/CheckScopesTest.php | 5 ++--- 12 files changed, 21 insertions(+), 35 deletions(-) delete mode 100644 src/Exceptions/AuthenticationException.php diff --git a/src/Exceptions/AuthenticationException.php b/src/Exceptions/AuthenticationException.php deleted file mode 100644 index 75ec03dbf..000000000 --- a/src/Exceptions/AuthenticationException.php +++ /dev/null @@ -1,9 +0,0 @@ -expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $server = m::mock(AuthorizationServer::class); $response = m::mock(AuthorizationViewResponse::class); @@ -368,7 +367,7 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log public function test_user_should_be_authenticated() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $server = m::mock(AuthorizationServer::class); $response = m::mock(AuthorizationViewResponse::class); diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 807bf93d4..754d9a7de 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -4,7 +4,6 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -86,7 +85,7 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 0a30b19ea..36e410dd5 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -4,7 +4,6 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; -use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -85,7 +84,7 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index e567feeb0..cf9e04c5b 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests\Unit; -use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckForAnyScope as CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -48,7 +47,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $middleware = new CheckScopes; $request = m::mock(); @@ -61,7 +60,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $middleware = new CheckScopes; $request = m::mock(); diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index 21e8b40bf..3eb172b9b 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -2,7 +2,6 @@ namespace Laravel\Passport\Tests\Unit; -use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -47,7 +46,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $middleware = new CheckScopes; $request = m::mock(); @@ -60,7 +59,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException(AuthenticationException::class); + $this->expectException('Illuminate\Auth\AuthenticationException'); $middleware = new CheckScopes; $request = m::mock(); From f3d03156046951fcb54868265a795ef92abca200 Mon Sep 17 00:00:00 2001 From: driesvints Date: Mon, 20 Feb 2023 09:23:45 +0000 Subject: [PATCH 313/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94fe37c2a..4c75eaa36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.1...11.x) + +## [v11.8.1](https://github.com/laravel/passport/compare/v11.8.0...v11.8.1) - 2023-02-20 + +- Revert "Move AuthenticationException into the scope of Laravel Passport" by @driesvints in https://github.com/laravel/passport/commit/db543b0cc13ed3f56f1bffda04707fbe2a8c7ab5 ## [v11.8.0](https://github.com/laravel/passport/compare/v11.7.0...v11.8.0) - 2023-02-17 From 67c3e336af163f6eba5dbca8e5db46275ff0e433 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 20 Feb 2023 14:43:07 +0100 Subject: [PATCH 314/353] Revert "Revert "Added AuthenticationException to extend the behaviour of Laravel's default exception handler (#1633)"" This reverts commit db543b0cc13ed3f56f1bffda04707fbe2a8c7ab5. --- src/Exceptions/AuthenticationException.php | 9 +++++++++ src/Http/Controllers/AuthorizationController.php | 4 ++-- src/Http/Middleware/CheckClientCredentials.php | 4 ++-- .../Middleware/CheckClientCredentialsForAnyScope.php | 4 ++-- src/Http/Middleware/CheckCredentials.php | 6 +++--- src/Http/Middleware/CheckForAnyScope.php | 4 ++-- src/Http/Middleware/CheckScopes.php | 4 ++-- tests/Unit/AuthorizationControllerTest.php | 5 +++-- tests/Unit/CheckClientCredentialsForAnyScopeTest.php | 3 ++- tests/Unit/CheckClientCredentialsTest.php | 3 ++- tests/Unit/CheckForAnyScopeTest.php | 5 +++-- tests/Unit/CheckScopesTest.php | 5 +++-- 12 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 src/Exceptions/AuthenticationException.php diff --git a/src/Exceptions/AuthenticationException.php b/src/Exceptions/AuthenticationException.php new file mode 100644 index 000000000..75ec03dbf --- /dev/null +++ b/src/Exceptions/AuthenticationException.php @@ -0,0 +1,9 @@ +expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); $response = m::mock(AuthorizationViewResponse::class); @@ -367,7 +368,7 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log public function test_user_should_be_authenticated() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $server = m::mock(AuthorizationServer::class); $response = m::mock(AuthorizationViewResponse::class); diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 754d9a7de..807bf93d4 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -85,7 +86,7 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 36e410dd5..0a30b19ea 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -84,7 +85,7 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index cf9e04c5b..e567feeb0 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckForAnyScope as CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -47,7 +48,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -60,7 +61,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index 3eb172b9b..21e8b40bf 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -46,7 +47,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -59,7 +60,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); From d95c09566541e5a7fb731f7f8ca00fa0619f5f7e Mon Sep 17 00:00:00 2001 From: driesvints Date: Mon, 20 Feb 2023 13:44:26 +0000 Subject: [PATCH 315/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c75eaa36..f618e323d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.2...11.x) + +## [v11.8.2](https://github.com/laravel/passport/compare/v11.8.1...v11.8.2) - 2023-02-20 + +- Re-apply "Added AuthenticationException to extend the behaviour of Laravel's default exception handler" by @driesvints in https://github.com/laravel/passport/commit/67c3e336af163f6eba5dbca8e5db46275ff0e433 ## [v11.8.1](https://github.com/laravel/passport/compare/v11.8.0...v11.8.1) - 2023-02-20 From 587aa1460fb8a4ac24d042b68513ef86b78d760a Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Tue, 21 Feb 2023 19:40:22 +0330 Subject: [PATCH 316/353] allow overriding the `AccessToken` class (#1638) --- src/Bridge/AccessTokenRepository.php | 3 ++- src/Passport.php | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index 0fe2be49b..23572d760 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -5,6 +5,7 @@ use DateTime; use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Events\AccessTokenCreated; +use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; @@ -46,7 +47,7 @@ public function __construct(TokenRepository $tokenRepository, Dispatcher $events */ public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null) { - return new AccessToken($userIdentifier, $scopes, $clientEntity); + return new Passport::$accessTokenEntity($userIdentifier, $scopes, $clientEntity); } /** diff --git a/src/Passport.php b/src/Passport.php index 706a7543a..d1a6c0e90 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -79,6 +79,13 @@ class Passport */ public static $keyPath; + /** + * The access token entity class name. + * + * @var string + */ + public static $accessTokenEntity = 'Laravel\Passport\Bridge\AccessToken'; + /** * The auth code model class name. * @@ -432,6 +439,17 @@ public static function keyPath($file) : storage_path($file); } + /** + * Set the access token entity class name. + * + * @param string $accessTokenEntity + * @return void + */ + public static function useAccessTokenEntity($accessTokenEntity) + { + static::$accessTokenEntity = $accessTokenEntity; + } + /** * Set the auth code model class name. * From 112e94561b1df90985493f8e0e65630bd70b8575 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Thu, 23 Feb 2023 08:21:11 +0000 Subject: [PATCH 317/353] Adds type checking (#1640) --- .gitattributes | 1 + .github/workflows/static-analysis.yml | 41 +++++++++++++++++++++++++++ composer.json | 1 + phpstan.neon.dist | 11 +++++++ src/Guards/TokenGuard.php | 2 +- 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/static-analysis.yml create mode 100644 phpstan.neon.dist diff --git a/.gitattributes b/.gitattributes index efd7a3a8e..6c56d0f01 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,5 +14,6 @@ .gitignore export-ignore .styleci.yml export-ignore CHANGELOG.md export-ignore +phpstan.neon.dist export-ignore phpunit.xml.dist export-ignore UPGRADE.md diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 000000000..453d8a6a0 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,41 @@ +name: static analysis + +on: + push: + branches: + - master + - '*.x' + pull_request: + +permissions: + contents: read + +jobs: + tests: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: true + + name: Static Analysis + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + tools: composer:v2 + coverage: none + + - name: Install dependencies + uses: nick-fields/retry@v2 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress + + - name: Execute type checking + run: vendor/bin/phpstan diff --git a/composer.json b/composer.json index 364339a7f..d7b2f0f83 100644 --- a/composer.json +++ b/composer.json @@ -35,6 +35,7 @@ "require-dev": { "mockery/mockery": "^1.0", "orchestra/testbench": "^7.0|^8.0", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3" }, "autoload": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 000000000..649776a4c --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,11 @@ +parameters: + paths: + - config + - database + - routes + - src + + level: 0 + + ignoreErrors: + - "#Unsafe usage of new static\\(\\)#" diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 6798ca393..fe067e800 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -214,7 +214,7 @@ protected function authenticateViaBearerToken($request) * Authenticate and get the incoming PSR-7 request via the Bearer token. * * @param \Illuminate\Http\Request $request - * @return \Psr\Http\Message\ServerRequestInterface + * @return \Psr\Http\Message\ServerRequestInterface|null */ protected function getPsrRequestViaBearerToken($request) { From fcfac3fe70a01d6ad23b33a9f562c3d4067b2713 Mon Sep 17 00:00:00 2001 From: Bram Date: Wed, 1 Mar 2023 08:32:45 +0000 Subject: [PATCH 318/353] Update ClientRepository.php (#1642) --- src/ClientRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 402deb057..2809b3ae1 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -158,7 +158,7 @@ public function create($userId, $name, $redirect, $provider = null, $personalAcc /** * Store a new personal access token client. * - * @param int $userId + * @param int|null $userId * @param string $name * @param string $redirect * @return \Laravel\Passport\Client @@ -175,7 +175,7 @@ public function createPersonalAccessClient($userId, $name, $redirect) /** * Store a new password grant client. * - * @param int $userId + * @param int|null $userId * @param string $name * @param string $redirect * @param string|null $provider From d60300185cfd066190b7842982cce314f779f9dd Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Wed, 1 Mar 2023 16:56:44 +0100 Subject: [PATCH 319/353] Fix tests --- tests/Feature/AccessTokenControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 54cb4ffd9..87d31b3a9 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -73,7 +73,7 @@ public function testGettingAccessTokenWithClientCredentialsGrant() $this->assertArrayHasKey('expires_in', $decodedResponse); $this->assertArrayHasKey('access_token', $decodedResponse); $this->assertSame('Bearer', $decodedResponse['token_type']); - $expiresInSeconds = 31536000; + $expiresInSeconds = 31622400; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); @@ -163,7 +163,7 @@ public function testGettingAccessTokenWithPasswordGrant() $this->assertArrayHasKey('access_token', $decodedResponse); $this->assertArrayHasKey('refresh_token', $decodedResponse); $this->assertSame('Bearer', $decodedResponse['token_type']); - $expiresInSeconds = 31536000; + $expiresInSeconds = 31622400; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); From 37ce6e6b6a2dab591978903795454cdfa80e9c2a Mon Sep 17 00:00:00 2001 From: driesvints Date: Thu, 2 Mar 2023 16:24:50 +0000 Subject: [PATCH 320/353] Update CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f618e323d..9328e6a68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.2...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.3...11.x) + +## [v11.8.3](https://github.com/laravel/passport/compare/v11.8.2...v11.8.3) - 2023-03-01 + +- Allow overriding the `AccessToken` class by @hafezdivandari in https://github.com/laravel/passport/pull/1638 +- Make `$userId` nullable in `ClientRepository->createPersonalAccessClient` by @bram-pkg in https://github.com/laravel/passport/pull/1642 ## [v11.8.2](https://github.com/laravel/passport/compare/v11.8.1...v11.8.2) - 2023-02-20 From 95a2258b396af786e5a8ae2a5e9ed3fa7c1a57ce Mon Sep 17 00:00:00 2001 From: Sergey Pashkevich Date: Fri, 17 Mar 2023 16:39:15 +0300 Subject: [PATCH 321/353] Update RefreshToken.php (#1645) --- src/RefreshToken.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/RefreshToken.php b/src/RefreshToken.php index 00e5a1c84..df45c4247 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -41,15 +41,7 @@ class RefreshToken extends Model */ protected $casts = [ 'revoked' => 'bool', - ]; - - /** - * The attributes that should be mutated to dates. - * - * @var array - */ - protected $dates = [ - 'expires_at', + 'expires_at' => 'datetime', ]; /** From a1682d39b7730d318d1a6e3139836e06bda692d4 Mon Sep 17 00:00:00 2001 From: Sergey Pashkevich Date: Fri, 17 Mar 2023 16:39:26 +0300 Subject: [PATCH 322/353] Update AuthCode.php (#1644) --- src/AuthCode.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/AuthCode.php b/src/AuthCode.php index 09a79c826..5c045bacb 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -34,15 +34,7 @@ class AuthCode extends Model */ protected $casts = [ 'revoked' => 'bool', - ]; - - /** - * The attributes that should be mutated to dates. - * - * @var array - */ - protected $dates = [ - 'expires_at', + 'expires_at' => 'datetime', ]; /** From b33fa25458c26465e6acf5ed6989ba48e2628eef Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 17 Mar 2023 13:39:43 +0000 Subject: [PATCH 323/353] Apply fixes from StyleCI --- tests/Unit/DenyAuthorizationControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/DenyAuthorizationControllerTest.php b/tests/Unit/DenyAuthorizationControllerTest.php index 366cc8636..e2cd26f69 100644 --- a/tests/Unit/DenyAuthorizationControllerTest.php +++ b/tests/Unit/DenyAuthorizationControllerTest.php @@ -36,7 +36,7 @@ public function test_authorization_can_be_denied() ->once() ->with('authRequest') ->andReturn($authRequest = m::mock( - AuthorizationRequest::class + AuthorizationRequest::class )); $authRequest->shouldReceive('setUser')->once(); From b6b68fad1d02e39c6c659705159487f643393cdd Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Sat, 18 Mar 2023 22:25:20 +0330 Subject: [PATCH 324/353] fix doc types (#1647) --- src/Http/Controllers/AuthorizationController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 0c2bc6e8d..38942232b 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -46,6 +46,7 @@ class AuthorizationController * * @param \League\OAuth2\Server\AuthorizationServer $server * @param \Illuminate\Contracts\Auth\StatefulGuard $guard + * @param \Laravel\Passport\Contracts\AuthorizationViewResponse $response * @return void */ public function __construct(AuthorizationServer $server, @@ -64,7 +65,7 @@ public function __construct(AuthorizationServer $server, * @param \Illuminate\Http\Request $request * @param \Laravel\Passport\ClientRepository $clients * @param \Laravel\Passport\TokenRepository $tokens - * @return \Laravel\Passport\Contracts\AuthorizationViewResponse + * @return \Illuminate\Http\Response|\Laravel\Passport\Contracts\AuthorizationViewResponse */ public function authorize(ServerRequestInterface $psrRequest, Request $request, From 2583a0a8252288150cc9c518b5eaf45fd4237fa6 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 28 Mar 2023 18:16:05 +0000 Subject: [PATCH 325/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9328e6a68..ba22d21de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.3...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.4...11.x) + +## [v11.8.4](https://github.com/laravel/passport/compare/v11.8.3...v11.8.4) - 2023-03-18 + +- Removed deprecated `dates` property from `RefreshToken` model by @siarheipashkevich in https://github.com/laravel/passport/pull/1645 +- Removed deprecated `dates` property from `AuthCode` model by @siarheipashkevich in https://github.com/laravel/passport/pull/1644 +- Fix doc block types by @hafezdivandari in https://github.com/laravel/passport/pull/1647 ## [v11.8.3](https://github.com/laravel/passport/compare/v11.8.2...v11.8.3) - 2023-03-01 From ef5fa30b43e08ada9ec9dc7468e8ea8b2e1a490b Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Tue, 4 Apr 2023 14:37:07 +0100 Subject: [PATCH 326/353] [11.x] Allow `lcobucci/jwt` v5 and cleaned up version constraints (#1649) * Allow `lcobucci/jwt` v5 * Temp change to see why CI no likey * Update composer.json * Update composer.json * Fixes * Update composer.json --- composer.json | 10 +++++----- src/PassportServiceProvider.php | 9 +++++---- tests/Unit/PersonalAccessTokenFactoryTest.php | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index d7b2f0f83..450845b4b 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require": { "php": "^8.0", "ext-json": "*", - "firebase/php-jwt": "^6.3.1", + "firebase/php-jwt": "^6.4", "illuminate/auth": "^9.0|^10.0", "illuminate/console": "^9.0|^10.0", "illuminate/container": "^9.0|^10.0", @@ -26,11 +26,11 @@ "illuminate/encryption": "^9.0|^10.0", "illuminate/http": "^9.0|^10.0", "illuminate/support": "^9.0|^10.0", - "lcobucci/jwt": "^3.4|^4.0", - "league/oauth2-server": "^8.2", - "nyholm/psr7": "^1.3", + "lcobucci/jwt": "^4.3|^5.0", + "league/oauth2-server": "^8.5.1", + "nyholm/psr7": "^1.5", "phpseclib/phpseclib": "^2.0|^3.0", - "symfony/psr-http-message-bridge": "^2.0" + "symfony/psr-http-message-bridge": "^2.1" }, "require-dev": { "mockery/mockery": "^1.0", diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 64ed0b925..99e345e17 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -16,8 +16,9 @@ use Laravel\Passport\Bridge\RefreshTokenRepository; use Laravel\Passport\Guards\TokenGuard; use Laravel\Passport\Http\Controllers\AuthorizationController; -use Lcobucci\JWT\Configuration; -use Lcobucci\JWT\Parser; +use Lcobucci\JWT\Encoding\JoseEncoder; +use Lcobucci\JWT\Parser as ParserContract; +use Lcobucci\JWT\Token\Parser; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Grant\AuthCodeGrant; @@ -294,8 +295,8 @@ protected function registerClientRepository() */ protected function registerJWTParser() { - $this->app->singleton(Parser::class, function () { - return Configuration::forUnsecuredSigner()->parser(); + $this->app->singleton(ParserContract::class, function () { + return new Parser(new JoseEncoder); }); } diff --git a/tests/Unit/PersonalAccessTokenFactoryTest.php b/tests/Unit/PersonalAccessTokenFactoryTest.php index 33e576465..c35127104 100644 --- a/tests/Unit/PersonalAccessTokenFactoryTest.php +++ b/tests/Unit/PersonalAccessTokenFactoryTest.php @@ -42,7 +42,7 @@ public function test_access_token_can_be_created() $parsedToken = new PlainToken( new DataSet([], ''), new DataSet([RegisteredClaims::ID => 'token'], ''), - Signature::fromEmptyData() + new Signature('', '') ); $jwt->shouldReceive('parse')->with('foo')->andReturn($parsedToken); From 5417fe870a1a76628c13c79ce4c9b6fbea429bc0 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Tue, 4 Apr 2023 15:06:53 +0100 Subject: [PATCH 327/353] Pass user identifier through to finalize scopes in personal access grant (#1650) --- src/Bridge/PersonalAccessGrant.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Bridge/PersonalAccessGrant.php b/src/Bridge/PersonalAccessGrant.php index 289a0257a..4eb5f869c 100644 --- a/src/Bridge/PersonalAccessGrant.php +++ b/src/Bridge/PersonalAccessGrant.php @@ -20,14 +20,22 @@ public function respondToAccessTokenRequest( // Validate request $client = $this->validateClient($request); $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $userIdentifier = $this->getRequestParameter('user_id', $request); // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); + $scopes = $this->scopeRepository->finalizeScopes( + $scopes, + $this->getIdentifier(), + $client, + $userIdentifier + ); // Issue and persist access token $accessToken = $this->issueAccessToken( - $accessTokenTTL, $client, - $this->getRequestParameter('user_id', $request), $scopes + $accessTokenTTL, + $client, + $userIdentifier, + $scopes ); // Inject access token into response type From 771cedbda3c55c8611abbe901dbb78163a59201b Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 4 Apr 2023 15:04:47 +0000 Subject: [PATCH 328/353] Update CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba22d21de..4f0ae6e1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.4...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.5...11.x) + +## [v11.8.5](https://github.com/laravel/passport/compare/v11.8.4...v11.8.5) - 2023-04-04 + +- Allow `lcobucci/jwt` v5 and cleaned up version constraints by @GrahamCampbell in https://github.com/laravel/passport/pull/1649 +- Pass user identifier through to finalize scopes in personal access grant by @GrahamCampbell in https://github.com/laravel/passport/pull/1650 ## [v11.8.4](https://github.com/laravel/passport/compare/v11.8.3...v11.8.4) - 2023-03-18 From 5e5a54f3d8a398344d75aacd9097bceff2e10c17 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 6 Apr 2023 17:21:28 +0200 Subject: [PATCH 329/353] Update 1_Bug_report.md --- .github/ISSUE_TEMPLATE/1_Bug_report.md | 68 ++++++++++++++++++-------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md index 2d7b68a23..f9c5e229b 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.md @@ -1,20 +1,48 @@ ---- -name: "Bug report" -about: "Report something that's broken. Please ensure your Laravel version is still supported: https://laravel.com/docs/releases#support-policy" ---- - - - - -- Passport Version: #.#.# -- Laravel Version: #.#.# -- PHP Version: #.#.# -- Database Driver & Version: - -### Description: - - -### Steps To Reproduce: - - - +name: Bug Report +description: "Report a general library issue." +labels: ["bug"] +body: + - type: markdown + attributes: + value: "Before submitting your report, [please ensure your Laravel version is still supported](https://laravel.com/docs/releases#support-policy)." + - type: input + attributes: + label: Passport Version + description: Provide the Passport version that you are using. + placeholder: 10.0.1 + validations: + required: true + - type: input + attributes: + label: Laravel Version + description: Provide the Laravel version that you are using. + placeholder: 10.4.1 + validations: + required: true + - type: input + attributes: + label: PHP Version + description: Provide the PHP version that you are using. + placeholder: 8.1.4 + validations: + required: true + - type: input + attributes: + label: Database Driver & Version + description: If applicable, provide the database driver and version you are using. + placeholder: "MySQL 8.0.31 for macOS 13.0 on arm64 (Homebrew)" + validations: + required: false + - type: textarea + attributes: + label: Description + description: Provide a detailed description of the issue you are facing. + validations: + required: true + - type: textarea + attributes: + label: Steps To Reproduce + description: Provide detailed steps to reproduce your issue. If necessary, please provide a GitHub repository to demonstrate your issue using `laravel new bug-report --github="--public"`. + validations: + required: true + From 5131ceaec1ed02028966c0c44f87e565da19fad2 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 6 Apr 2023 17:21:38 +0200 Subject: [PATCH 330/353] Rename 1_Bug_report.md to 1_Bug_report.yml --- .github/ISSUE_TEMPLATE/{1_Bug_report.md => 1_Bug_report.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{1_Bug_report.md => 1_Bug_report.yml} (100%) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/1_Bug_report.md rename to .github/ISSUE_TEMPLATE/1_Bug_report.yml From bf5e6f41900b88e1b545377317c2006b53834937 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 7 Apr 2023 10:05:00 +0200 Subject: [PATCH 331/353] Update 1_Bug_report.yml --- .github/ISSUE_TEMPLATE/1_Bug_report.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yml b/.github/ISSUE_TEMPLATE/1_Bug_report.yml index f9c5e229b..bc02d3a13 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yml @@ -1,6 +1,5 @@ name: Bug Report description: "Report a general library issue." -labels: ["bug"] body: - type: markdown attributes: From a75f0a92136a6cf91e5c6755374f77bf4b30c411 Mon Sep 17 00:00:00 2001 From: Michael Nabil <46572405+michaelnabil230@users.noreply.github.com> Date: Mon, 24 Apr 2023 22:05:58 +0200 Subject: [PATCH 332/353] [11.x] Add Provider Guard to ClientRepository for Personal Access Clients (#1655) * Added provider guard to Password Grant Client. * Add argument provider in `InstallCommand` * formatting --------- Co-authored-by: Taylor Otwell --- src/ClientRepository.php | 5 +++-- src/Console/ClientCommand.php | 28 ++++++++++++++++++++-------- src/Console/InstallCommand.php | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 2809b3ae1..5fc2fab0a 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -161,11 +161,12 @@ public function create($userId, $name, $redirect, $provider = null, $personalAcc * @param int|null $userId * @param string $name * @param string $redirect + * @param string|null $provider * @return \Laravel\Passport\Client */ - public function createPersonalAccessClient($userId, $name, $redirect) + public function createPersonalAccessClient($userId, $name, $redirect, $provider = null) { - return tap($this->create($userId, $name, $redirect, null, true), function ($client) { + return tap($this->create($userId, $name, $redirect, $provider, true), function ($client) { $accessClient = Passport::personalAccessClient(); $accessClient->client_id = $client->getKey(); $accessClient->save(); diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index c46f63bc6..2a9f47cc5 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -63,8 +63,10 @@ protected function createPersonalClient(ClientRepository $clients) config('app.name').' Personal Access Client' ); + $provider = $this->promptForProvider(); + $client = $clients->createPersonalAccessClient( - null, $name, 'http://localhost' + null, $name, 'http://localhost', $provider ); $this->info('Personal access client created successfully.'); @@ -85,13 +87,7 @@ protected function createPasswordClient(ClientRepository $clients) config('app.name').' Password Grant Client' ); - $providers = array_keys(config('auth.providers')); - - $provider = $this->option('provider') ?: $this->choice( - 'Which user provider should this client use to retrieve users?', - $providers, - in_array('users', $providers) ? 'users' : null - ); + $provider = $this->promptForProvider(); $client = $clients->createPasswordGrantClient( null, $name, 'http://localhost', $provider @@ -154,6 +150,22 @@ protected function createAuthCodeClient(ClientRepository $clients) $this->outputClientDetails($client); } + /** + * Ask the user what user provider should be used. + * + * @return string + */ + protected function promptForProvider() + { + $providers = array_keys(config('auth.providers')); + + return $this->option('provider') ?: $this->choice( + 'Which user provider should this client use to retrieve users?', + $providers, + in_array('users', $providers) ? 'users' : null + ); + } + /** * Output the client's ID and secret key. * diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index f5ed11023..a5311c47f 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -39,7 +39,7 @@ public function handle() $this->configureUuids(); } - $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); + $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client', '--provider' => $provider]); $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => $provider]); } From 487f1831e5725ebc5037e3ef0dd8ecafa840c994 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 25 Apr 2023 14:50:00 +0000 Subject: [PATCH 333/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f0ae6e1e..dc9175af0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.5...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.6...11.x) + +## [v11.8.6](https://github.com/laravel/passport/compare/v11.8.5...v11.8.6) - 2023-04-24 + +- Add Provider Guard to ClientRepository for Personal Access Clients by @michaelnabil230 in https://github.com/laravel/passport/pull/1655 ## [v11.8.5](https://github.com/laravel/passport/compare/v11.8.4...v11.8.5) - 2023-04-04 From 48a03ffbfce7217b7ceba2c8e685ae8caa68db10 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 28 Apr 2023 12:08:34 +0200 Subject: [PATCH 334/353] Revert "[11.x] Add Provider Guard to ClientRepository for Personal Access Clients (#1655)" (#1658) This reverts commit a75f0a92136a6cf91e5c6755374f77bf4b30c411. --- src/ClientRepository.php | 5 ++--- src/Console/ClientCommand.php | 28 ++++++++-------------------- src/Console/InstallCommand.php | 2 +- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 5fc2fab0a..2809b3ae1 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -161,12 +161,11 @@ public function create($userId, $name, $redirect, $provider = null, $personalAcc * @param int|null $userId * @param string $name * @param string $redirect - * @param string|null $provider * @return \Laravel\Passport\Client */ - public function createPersonalAccessClient($userId, $name, $redirect, $provider = null) + public function createPersonalAccessClient($userId, $name, $redirect) { - return tap($this->create($userId, $name, $redirect, $provider, true), function ($client) { + return tap($this->create($userId, $name, $redirect, null, true), function ($client) { $accessClient = Passport::personalAccessClient(); $accessClient->client_id = $client->getKey(); $accessClient->save(); diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index 2a9f47cc5..c46f63bc6 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -63,10 +63,8 @@ protected function createPersonalClient(ClientRepository $clients) config('app.name').' Personal Access Client' ); - $provider = $this->promptForProvider(); - $client = $clients->createPersonalAccessClient( - null, $name, 'http://localhost', $provider + null, $name, 'http://localhost' ); $this->info('Personal access client created successfully.'); @@ -87,7 +85,13 @@ protected function createPasswordClient(ClientRepository $clients) config('app.name').' Password Grant Client' ); - $provider = $this->promptForProvider(); + $providers = array_keys(config('auth.providers')); + + $provider = $this->option('provider') ?: $this->choice( + 'Which user provider should this client use to retrieve users?', + $providers, + in_array('users', $providers) ? 'users' : null + ); $client = $clients->createPasswordGrantClient( null, $name, 'http://localhost', $provider @@ -150,22 +154,6 @@ protected function createAuthCodeClient(ClientRepository $clients) $this->outputClientDetails($client); } - /** - * Ask the user what user provider should be used. - * - * @return string - */ - protected function promptForProvider() - { - $providers = array_keys(config('auth.providers')); - - return $this->option('provider') ?: $this->choice( - 'Which user provider should this client use to retrieve users?', - $providers, - in_array('users', $providers) ? 'users' : null - ); - } - /** * Output the client's ID and secret key. * diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index a5311c47f..f5ed11023 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -39,7 +39,7 @@ public function handle() $this->configureUuids(); } - $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client', '--provider' => $provider]); + $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => $provider]); } From 8cae3ef2ccb4f83f23c6a5929b6996a4affdaa72 Mon Sep 17 00:00:00 2001 From: driesvints Date: Fri, 28 Apr 2023 10:09:54 +0000 Subject: [PATCH 335/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc9175af0..104fb6d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.6...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.7...11.x) + +## [v11.8.7](https://github.com/laravel/passport/compare/v11.8.6...v11.8.7) - 2023-04-28 + +- Revert "[11.x] Add Provider Guard to ClientRepository for Personal Access Clients" by @driesvints in https://github.com/laravel/passport/pull/1658 ## [v11.8.6](https://github.com/laravel/passport/compare/v11.8.5...v11.8.6) - 2023-04-24 From be0d862ae3b85ffebfdeddbaada2f2163a8e6dac Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Wed, 31 May 2023 16:45:40 +0200 Subject: [PATCH 336/353] Update ClientFactory.php (#1669) --- database/factories/ClientFactory.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index afdc227da..e9f25b790 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -7,6 +7,9 @@ use Laravel\Passport\Client; use Laravel\Passport\Passport; +/** + * @extends \Illuminate\Database\Eloquent\Factories\Factory<\Laravel\Passport\Client> + */ class ClientFactory extends Factory { /** From 8b88aff8bf97e90e570e9a8e2a49d9786cf95307 Mon Sep 17 00:00:00 2001 From: "P. De Bleye" Date: Wed, 21 Jun 2023 08:53:41 +0200 Subject: [PATCH 337/353] Update composer.json (#1674) Require new thephpleague/oauth2-server --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 450845b4b..378e2c9fb 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "illuminate/http": "^9.0|^10.0", "illuminate/support": "^9.0|^10.0", "lcobucci/jwt": "^4.3|^5.0", - "league/oauth2-server": "^8.5.1", + "league/oauth2-server": "^8.5.2", "nyholm/psr7": "^1.5", "phpseclib/phpseclib": "^2.0|^3.0", "symfony/psr-http-message-bridge": "^2.1" From 401836130d46c94138a637ada29f9e5b2bf053b6 Mon Sep 17 00:00:00 2001 From: Houssem Eddine Guemari Date: Fri, 7 Jul 2023 08:37:11 +0200 Subject: [PATCH 338/353] Update composer.json (#1677) Updated league/oauth2-server. More details in tis PR: https://github.com/thephpleague/oauth2-server/pull/1353 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 378e2c9fb..2b8b77602 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "illuminate/http": "^9.0|^10.0", "illuminate/support": "^9.0|^10.0", "lcobucci/jwt": "^4.3|^5.0", - "league/oauth2-server": "^8.5.2", + "league/oauth2-server": "^8.5.3", "nyholm/psr7": "^1.5", "phpseclib/phpseclib": "^2.0|^3.0", "symfony/psr-http-message-bridge": "^2.1" From b566e159c9661c49ca07b8e12a91ef86ee1bb94c Mon Sep 17 00:00:00 2001 From: driesvints Date: Fri, 7 Jul 2023 09:45:43 +0000 Subject: [PATCH 339/353] Update CHANGELOG --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 104fb6d27..a3bef1474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.7...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.8...11.x) + +## [v11.8.8](https://github.com/laravel/passport/compare/v11.8.7...v11.8.8) - 2023-07-07 + +- Add generics to client factory by [@axlon](https://github.com/axlon) in https://github.com/laravel/passport/pull/1669 +- Update composer.json by [@Smoggert](https://github.com/Smoggert) in https://github.com/laravel/passport/pull/1674 +- Update composer.json by [@drhoussem](https://github.com/drhoussem) in https://github.com/laravel/passport/pull/1677 ## [v11.8.7](https://github.com/laravel/passport/compare/v11.8.6...v11.8.7) - 2023-04-28 From dd3f0815948097e6d9f0ba4a1d79c53040bcdd03 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Wed, 23 Aug 2023 17:35:47 +0200 Subject: [PATCH 340/353] [11.x] Add the ability to limit scopes by client (#1682) * Add the ability to limit scopes by client * Update Client.php --------- Co-authored-by: Taylor Otwell --- src/Bridge/ScopeRepository.php | 26 +++++++++- src/Client.php | 12 +++++ tests/Unit/BridgeScopeRepositoryTest.php | 61 +++++++++++++++++++++++- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/Bridge/ScopeRepository.php b/src/Bridge/ScopeRepository.php index 4e7e7ec12..da05f77e2 100644 --- a/src/Bridge/ScopeRepository.php +++ b/src/Bridge/ScopeRepository.php @@ -2,12 +2,31 @@ namespace Laravel\Passport\Bridge; +use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; class ScopeRepository implements ScopeRepositoryInterface { + /** + * The client repository. + * + * @var \Laravel\Passport\ClientRepository + */ + protected ClientRepository $clients; + + /** + * Create a new scope repository. + * + * @param \Laravel\Passport\ClientRepository $clients + * @return void + */ + public function __construct(ClientRepository $clients) + { + $this->clients = $clients; + } + /** * {@inheritdoc} */ @@ -31,8 +50,11 @@ public function finalizeScopes( })->values()->all(); } - return collect($scopes)->filter(function ($scope) { - return Passport::hasScope($scope->getIdentifier()); + $client = $this->clients->findActive($clientEntity->getIdentifier()); + + return collect($scopes)->filter(function ($scope) use ($client) { + return Passport::hasScope($scope->getIdentifier()) + && $client->hasScope($scope->getIdentifier()); })->values()->all(); } } diff --git a/src/Client.php b/src/Client.php index 7313b40d8..ff721eac3 100644 --- a/src/Client.php +++ b/src/Client.php @@ -41,6 +41,7 @@ class Client extends Model */ protected $casts = [ 'grant_types' => 'array', + 'scopes' => 'array', 'personal_access_client' => 'bool', 'password_client' => 'bool', 'revoked' => 'bool', @@ -154,6 +155,17 @@ public function skipsAuthorization() return false; } + /** + * Determine whether the client has the given scope. + * + * @param string $scope + * @return bool + */ + public function hasScope($scope) + { + return ! is_array($this->scopes) || in_array($scope, $this->scopes); + } + /** * Determine if the client is a confidential client. * diff --git a/tests/Unit/BridgeScopeRepositoryTest.php b/tests/Unit/BridgeScopeRepositoryTest.php index 4dc370aca..7cfdec1ff 100644 --- a/tests/Unit/BridgeScopeRepositoryTest.php +++ b/tests/Unit/BridgeScopeRepositoryTest.php @@ -5,7 +5,10 @@ use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\Scope; use Laravel\Passport\Bridge\ScopeRepository; +use Laravel\Passport\Client as ClientModel; +use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; +use Mockery; use PHPUnit\Framework\TestCase; class BridgeScopeRepositoryTest extends TestCase @@ -16,7 +19,56 @@ public function test_invalid_scopes_are_removed() 'scope-1' => 'description', ]); - $repository = new ScopeRepository; + $client = Mockery::mock(ClientModel::class)->makePartial(); + + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs()->andReturn($client); + + $repository = new ScopeRepository($clients); + + $scopes = $repository->finalizeScopes( + [$scope1 = new Scope('scope-1'), new Scope('scope-2')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([$scope1], $scopes); + } + + public function test_clients_do_not_restrict_scopes_by_default() + { + Passport::tokensCan([ + 'scope-1' => 'description', + 'scope-2' => 'description', + ]); + + $client = Mockery::mock(ClientModel::class)->makePartial(); + $client->scopes = null; + + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs()->andReturn($client); + + $repository = new ScopeRepository($clients); + + $scopes = $repository->finalizeScopes( + [$scope1 = new Scope('scope-1'), $scope2 = new Scope('scope-2')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([$scope1, $scope2], $scopes); + } + + public function test_scopes_disallowed_for_client_are_removed() + { + Passport::tokensCan([ + 'scope-1' => 'description', + 'scope-2' => 'description', + ]); + + $client = Mockery::mock(ClientModel::class)->makePartial(); + $client->scopes = ['scope-1']; + + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs()->andReturn($client); + + $repository = new ScopeRepository($clients); $scopes = $repository->finalizeScopes( [$scope1 = new Scope('scope-1'), new Scope('scope-2')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 @@ -31,7 +83,12 @@ public function test_superuser_scope_cant_be_applied_if_wrong_grant() 'scope-1' => 'description', ]); - $repository = new ScopeRepository; + $client = Mockery::mock(ClientModel::class)->makePartial(); + + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs()->andReturn($client); + + $repository = new ScopeRepository($clients); $scopes = $repository->finalizeScopes( [$scope1 = new Scope('*')], 'refresh_token', new Client('id', 'name', 'http://localhost'), 1 From 2582d2a58ff32761cb3aecb337a146ba17483f76 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:48:41 +0200 Subject: [PATCH 341/353] Add support for inherited scopes when limiting scopes on clients (#1683) --- src/Client.php | 17 +++++++++++++- src/ResolvesInheritedScopes.php | 27 +++++++++++++++++++++ src/Token.php | 23 ++---------------- tests/Unit/BridgeScopeRepositoryTest.php | 30 ++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 src/ResolvesInheritedScopes.php diff --git a/src/Client.php b/src/Client.php index ff721eac3..e33454ad7 100644 --- a/src/Client.php +++ b/src/Client.php @@ -10,6 +10,7 @@ class Client extends Model { use HasFactory; + use ResolvesInheritedScopes; /** * The database table used by the model. @@ -163,7 +164,21 @@ public function skipsAuthorization() */ public function hasScope($scope) { - return ! is_array($this->scopes) || in_array($scope, $this->scopes); + if (! is_array($this->scopes)) { + return true; + } + + $scopes = Passport::$withInheritedScopes + ? $this->resolveInheritedScopes($scope) + : [$scope]; + + foreach ($scopes as $scope) { + if (in_array($scope, $this->scopes)) { + return true; + } + } + + return false; } /** diff --git a/src/ResolvesInheritedScopes.php b/src/ResolvesInheritedScopes.php new file mode 100644 index 000000000..e7658a165 --- /dev/null +++ b/src/ResolvesInheritedScopes.php @@ -0,0 +1,27 @@ +assertEquals([$scope1], $scopes); } + public function test_scopes_disallowed_for_client_are_removed_but_inherited_scopes_are_not() + { + Passport::$withInheritedScopes = true; + + Passport::tokensCan([ + 'scope-1' => 'description', + 'scope-1:limited-access' => 'description', + 'scope-2' => 'description', + ]); + + $client = Mockery::mock(ClientModel::class)->makePartial(); + $client->scopes = ['scope-1']; + + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs()->andReturn($client); + + $repository = new ScopeRepository($clients); + + $scopes = $repository->finalizeScopes( + [$scope1 = new Scope('scope-1:limited-access'), new Scope('scope-2')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([$scope1], $scopes); + } + public function test_superuser_scope_cant_be_applied_if_wrong_grant() { Passport::tokensCan([ From e22596051d83ce8d92c4a0f75ce95f78198cee06 Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 29 Aug 2023 15:23:00 +0000 Subject: [PATCH 342/353] Update CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3bef1474..2a951207b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.8.8...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.9.0...11.x) + +## [v11.9.0](https://github.com/laravel/passport/compare/v11.8.8...v11.9.0) - 2023-08-29 + +- [11.x] Add the ability to limit scopes by client by [@axlon](https://github.com/axlon) in https://github.com/laravel/passport/pull/1682 +- [11.x] Add support for inherited scopes when limiting scopes on clients by [@axlon](https://github.com/axlon) in https://github.com/laravel/passport/pull/1683 ## [v11.8.8](https://github.com/laravel/passport/compare/v11.8.7...v11.8.8) - 2023-07-07 From 93bb9c36045fe5be2eaeacf35e836c00b392b761 Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Fri, 1 Sep 2023 16:20:24 +0200 Subject: [PATCH 343/353] Fix breaking change introduced by laravel/passport#1682 (#1686) --- src/Bridge/ScopeRepository.php | 17 +++++++------- tests/Unit/BridgeScopeRepositoryTest.php | 30 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/Bridge/ScopeRepository.php b/src/Bridge/ScopeRepository.php index da05f77e2..05e0ac9a1 100644 --- a/src/Bridge/ScopeRepository.php +++ b/src/Bridge/ScopeRepository.php @@ -12,17 +12,17 @@ class ScopeRepository implements ScopeRepositoryInterface /** * The client repository. * - * @var \Laravel\Passport\ClientRepository + * @var \Laravel\Passport\ClientRepository|null */ - protected ClientRepository $clients; + protected ?ClientRepository $clients; /** * Create a new scope repository. * - * @param \Laravel\Passport\ClientRepository $clients + * @param \Laravel\Passport\ClientRepository|null $clients * @return void */ - public function __construct(ClientRepository $clients) + public function __construct(?ClientRepository $clients = null) { $this->clients = $clients; } @@ -50,11 +50,12 @@ public function finalizeScopes( })->values()->all(); } - $client = $this->clients->findActive($clientEntity->getIdentifier()); + $client = $this->clients?->findActive($clientEntity->getIdentifier()); - return collect($scopes)->filter(function ($scope) use ($client) { - return Passport::hasScope($scope->getIdentifier()) - && $client->hasScope($scope->getIdentifier()); + return collect($scopes)->filter(function ($scope) { + return Passport::hasScope($scope->getIdentifier()); + })->when($client, function ($scopes, $client) { + return $scopes->filter(fn ($scope) => $client->hasScope($scope->getIdentifier())); })->values()->all(); } } diff --git a/tests/Unit/BridgeScopeRepositoryTest.php b/tests/Unit/BridgeScopeRepositoryTest.php index 4743073cf..e663bf89b 100644 --- a/tests/Unit/BridgeScopeRepositoryTest.php +++ b/tests/Unit/BridgeScopeRepositoryTest.php @@ -38,6 +38,21 @@ public function test_invalid_scopes_are_removed() $this->assertEquals([$scope1], $scopes); } + public function test_invalid_scopes_are_removed_without_a_client_repository() + { + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $repository = new ScopeRepository(); + + $scopes = $repository->finalizeScopes( + [$scope1 = new Scope('scope-1'), new Scope('scope-2')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([$scope1], $scopes); + } + public function test_clients_do_not_restrict_scopes_by_default() { Passport::tokensCan([ @@ -126,4 +141,19 @@ public function test_superuser_scope_cant_be_applied_if_wrong_grant() $this->assertEquals([], $scopes); } + + public function test_superuser_scope_cant_be_applied_if_wrong_grant_without_a_client_repository() + { + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $repository = new ScopeRepository(); + + $scopes = $repository->finalizeScopes( + [$scope1 = new Scope('*')], 'refresh_token', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([], $scopes); + } } From 286baeb1be934654fe4eef147b24d3c8a9a3e08d Mon Sep 17 00:00:00 2001 From: driesvints Date: Fri, 1 Sep 2023 14:21:51 +0000 Subject: [PATCH 344/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a951207b..39040ba31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.9.0...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.9.1...11.x) + +## [v11.9.1](https://github.com/laravel/passport/compare/v11.9.0...v11.9.1) - 2023-09-01 + +- [11.x] Allow scope repository to be constructed without parameters by [@axlon](https://github.com/axlon) in https://github.com/laravel/passport/pull/1686 ## [v11.9.0](https://github.com/laravel/passport/compare/v11.8.8...v11.9.0) - 2023-08-29 From 5e9e4b8da8ea5c2d23bb7b119f634f57df770561 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Wed, 20 Sep 2023 21:58:30 +0800 Subject: [PATCH 345/353] Test Improvements (#1688) * Test Improvements Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki --------- Signed-off-by: Mior Muhammad Zaki --- composer.json | 10 ++- testbench.yaml | 5 ++ tests/Feature/AccessTokenControllerTest.php | 83 +++++++------------- tests/Feature/ActingAsTest.php | 20 ++--- tests/Feature/KeysCommandTest.php | 10 --- tests/Feature/PassportTestCase.php | 59 +++++--------- workbench/app/Models/User.php | 42 ++++++++++ workbench/database/factories/UserFactory.php | 20 +++++ 8 files changed, 129 insertions(+), 120 deletions(-) create mode 100644 testbench.yaml create mode 100644 workbench/app/Models/User.php create mode 100644 workbench/database/factories/UserFactory.php diff --git a/composer.json b/composer.json index 2b8b77602..9516d6d87 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.0|^8.0", + "orchestra/testbench": "^7.31|^8.11", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3" }, @@ -46,7 +46,9 @@ }, "autoload-dev": { "psr-4": { - "Laravel\\Passport\\Tests\\": "tests/" + "Laravel\\Passport\\Tests\\": "tests/", + "Workbench\\App\\": "workbench/app/", + "Workbench\\Database\\Factories\\": "workbench/database/factories/" } }, "extra": { @@ -62,6 +64,10 @@ "config": { "sort-packages": true }, + "scripts": { + "post-autoload-dump": "@prepare", + "prepare": "@php vendor/bin/testbench package:discover --ansi" + }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/testbench.yaml b/testbench.yaml new file mode 100644 index 000000000..7d0c53214 --- /dev/null +++ b/testbench.yaml @@ -0,0 +1,5 @@ +providers: + - Laravel\Passport\PassportServiceProvider + +migrations: true + diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index 87d31b3a9..92218333c 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -4,50 +4,26 @@ use Carbon\CarbonImmutable; use Illuminate\Contracts\Hashing\Hasher; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\Schema; use Laravel\Passport\Client; use Laravel\Passport\Database\Factories\ClientFactory; -use Laravel\Passport\HasApiTokens; use Laravel\Passport\Passport; use Laravel\Passport\PersonalAccessTokenFactory; use Laravel\Passport\Token; +use Orchestra\Testbench\Concerns\WithLaravelMigrations; +use Workbench\Database\Factories\UserFactory; class AccessTokenControllerTest extends PassportTestCase { - protected function setUp(): void - { - parent::setUp(); - - Schema::create('users', function (Blueprint $table) { - $table->increments('id'); - $table->string('email')->unique(); - $table->string('password'); - $table->dateTime('created_at'); - $table->dateTime('updated_at'); - }); - } - - protected function tearDown(): void - { - Schema::dropIfExists('users'); - - parent::tearDown(); - } - - protected function getUserClass() - { - return User::class; - } + use WithLaravelMigrations; public function testGettingAccessTokenWithClientCredentialsGrant() { $this->withoutExceptionHandling(); - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make('foobar123'); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make('foobar123'), + ]); /** @var Client $client */ $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); @@ -87,10 +63,10 @@ public function testGettingAccessTokenWithClientCredentialsGrant() public function testGettingAccessTokenWithClientCredentialsGrantInvalidClientSecret() { - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make('foobar123'); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make('foobar123'), + ]); /** @var Client $client */ $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); @@ -131,10 +107,10 @@ public function testGettingAccessTokenWithPasswordGrant() $this->withoutExceptionHandling(); $password = 'foobar123'; - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make($password); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make($password), + ]); /** @var Client $client */ $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); @@ -178,10 +154,10 @@ public function testGettingAccessTokenWithPasswordGrant() public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() { $password = 'foobar123'; - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make($password); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make($password), + ]); /** @var Client $client */ $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); @@ -221,10 +197,10 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() { $password = 'foobar123'; - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make($password); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make($password), + ]); /** @var Client $client */ $client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->getKey()]); @@ -268,10 +244,10 @@ public function testGettingCustomResponseType() $this->withoutExceptionHandling(); Passport::$authorizationServerResponseType = new IdTokenResponse('foo_bar_open_id_token'); - $user = new User(); - $user->email = 'foo@gmail.com'; - $user->password = $this->app->make(Hasher::class)->make('foobar123'); - $user->save(); + $user = UserFactory::new()->create([ + 'email' => 'foo@gmail.com', + 'password' => $this->app->make(Hasher::class)->make('foobar123'), + ]); /** @var Client $client */ $client = ClientFactory::new()->asClientCredentials()->create(['user_id' => $user->getKey()]); @@ -294,11 +270,6 @@ public function testGettingCustomResponseType() } } -class User extends \Illuminate\Foundation\Auth\User -{ - use HasApiTokens; -} - class IdTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerTokenResponse { /** diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index bf0b95319..031d5abf4 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -3,12 +3,11 @@ namespace Laravel\Passport\Tests\Feature; use Illuminate\Contracts\Routing\Registrar; -use Illuminate\Foundation\Auth\User; use Illuminate\Support\Facades\Route; -use Laravel\Passport\HasApiTokens; use Laravel\Passport\Http\Middleware\CheckForAnyScope; use Laravel\Passport\Http\Middleware\CheckScopes; use Laravel\Passport\Passport; +use Workbench\App\Models\User; class ActingAsTest extends PassportTestCase { @@ -23,7 +22,7 @@ public function testActingAsWhenTheRouteIsProtectedByAuthMiddleware() return 'bar'; })->middleware('auth:api'); - Passport::actingAs(new PassportUser()); + Passport::actingAs(new User()); $response = $this->get('/foo'); $response->assertSuccessful(); @@ -41,7 +40,7 @@ public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddleware() return 'bar'; })->middleware(CheckScopes::class.':admin,footest'); - Passport::actingAs(new PassportUser(), ['admin', 'footest']); + Passport::actingAs(new User(), ['admin', 'footest']); $response = $this->get('/foo'); $response->assertSuccessful(); @@ -59,7 +58,7 @@ public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware( return 'bar'; })->middleware(CheckForAnyScope::class.':admin,footest'); - Passport::actingAs(new PassportUser(), ['footest']); + Passport::actingAs(new User(), ['footest']); $response = $this->get('/foo'); $response->assertSuccessful(); @@ -76,7 +75,7 @@ public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddlewareWithIn return 'bar'; }); - Passport::actingAs(new PassportUser(), ['foo', 'baz']); + Passport::actingAs(new User(), ['foo', 'baz']); $response = $this->get('/foo'); $response->assertSuccessful(); @@ -93,17 +92,10 @@ public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddlewareW return 'bar'; }); - Passport::actingAs(new PassportUser(), ['foo']); + Passport::actingAs(new User(), ['foo']); $response = $this->get('/foo'); $response->assertSuccessful(); $response->assertSee('bar'); } } - -class PassportUser extends User -{ - use HasApiTokens; - - protected $table = 'users'; -} diff --git a/tests/Feature/KeysCommandTest.php b/tests/Feature/KeysCommandTest.php index e7d528f82..3d2f4b986 100644 --- a/tests/Feature/KeysCommandTest.php +++ b/tests/Feature/KeysCommandTest.php @@ -2,18 +2,8 @@ namespace Laravel\Passport\Tests\Feature; -use Mockery as m; - class KeysCommandTest extends PassportTestCase { - protected function tearDown(): void - { - m::close(); - - @unlink(self::PUBLIC_KEY); - @unlink(self::PRIVATE_KEY); - } - public function testPrivateAndPublicKeysAreGenerated() { $this->assertFileExists(self::PUBLIC_KEY); diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 8daeb4e6c..3ccf02bdc 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -3,14 +3,15 @@ namespace Laravel\Passport\Tests\Feature; use Illuminate\Contracts\Config\Repository; -use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Foundation\Testing\LazilyRefreshDatabase; use Laravel\Passport\Passport; -use Laravel\Passport\PassportServiceProvider; +use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase; +use Workbench\App\Models\User; abstract class PassportTestCase extends TestCase { - use RefreshDatabase; + use LazilyRefreshDatabase, WithWorkbench; const KEYS = __DIR__.'/../keys'; const PUBLIC_KEY = self::KEYS.'/oauth-public.key'; @@ -18,50 +19,32 @@ abstract class PassportTestCase extends TestCase protected function setUp(): void { - parent::setUp(); + $this->afterApplicationCreated(function () { + Passport::loadKeysFrom(self::KEYS); - $this->artisan('migrate:fresh'); + @unlink(self::PUBLIC_KEY); + @unlink(self::PRIVATE_KEY); - Passport::loadKeysFrom(self::KEYS); + $this->artisan('passport:keys'); + }); - @unlink(self::PUBLIC_KEY); - @unlink(self::PRIVATE_KEY); + $this->beforeApplicationDestroyed(function () { + @unlink(self::PUBLIC_KEY); + @unlink(self::PRIVATE_KEY); + }); - $this->artisan('passport:keys'); + parent::setUp(); } - protected function getEnvironmentSetUp($app) + protected function defineEnvironment($app) { $config = $app->make(Repository::class); - $config->set('auth.defaults.provider', 'users'); - - if (($userClass = $this->getUserClass()) !== null) { - $config->set('auth.providers.users.model', $userClass); - } - - $config->set('auth.guards.api', ['driver' => 'passport', 'provider' => 'users']); - - $app['config']->set('database.default', 'testbench'); - - $app['config']->set('database.connections.testbench', [ - 'driver' => 'sqlite', - 'database' => ':memory:', - 'prefix' => '', + $config->set([ + 'auth.defaults.provider' => 'users', + 'auth.providers.users.model' => User::class, + 'auth.guards.api' => ['driver' => 'passport', 'provider' => 'users'], + 'database.default' => 'testing', ]); } - - protected function getPackageProviders($app) - { - return [PassportServiceProvider::class]; - } - - /** - * Get the Eloquent user model class name. - * - * @return string|null - */ - protected function getUserClass() - { - } } diff --git a/workbench/app/Models/User.php b/workbench/app/Models/User.php new file mode 100644 index 000000000..6987bfb38 --- /dev/null +++ b/workbench/app/Models/User.php @@ -0,0 +1,42 @@ + + */ + protected $fillable = [ + 'name', + 'email', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + ]; +} diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php new file mode 100644 index 000000000..db6dfa3df --- /dev/null +++ b/workbench/database/factories/UserFactory.php @@ -0,0 +1,20 @@ + + */ +class UserFactory extends \Orchestra\Testbench\Factories\UserFactory +{ + /** + * The name of the factory's corresponding model. + * + * @var class-string<\TModel> + */ + protected $model = User::class; +} From 30e23b04487ee8733e8301153e8c1051764e0702 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 21 Sep 2023 16:45:07 +0200 Subject: [PATCH 346/353] PHP 8.3 (#1689) --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d61da8afa..67e6f8c65 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,11 +16,13 @@ jobs: strategy: fail-fast: true matrix: - php: ['8.0', 8.1, 8.2] + php: ['8.0', 8.1, 8.2, 8.3] laravel: [9, 10] exclude: - php: '8.0' laravel: 10 + - php: 8.3 + laravel: 9 name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} From 8c52a6958ed27a7b6371336bc3af57922e5c6db3 Mon Sep 17 00:00:00 2001 From: Saleh Hashemi <81674631+salehhashemi1992@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:04:03 +0330 Subject: [PATCH 347/353] update checkout to v4 (#1690) --- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 453d8a6a0..efea805e1 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 67e6f8c65..3ae685569 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 From cece4efda933219002d95f3d5d03509e9ed29a14 Mon Sep 17 00:00:00 2001 From: Amin Date: Mon, 16 Oct 2023 23:34:42 +0330 Subject: [PATCH 348/353] Add return to revokeRefreshTokensByAccessTokenId method (#1693) --- src/RefreshTokenRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php index ded3b0a85..bca0269e3 100644 --- a/src/RefreshTokenRepository.php +++ b/src/RefreshTokenRepository.php @@ -52,11 +52,11 @@ public function revokeRefreshToken($id) * Revokes refresh tokens by access token id. * * @param string $tokenId - * @return void + * @return mixed */ public function revokeRefreshTokensByAccessTokenId($tokenId) { - Passport::refreshToken()->where('access_token_id', $tokenId)->update(['revoked' => true]); + return Passport::refreshToken()->where('access_token_id', $tokenId)->update(['revoked' => true]); } /** From 40173015618f6f81d890d557406855b9a865685b Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 24 Oct 2023 15:40:58 +0000 Subject: [PATCH 349/353] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39040ba31..261339d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.9.1...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.9.2...11.x) + +## [v11.9.2](https://github.com/laravel/passport/compare/v11.9.1...v11.9.2) - 2023-10-16 + +- Add return to revokeRefreshTokensByAccessTokenId method by [@aminkhoshzahmat](https://github.com/aminkhoshzahmat) in https://github.com/laravel/passport/pull/1693 ## [v11.9.1](https://github.com/laravel/passport/compare/v11.9.0...v11.9.1) - 2023-09-01 From cf06f975d340df73857ca341daf38e975d7b134e Mon Sep 17 00:00:00 2001 From: Michael Nabil <46572405+michaelnabil230@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:42:04 +0200 Subject: [PATCH 350/353] [11.x] Named static methods for middleware (#1695) * Standardise of `using` for middleware * Fix * Use `func_get_args` * Formatting * formatting --------- Co-authored-by: Taylor Otwell --- src/Http/Middleware/CheckCredentials.php | 15 +++++++++++++++ src/Http/Middleware/CheckForAnyScope.php | 15 +++++++++++++++ src/Http/Middleware/CheckScopes.php | 15 +++++++++++++++ src/Http/Middleware/CreateFreshApiToken.php | 13 +++++++++++++ tests/Feature/ActingAsTest.php | 15 +++++++++++++++ 5 files changed, 73 insertions(+) diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 4ece0e21c..7c3992f6c 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -39,6 +39,21 @@ public function __construct(ResourceServer $server, TokenRepository $repository) $this->repository = $repository; } + /** + * Specify the scopes for the middleware. + * + * @param array|string $scopes + * @return string + */ + public static function using(...$scopes) + { + if (is_array($scopes[0])) { + return static::class.':'.implode(',', $scopes[0]); + } else { + return static::class.':'.implode(',', $scopes); + } + } + /** * Handle an incoming request. * diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index 9223dfe97..c6409f8fb 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -7,6 +7,21 @@ class CheckForAnyScope { + /** + * Specify the scopes for the middleware. + * + * @param array|string $scopes + * @return string + */ + public static function using(...$scopes) + { + if (is_array($scopes[0])) { + return static::class.':'.implode(',', $scopes[0]); + } else { + return static::class.':'.implode(',', $scopes); + } + } + /** * Handle the incoming request. * diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index af9f8596f..72d699a2e 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -7,6 +7,21 @@ class CheckScopes { + /** + * Specify the scopes for the middleware. + * + * @param array|string $scopes + * @return string + */ + public static function using(...$scopes) + { + if (is_array($scopes[0])) { + return static::class.':'.implode(',', $scopes[0]); + } else { + return static::class.':'.implode(',', $scopes); + } + } + /** * Handle the incoming request. * diff --git a/src/Http/Middleware/CreateFreshApiToken.php b/src/Http/Middleware/CreateFreshApiToken.php index 4ad06b2ec..1429362c8 100644 --- a/src/Http/Middleware/CreateFreshApiToken.php +++ b/src/Http/Middleware/CreateFreshApiToken.php @@ -35,6 +35,19 @@ public function __construct(ApiTokenCookieFactory $cookieFactory) $this->cookieFactory = $cookieFactory; } + /** + * Specify the guard for the middleware. + * + * @param string|null $guard + * @return string + */ + public static function using($guard = null) + { + $guard = is_null($guard) ? '' : ':'.$guard; + + return static::class.$guard; + } + /** * Handle an incoming request. * diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index 031d5abf4..d67f93798 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -47,6 +47,21 @@ public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddleware() $response->assertSee('bar'); } + public function testItCanGenerateDefinitionViaStaticMethod() + { + $signature = (string) CheckScopes::using('admin'); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckScopes:admin', $signature); + + $signature = (string) CheckScopes::using('admin', 'footest'); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckScopes:admin,footest', $signature); + + $signature = (string) CheckForAnyScope::using('admin'); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckForAnyScope:admin', $signature); + + $signature = (string) CheckForAnyScope::using('admin', 'footest'); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckForAnyScope:admin,footest', $signature); + } + public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware() { $this->withoutExceptionHandling(); From 966bc8e477d08c86a11dc4c5a86f85fa0abdb89b Mon Sep 17 00:00:00 2001 From: Michael Nabil <46572405+michaelnabil230@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:16:12 +0200 Subject: [PATCH 351/353] Simplify Conditional Statement (#1696) --- src/Http/Middleware/CheckCredentials.php | 4 ++-- src/Http/Middleware/CheckForAnyScope.php | 4 ++-- src/Http/Middleware/CheckScopes.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 7c3992f6c..5d7d9273f 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -49,9 +49,9 @@ public static function using(...$scopes) { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); - } else { - return static::class.':'.implode(',', $scopes); } + + return static::class.':'.implode(',', $scopes); } /** diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index c6409f8fb..77d9bb1a3 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -17,9 +17,9 @@ public static function using(...$scopes) { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); - } else { - return static::class.':'.implode(',', $scopes); } + + return static::class.':'.implode(',', $scopes); } /** diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index 72d699a2e..fdcead33a 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -17,9 +17,9 @@ public static function using(...$scopes) { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); - } else { - return static::class.':'.implode(',', $scopes); } + + return static::class.':'.implode(',', $scopes); } /** From 6dab7d087ef933d6ca4cc0038d10571d8a886b8a Mon Sep 17 00:00:00 2001 From: driesvints Date: Tue, 7 Nov 2023 17:58:36 +0000 Subject: [PATCH 352/353] Update CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 261339d6d..c2a573833 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v11.9.2...11.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.10.0...11.x) + +## [v11.10.0](https://github.com/laravel/passport/compare/v11.9.2...v11.10.0) - 2023-11-02 + +- [11.x] Named static methods for middleware by [@michaelnabil230](https://github.com/michaelnabil230) in https://github.com/laravel/passport/pull/1695 +- Simplify Conditional Statement by [@michaelnabil230](https://github.com/michaelnabil230) in https://github.com/laravel/passport/pull/1696 ## [v11.9.2](https://github.com/laravel/passport/compare/v11.9.1...v11.9.2) - 2023-10-16 From eb78ec6c192a01fbbe76dd427630a5e500e2486a Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:24:39 +0100 Subject: [PATCH 353/353] Update HasApiTokens.php (#1698) --- src/HasApiTokens.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HasApiTokens.php b/src/HasApiTokens.php index f68bc1ee0..e1479cc2c 100644 --- a/src/HasApiTokens.php +++ b/src/HasApiTokens.php @@ -71,7 +71,7 @@ public function createToken($name, array $scopes = []) /** * Set the current access token for the user. * - * @param \Laravel\Passport\Token|\Laravel\Passport\TransientToken $accessToken + * @param \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null $accessToken * @return $this */ public function withAccessToken($accessToken)

Name