diff --git a/src/Bridge/ScopeRepository.php b/src/Bridge/ScopeRepository.php index 92f7e4ea4..83db68b16 100644 --- a/src/Bridge/ScopeRepository.php +++ b/src/Bridge/ScopeRepository.php @@ -2,12 +2,26 @@ 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 { + /** + * @var ClientRepository + */ + protected $clients; + + /** + * @param ClientRepository $clients + */ + public function __construct(ClientRepository $clients) + { + $this->clients = $clients; + } + /** * {@inheritdoc} */ @@ -31,8 +45,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 8e16fa9c9..693030ee5 100644 --- a/src/Client.php +++ b/src/Client.php @@ -39,6 +39,7 @@ class Client extends Model 'personal_access_client' => 'bool', 'password_client' => 'bool', 'revoked' => 'bool', + 'scopes' => 'array', ]; /** @@ -51,6 +52,17 @@ public function authCodes() return $this->hasMany(Passport::authCodeModel(), 'client_id'); } + /** + * Determine if the client has the given scope. + * + * @param string $id + * @return bool + */ + public function hasScope($id) + { + return ! is_array($this->scopes) || empty($this->scopes) || array_key_exists($id, $this->scopes); + } + /** * Get all of the tokens that belong to the client. * diff --git a/tests/BridgeScopeRepositoryTest.php b/tests/BridgeScopeRepositoryTest.php index d314f1884..5168e20af 100644 --- a/tests/BridgeScopeRepositoryTest.php +++ b/tests/BridgeScopeRepositoryTest.php @@ -5,6 +5,8 @@ use Laravel\Passport\Bridge\Scope; use Laravel\Passport\Bridge\Client; use Laravel\Passport\Bridge\ScopeRepository; +use Laravel\Passport\Client as ClientModel; +use Laravel\Passport\ClientRepository; class BridgeScopeRepositoryTest extends TestCase { @@ -14,7 +16,13 @@ public function test_invalid_scopes_are_removed() 'scope-1' => 'description', ]); - $repository = new ScopeRepository; + $client = Mockery::mock(ClientModel::class); + $client->shouldReceive('hasScope')->andReturn(true); + + $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 @@ -29,7 +37,10 @@ public function test_superuser_scope_cant_be_applied_if_wrong_grant() 'scope-1' => 'description', ]); - $repository = new ScopeRepository; + $clients = Mockery::mock(ClientRepository::class); + $clients->shouldReceive('findActive')->withAnyArgs(); + + $repository = new ScopeRepository($clients); $scopes = $repository->finalizeScopes( [$scope1 = new Scope('*')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 @@ -37,4 +48,26 @@ public function test_superuser_scope_cant_be_applied_if_wrong_grant() $this->assertEquals([], $scopes); } + + public function test_scopes_which_client_cant_issue_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')], 'client_credentials', new Client('id', 'name', 'http://localhost'), 1 + ); + + $this->assertEquals([], $scopes); + } }