From 19ee32af5f9c4b439cf4ee1a992aacbb63f3f0ce Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 13:00:13 +0100 Subject: [PATCH 1/9] Allow overriding the status code for unauthorized requests via config --- config/horizon.php | 15 +++++++++++++++ src/Http/Middleware/Authenticate.php | 22 +++++++++++++++++++++- tests/Feature/AuthTest.php | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/config/horizon.php b/config/horizon.php index 5101f6f0..51089f6f 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -59,6 +59,21 @@ Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' ), + /* + |-------------------------------------------------------------------------- + | Horizon Unauthorized Status Code + |-------------------------------------------------------------------------- + | + | This status code will be used when an unauthorized request has been made. + | For example, you may wish to return a 404 status code to hide that the + | application uses Horizon. + | + | Accepted Status Codes: 403, 404 + | + */ + + 'unauthorized_status' => 403, + /* |-------------------------------------------------------------------------- | Horizon Route Middleware diff --git a/src/Http/Middleware/Authenticate.php b/src/Http/Middleware/Authenticate.php index 4965d115..c837bfaf 100644 --- a/src/Http/Middleware/Authenticate.php +++ b/src/Http/Middleware/Authenticate.php @@ -15,6 +15,26 @@ class Authenticate */ public function handle($request, $next) { - return Horizon::check($request) ? $next($request) : abort(403); + if (! Horizon::check($request)) { + abort($this->statusCode()); + } + + return $next($request); + } + + /** + * Determine the status code returned for unauthorized requests. + * + * @return int + */ + private function statusCode() + { + $code = config('horizon.unauthorized_status'); + + if (! in_array($code, [403, 404])) { + return 403; + } + + return $code; } } diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index 10358459..0f079563 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -6,6 +6,7 @@ use Laravel\Horizon\Http\Middleware\Authenticate; use Laravel\Horizon\Tests\IntegrationTest; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class AuthTest extends IntegrationTest { @@ -59,4 +60,21 @@ function ($value) { } ); } + + public function test_it_can_use_a_custom_status_code(): void + { + $this->expectException(NotFoundHttpException::class); + + $this->app['config']->set('horizon.unauthorized_status', 404); + + $middleware = new Authenticate; + + $middleware->handle( + new class { + }, + function ($value) { + return 'response'; + } + ); + } } From 3572cdcce67d36509ffdee7ad8b3fe03e8248d41 Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 13:11:05 +0100 Subject: [PATCH 2/9] Update tests --- tests/Feature/AuthTest.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index 0f079563..5a0cf34a 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -61,7 +61,7 @@ function ($value) { ); } - public function test_it_can_use_a_custom_status_code(): void + public function test_authentication_middleware_responds_with_custom_status_code(): void { $this->expectException(NotFoundHttpException::class); @@ -77,4 +77,21 @@ function ($value) { } ); } + + public function test_authentication_middleware_defaults_unsupported_status_codes_to_403(): void + { + $this->expectException(HttpException::class); + + $this->app['config']->set('horizon.unauthorized_status', 201); + + $middleware = new Authenticate; + + $middleware->handle( + new class { + }, + function ($value) { + return 'response'; + } + ); + } } From c16e2ab0ecdd9b041c37d4c210759c334ea69dea Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 14:44:55 +0100 Subject: [PATCH 3/9] Use custom unauthorized exception instead of config value --- config/horizon.php | 15 --------- src/Exceptions/UnauthorizedException.php | 10 ++++++ src/Http/Middleware/Authenticate.php | 19 ++---------- tests/Feature/AuthTest.php | 39 ++---------------------- 4 files changed, 15 insertions(+), 68 deletions(-) create mode 100644 src/Exceptions/UnauthorizedException.php diff --git a/config/horizon.php b/config/horizon.php index 51089f6f..5101f6f0 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -59,21 +59,6 @@ Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' ), - /* - |-------------------------------------------------------------------------- - | Horizon Unauthorized Status Code - |-------------------------------------------------------------------------- - | - | This status code will be used when an unauthorized request has been made. - | For example, you may wish to return a 404 status code to hide that the - | application uses Horizon. - | - | Accepted Status Codes: 403, 404 - | - */ - - 'unauthorized_status' => 403, - /* |-------------------------------------------------------------------------- | Horizon Route Middleware diff --git a/src/Exceptions/UnauthorizedException.php b/src/Exceptions/UnauthorizedException.php new file mode 100644 index 00000000..67bc624e --- /dev/null +++ b/src/Exceptions/UnauthorizedException.php @@ -0,0 +1,10 @@ +statusCode()); + throw new UnauthorizedException(); } return $next($request); } - - /** - * Determine the status code returned for unauthorized requests. - * - * @return int - */ - private function statusCode() - { - $code = config('horizon.unauthorized_status'); - - if (! in_array($code, [403, 404])) { - return 403; - } - - return $code; - } } diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index 5a0cf34a..f1ee0e5c 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -2,6 +2,7 @@ namespace Laravel\Horizon\Tests\Feature; +use Laravel\Horizon\Exceptions\UnauthorizedException; use Laravel\Horizon\Horizon; use Laravel\Horizon\Http\Middleware\Authenticate; use Laravel\Horizon\Tests\IntegrationTest; @@ -42,9 +43,9 @@ function ($value) { $this->assertSame('response', $response); } - public function test_authentication_middleware_responds_with_403_on_failure() + public function test_authentication_middleware_throws_on_failure() { - $this->expectException(HttpException::class); + $this->expectException(UnauthorizedException::class); Horizon::auth(function () { return false; @@ -60,38 +61,4 @@ function ($value) { } ); } - - public function test_authentication_middleware_responds_with_custom_status_code(): void - { - $this->expectException(NotFoundHttpException::class); - - $this->app['config']->set('horizon.unauthorized_status', 404); - - $middleware = new Authenticate; - - $middleware->handle( - new class { - }, - function ($value) { - return 'response'; - } - ); - } - - public function test_authentication_middleware_defaults_unsupported_status_codes_to_403(): void - { - $this->expectException(HttpException::class); - - $this->app['config']->set('horizon.unauthorized_status', 201); - - $middleware = new Authenticate; - - $middleware->handle( - new class { - }, - function ($value) { - return 'response'; - } - ); - } } From 821afff09b710aba1e3e97d9b0b7143244273e34 Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 14:45:21 +0100 Subject: [PATCH 4/9] Remove unused imports --- tests/Feature/AuthTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index f1ee0e5c..89646dd2 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -6,8 +6,6 @@ use Laravel\Horizon\Horizon; use Laravel\Horizon\Http\Middleware\Authenticate; use Laravel\Horizon\Tests\IntegrationTest; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class AuthTest extends IntegrationTest { From ecd5d9e782bd5a08179b5f790d7b7a12e15e5a3e Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 15:06:24 +0100 Subject: [PATCH 5/9] Use custom exception --- src/Exceptions/UnauthorizedException.php | 4 ++-- src/Http/Middleware/Authenticate.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Exceptions/UnauthorizedException.php b/src/Exceptions/UnauthorizedException.php index 67bc624e..c8730aec 100644 --- a/src/Exceptions/UnauthorizedException.php +++ b/src/Exceptions/UnauthorizedException.php @@ -2,9 +2,9 @@ namespace Laravel\Horizon\Exceptions; -use RuntimeException; +use Symfony\Component\HttpKernel\Exception\HttpException; -class UnauthorizedException extends RuntimeException +class UnauthorizedException extends HttpException { // } diff --git a/src/Http/Middleware/Authenticate.php b/src/Http/Middleware/Authenticate.php index 15b5dc03..52340854 100644 --- a/src/Http/Middleware/Authenticate.php +++ b/src/Http/Middleware/Authenticate.php @@ -17,7 +17,7 @@ class Authenticate public function handle($request, $next) { if (! Horizon::check($request)) { - throw new UnauthorizedException(); + throw new UnauthorizedException(401); } return $next($request); From 2b6ad494cb8d957d8bbf78c7db9a8dae73b4a1eb Mon Sep 17 00:00:00 2001 From: Joel Butcher <> Date: Tue, 29 Aug 2023 15:47:52 +0100 Subject: [PATCH 6/9] Use original error code and rename exception --- .../{UnauthorizedException.php => ForbiddenException.php} | 2 +- src/Http/Middleware/Authenticate.php | 4 ++-- tests/Feature/AuthTest.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Exceptions/{UnauthorizedException.php => ForbiddenException.php} (69%) diff --git a/src/Exceptions/UnauthorizedException.php b/src/Exceptions/ForbiddenException.php similarity index 69% rename from src/Exceptions/UnauthorizedException.php rename to src/Exceptions/ForbiddenException.php index c8730aec..bbf38b88 100644 --- a/src/Exceptions/UnauthorizedException.php +++ b/src/Exceptions/ForbiddenException.php @@ -4,7 +4,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; -class UnauthorizedException extends HttpException +class ForbiddenException extends HttpException { // } diff --git a/src/Http/Middleware/Authenticate.php b/src/Http/Middleware/Authenticate.php index 52340854..bbfc9aa3 100644 --- a/src/Http/Middleware/Authenticate.php +++ b/src/Http/Middleware/Authenticate.php @@ -2,7 +2,7 @@ namespace Laravel\Horizon\Http\Middleware; -use Laravel\Horizon\Exceptions\UnauthorizedException; +use Laravel\Horizon\Exceptions\ForbiddenException; use Laravel\Horizon\Horizon; class Authenticate @@ -17,7 +17,7 @@ class Authenticate public function handle($request, $next) { if (! Horizon::check($request)) { - throw new UnauthorizedException(401); + throw new ForbiddenException(403); } return $next($request); diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index 89646dd2..e0b0491f 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -2,7 +2,7 @@ namespace Laravel\Horizon\Tests\Feature; -use Laravel\Horizon\Exceptions\UnauthorizedException; +use Laravel\Horizon\Exceptions\ForbiddenException; use Laravel\Horizon\Horizon; use Laravel\Horizon\Http\Middleware\Authenticate; use Laravel\Horizon\Tests\IntegrationTest; @@ -43,7 +43,7 @@ function ($value) { public function test_authentication_middleware_throws_on_failure() { - $this->expectException(UnauthorizedException::class); + $this->expectException(ForbiddenException::class); Horizon::auth(function () { return false; From 9fef5077aaea2132c67292d1243a9000b8a6dd69 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Wed, 30 Aug 2023 10:09:58 +0800 Subject: [PATCH 7/9] wip Signed-off-by: Mior Muhammad Zaki --- src/Exceptions/ForbiddenException.php | 10 +++++++++- src/Http/Middleware/Authenticate.php | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Exceptions/ForbiddenException.php b/src/Exceptions/ForbiddenException.php index bbf38b88..95d968f5 100644 --- a/src/Exceptions/ForbiddenException.php +++ b/src/Exceptions/ForbiddenException.php @@ -6,5 +6,13 @@ class ForbiddenException extends HttpException { - // + /** + * Make a new exception + * + * @return static + */ + public static function make() + { + return new static(403); + } } diff --git a/src/Http/Middleware/Authenticate.php b/src/Http/Middleware/Authenticate.php index bbfc9aa3..e88ed236 100644 --- a/src/Http/Middleware/Authenticate.php +++ b/src/Http/Middleware/Authenticate.php @@ -17,7 +17,7 @@ class Authenticate public function handle($request, $next) { if (! Horizon::check($request)) { - throw new ForbiddenException(403); + throw ForbiddenException::make(); } return $next($request); From d30b615972968f8ee4fe4001bbddfe9e9ab4fca2 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Wed, 30 Aug 2023 10:10:37 +0800 Subject: [PATCH 8/9] wip Signed-off-by: Mior Muhammad Zaki --- src/Exceptions/ForbiddenException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/ForbiddenException.php b/src/Exceptions/ForbiddenException.php index 95d968f5..85f65347 100644 --- a/src/Exceptions/ForbiddenException.php +++ b/src/Exceptions/ForbiddenException.php @@ -7,7 +7,7 @@ class ForbiddenException extends HttpException { /** - * Make a new exception + * Make a new exception. * * @return static */ From d009a1635a295cacf4093f6342d15175ec96e266 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 30 Aug 2023 09:01:46 -0500 Subject: [PATCH 9/9] formatting --- src/Exceptions/ForbiddenException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/ForbiddenException.php b/src/Exceptions/ForbiddenException.php index 85f65347..9718aee6 100644 --- a/src/Exceptions/ForbiddenException.php +++ b/src/Exceptions/ForbiddenException.php @@ -7,7 +7,7 @@ class ForbiddenException extends HttpException { /** - * Make a new exception. + * Create a new exception instance. * * @return static */