feat: allow Sanctum-authenticated sessions through VerifyApiKey middleware

Enables stateful API via Sanctum so the Vue SPA can call /api/* routes
using cookie auth, without requiring an X-Api-Key header.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ovidiu U
2026-04-10 17:56:14 +01:00
parent 8cf5e210de
commit acaa791eda
3 changed files with 36 additions and 2 deletions

View File

@@ -4,9 +4,10 @@ namespace App\Http\Middleware;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
class VerifyApiKey final class VerifyApiKey
{ {
/** /**
* Handle an incoming request. * Handle an incoming request.
@@ -15,6 +16,10 @@ class VerifyApiKey
*/ */
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
if (Auth::guard('sanctum')->check()) {
return $next($request);
}
if ($request->header('X-Api-Key') !== config('app.api_secret_key')) { if ($request->header('X-Api-Key') !== config('app.api_secret_key')) {
abort(403); abort(403);
} }

View File

@@ -13,7 +13,7 @@ return Application::configure(basePath: dirname(__DIR__))
health: '/up', health: '/up',
) )
->withMiddleware(function (Middleware $middleware): void { ->withMiddleware(function (Middleware $middleware): void {
// $middleware->statefulApi();
}) })
->withExceptions(function (Exceptions $exceptions): void { ->withExceptions(function (Exceptions $exceptions): void {
$exceptions->shouldRenderJsonWhen(fn (Request $request) => $request->is('api/*')); $exceptions->shouldRenderJsonWhen(fn (Request $request) => $request->is('api/*'));

View File

@@ -0,0 +1,29 @@
<?php
use App\Models\User;
use Laravel\Sanctum\Sanctum;
it('rejects requests without api key or sanctum session', function (): void {
$response = $this->getJson('/api/stations?postcode=SW1A1AA&fuel_type=petrol');
$response->assertStatus(403);
});
it('accepts requests with valid api key', function (): void {
config(['app.api_secret_key' => 'test-secret']);
$response = $this->withHeader('X-Api-Key', 'test-secret')
->getJson('/api/stations?postcode=SW1A1AA&fuel_type=petrol');
// 403 would mean middleware rejected — any other status means it passed through
expect($response->status())->not->toBe(403);
});
it('accepts requests from sanctum authenticated users', function (): void {
$user = User::factory()->create();
Sanctum::actingAs($user);
$response = $this->getJson('/api/stations?postcode=SW1A1AA&fuel_type=petrol');
expect($response->status())->not->toBe(403);
});