From 45cb7c61bdbcdb2a226a4f65cfe083968acaf103 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Fri, 16 Jan 2026 09:51:53 +0100 Subject: [PATCH 1/2] Add an HTTP Basic Auth example page --- app/Http/Middleware/BasicAuth.php | 29 +++++++++ resources/views/examples/basic-auth.blade.php | 59 +++++++++++++++++++ resources/views/home.blade.php | 25 ++++++++ routes/web.php | 5 ++ tests/Feature/BasicAuthTest.php | 34 +++++++++++ 5 files changed, 152 insertions(+) create mode 100644 app/Http/Middleware/BasicAuth.php create mode 100644 resources/views/examples/basic-auth.blade.php create mode 100644 tests/Feature/BasicAuthTest.php diff --git a/app/Http/Middleware/BasicAuth.php b/app/Http/Middleware/BasicAuth.php new file mode 100644 index 0000000..f18fd8d --- /dev/null +++ b/app/Http/Middleware/BasicAuth.php @@ -0,0 +1,29 @@ +getUser() ?? '') || ! hash_equals($password, $request->getPassword() ?? '')) { + return response('Unauthorized', 401, [ + 'WWW-Authenticate' => 'Basic realm="Protected Area"', + ]); + } + + return $next($request); + } +} diff --git a/resources/views/examples/basic-auth.blade.php b/resources/views/examples/basic-auth.blade.php new file mode 100644 index 0000000..e21b051 --- /dev/null +++ b/resources/views/examples/basic-auth.blade.php @@ -0,0 +1,59 @@ +@use('Illuminate\Support\Str') + + + + + + + Protected Page - Basic Auth Example + + @vite(['resources/css/app.css', 'resources/js/app.js']) + + +
+
+
+ + + +
+

Authentication Successful

+

+ You have successfully authenticated using HTTP Basic Authentication. +

+
+ +
+

Request Details

+ +
+
+ Authenticated User + {{ request()->getUser() }} +
+
+ Authentication Method + HTTP Basic +
+
+ Your IP Address + {{ request()->ip() }} +
+
+ User Agent + {{ Str::limit(request()->userAgent(), 50) }} +
+
+
+ + +
+ + diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 3b7f16f..250e408 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -334,6 +334,14 @@
Test form validation and browser automation
+
+ +
HTTP Basic Auth protected page
+ +
@@ -637,6 +645,23 @@ + + +
+

Test HTTP Basic Authentication

+
+
+
Command
+
+
# Access a page protected by HTTP Basic Auth
+curl -u ohdear:best-monitoring-service-ever {{ url('/basic-auth') }}
+
+
Response
+
# Returns HTML page confirming successful authentication
+# Without credentials, returns 401 Unauthorized
+
+
+
diff --git a/routes/web.php b/routes/web.php index 300cb16..20e0ad0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,7 @@ name('examples.contact'); }); +Route::view('/basic-auth', 'examples.basic-auth') + ->middleware([NoIndexHeader::class, BasicAuth::class]) + ->name('basic-auth'); + Route::get('/sitemap.xml', function () { $baseUrl = config('app.url'); diff --git a/tests/Feature/BasicAuthTest.php b/tests/Feature/BasicAuthTest.php new file mode 100644 index 0000000..249bc87 --- /dev/null +++ b/tests/Feature/BasicAuthTest.php @@ -0,0 +1,34 @@ +get('/basic-auth'); + + $response->assertUnauthorized() + ->assertHeader('WWW-Authenticate', 'Basic realm="Protected Area"'); +}); + +it('returns 401 with wrong credentials', function () { + $response = $this->withHeaders([ + 'Authorization' => 'Basic '.base64_encode('wrong:credentials'), + ])->get('/basic-auth'); + + $response->assertUnauthorized(); +}); + +it('returns 200 with correct credentials', function () { + $response = $this->withHeaders([ + 'Authorization' => 'Basic '.base64_encode('ohdear:best-monitoring-service-ever'), + ])->get('/basic-auth'); + + $response->assertOk() + ->assertViewIs('examples.basic-auth') + ->assertSee('Authentication Successful'); +}); + +it('returns noindex header', function () { + $response = $this->withHeaders([ + 'Authorization' => 'Basic '.base64_encode('ohdear:best-monitoring-service-ever'), + ])->get('/basic-auth'); + + $response->assertHeader('X-Robots-Tag', 'noindex, nofollow'); +}); From fc0e2f01cf922628408ceb0907853b980a29c181 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Fri, 16 Jan 2026 09:53:31 +0100 Subject: [PATCH 2/2] cleanup --- tests/Feature/BasicAuthTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Feature/BasicAuthTest.php b/tests/Feature/BasicAuthTest.php index 249bc87..1903b4a 100644 --- a/tests/Feature/BasicAuthTest.php +++ b/tests/Feature/BasicAuthTest.php @@ -9,7 +9,7 @@ it('returns 401 with wrong credentials', function () { $response = $this->withHeaders([ - 'Authorization' => 'Basic '.base64_encode('wrong:credentials'), + 'Authorization' => 'Basic ' . base64_encode('wrong:credentials'), ])->get('/basic-auth'); $response->assertUnauthorized(); @@ -17,7 +17,7 @@ it('returns 200 with correct credentials', function () { $response = $this->withHeaders([ - 'Authorization' => 'Basic '.base64_encode('ohdear:best-monitoring-service-ever'), + 'Authorization' => 'Basic ' . base64_encode('ohdear:best-monitoring-service-ever'), ])->get('/basic-auth'); $response->assertOk() @@ -27,7 +27,7 @@ it('returns noindex header', function () { $response = $this->withHeaders([ - 'Authorization' => 'Basic '.base64_encode('ohdear:best-monitoring-service-ever'), + 'Authorization' => 'Basic ' . base64_encode('ohdear:best-monitoring-service-ever'), ])->get('/basic-auth'); $response->assertHeader('X-Robots-Tag', 'noindex, nofollow');