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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/*'));
|
||||||
|
|||||||
29
tests/Feature/VerifyApiKeyMiddlewareTest.php
Normal file
29
tests/Feature/VerifyApiKeyMiddlewareTest.php
Normal 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);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user