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 + )); + } }