From 3566b17befc0c14632fb16509a1c1bfe611d93ac Mon Sep 17 00:00:00 2001 From: Robert Marney Date: Tue, 16 Jan 2024 07:50:57 -0700 Subject: [PATCH] Allow configuration of login route via config --- config/passport.php | 12 ++++ src/Exceptions/AuthenticationException.php | 4 ++ .../Controllers/AuthorizationController.php | 2 +- .../Middleware/CheckClientCredentials.php | 2 +- .../CheckClientCredentialsForAnyScope.php | 3 +- src/Http/Middleware/CheckCredentials.php | 2 +- src/Http/Middleware/CheckForAnyScope.php | 2 +- src/Http/Middleware/CheckScopes.php | 2 +- tests/Unit/AuthorizationControllerTest.php | 62 +++++++++++++++++++ 9 files changed, 85 insertions(+), 6 deletions(-) diff --git a/config/passport.php b/config/passport.php index 06053cd12..bcf6c6d70 100644 --- a/config/passport.php +++ b/config/passport.php @@ -15,6 +15,18 @@ 'guard' => 'web', + /* + |-------------------------------------------------------------------------- + | Login Route + |-------------------------------------------------------------------------- + | + | Here you may specify which route Passport will redirect Unauthenticated + | users to. + | + */ + + 'login_route' => route('login'), + /* |-------------------------------------------------------------------------- | Encryption Keys diff --git a/src/Exceptions/AuthenticationException.php b/src/Exceptions/AuthenticationException.php index 75ec03dbf..09f766e55 100644 --- a/src/Exceptions/AuthenticationException.php +++ b/src/Exceptions/AuthenticationException.php @@ -6,4 +6,8 @@ class AuthenticationException extends Exception { + static function make(): self + { + return new self(redirectTo: config('passport.login_route', route('login'))); + } } diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 38942232b..a0e03158b 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -215,6 +215,6 @@ protected function promptForLogin($request) { $request->session()->put('promptedForLogin', true); - throw new AuthenticationException; + throw AuthenticationException::make(); } } diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index 25644dd24..a59fc8bbc 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -18,7 +18,7 @@ class CheckClientCredentials extends CheckCredentials protected function validateCredentials($token) { if (! $token) { - throw new AuthenticationException; + throw AuthenticationException::make(); } } diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index 8da32bf19..8539cbd65 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Http\Middleware; +use Illuminate\Support\Facades\Auth; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; @@ -18,7 +19,7 @@ class CheckClientCredentialsForAnyScope extends CheckCredentials protected function validateCredentials($token) { if (! $token) { - throw new AuthenticationException; + throw AuthenticationException::make(); } } diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 5d7d9273f..fc6c5186e 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -76,7 +76,7 @@ public function handle($request, Closure $next, ...$scopes) try { $psr = $this->server->validateAuthenticatedRequest($psr); } catch (OAuthServerException $e) { - throw new AuthenticationException; + throw AuthenticationException::make(); } $this->validate($psr, $scopes); diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index 77d9bb1a3..bce77c653 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -35,7 +35,7 @@ public static function using(...$scopes) public function handle($request, $next, ...$scopes) { if (! $request->user() || ! $request->user()->token()) { - throw new AuthenticationException; + throw AuthenticationException::make(); } foreach ($scopes as $scope) { diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index fdcead33a..6726d3478 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -35,7 +35,7 @@ public static function using(...$scopes) public function handle($request, $next, ...$scopes) { if (! $request->user() || ! $request->user()->token()) { - throw new AuthenticationException; + throw AuthenticationException::make(); } foreach ($scopes as $scope) { diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index fe6e7f3ea..9e6836759 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -343,6 +343,16 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); + // Mock the URL generator... + $urlGenerator = m::mock(\Illuminate\Contracts\Routing\UrlGenerator::class); + app()->instance('url', $urlGenerator); + $urlGenerator->shouldReceive('route')->with('login', [], true)->andReturn('login'); + + // Mock the config class... + $config = m::mock('alias:config'); + $config->shouldReceive('get')->with('passport.login_route', 'login')->andReturn('login'); + app()->instance('config', $config); + $controller = new AuthorizationController($server, $guard, $response); $guard->shouldReceive('guest')->andReturn(false); @@ -370,6 +380,16 @@ public function test_user_should_be_authenticated() { $this->expectException(AuthenticationException::class); + // Mock the URL generator... + $urlGenerator = m::mock(\Illuminate\Contracts\Routing\UrlGenerator::class); + app()->instance('url', $urlGenerator); + $urlGenerator->shouldReceive('route')->with('login', [], true)->andReturn('login'); + + // Mock the config class... + $config = m::mock('alias:config'); + $config->shouldReceive('get')->with('passport.login_route', 'login')->andReturn('login'); + app()->instance('config', $config); + $server = m::mock(AuthorizationServer::class); $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); @@ -393,4 +413,46 @@ public function test_user_should_be_authenticated() m::mock(ServerRequestInterface::class), $request, $clients, $tokens ); } + + public function test_user_redirected_to_configured_login_url_when_unauthenticated() + { + $this->expectException(AuthenticationException::class); + + // Mock the URL generator... + $urlGenerator = m::mock(\Illuminate\Contracts\Routing\UrlGenerator::class); + app()->instance('url', $urlGenerator); + $urlGenerator->shouldReceive('route')->with('login', [], true)->andReturn('custom_login'); + + // Mock the config class + $config = m::mock('alias:config'); + $config->shouldReceive('get')->with('passport.login_route', 'custom_login')->andReturn('custom_login_uri'); + app()->instance('config', $config); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(true); + $server->shouldReceive('validateAuthorizationRequest')->once(); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->with('promptedForLogin', true)->once(); + $request->shouldReceive('get')->with('prompt')->andReturn(null); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + + try { + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens + ); + } catch (AuthenticationException $exception) { + $this->assertEquals('custom_login_uri', $exception->redirectTo()); + + throw $exception; + } + } }