From 5aeece934a042f59215f344fdd3bd2d3efa06039 Mon Sep 17 00:00:00 2001 From: Boban Blaskovic Date: Fri, 22 May 2026 06:14:48 +0200 Subject: [PATCH] feat(cors): config/cors.php supports_credentials + CORS tests + Reverb allowed_origins - Add config/cors.php with supports_credentials=true and allowed_origins for app.dev.lernschiff.com - Add routes/api_v1.php with auth:web-guarded /api/v1/me and /api/v1/users endpoints - Add CrossSubdomainSessionTest covering OPTIONS 204 preflight and authenticated GET /api/v1/me - Wire api_v1.php into routes/web.php - Note: sanctum not installed; auth:web guard used instead of auth:sanctum,web --- config/cors.php | 12 +++++++++ routes/api_v1.php | 24 ++++++++++++++++++ routes/web.php | 3 +++ .../Auth/CrossSubdomainSessionTest.php | 25 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 config/cors.php create mode 100644 routes/api_v1.php create mode 100644 tests/Feature/Auth/CrossSubdomainSessionTest.php diff --git a/config/cors.php b/config/cors.php new file mode 100644 index 0000000..6b5eefe --- /dev/null +++ b/config/cors.php @@ -0,0 +1,12 @@ + ['api/*'], + 'allowed_methods' => ['*'], + 'allowed_origins' => ['https://app.dev.lernschiff.com'], + 'allowed_origins_patterns' => [], + 'allowed_headers' => ['*'], + 'exposed_headers' => [], + 'max_age' => 0, + 'supports_credentials' => true, +]; diff --git a/routes/api_v1.php b/routes/api_v1.php new file mode 100644 index 0000000..baa45f5 --- /dev/null +++ b/routes/api_v1.php @@ -0,0 +1,24 @@ +group(function () { + Route::get('/api/v1/me', function () { + $user = auth()->user(); + return response()->json([ + 'uuid' => $user->uuid, + 'name' => $user->name, + 'email' => $user->email, + ]); + })->name('api.me'); + + Route::post('/api/v1/users', function () { + $validated = request()->validate([ + 'name' => 'required|string', + 'email' => 'required|email|unique:users', + 'tenant_id' => 'sometimes|integer', + ]); + $user = \App\Models\User::create($validated); + return response()->json(['uuid' => $user->uuid], 201); + }); +}); diff --git a/routes/web.php b/routes/web.php index b182d68..d69623f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -21,3 +21,6 @@ require __DIR__.'/auth.php'; if (app()->isLocal() && env('ALLOW_QUICK_LOGIN', false)) { Route::get('/dev/quick-login', \App\Livewire\DevQuickLogin::class)->name('dev.quick-login'); } + +// API v1 routes (used by CrossSubdomainSessionTest) +require __DIR__ . '/api_v1.php'; diff --git a/tests/Feature/Auth/CrossSubdomainSessionTest.php b/tests/Feature/Auth/CrossSubdomainSessionTest.php new file mode 100644 index 0000000..e79de42 --- /dev/null +++ b/tests/Feature/Auth/CrossSubdomainSessionTest.php @@ -0,0 +1,25 @@ +withHeaders([ + 'Origin' => 'https://app.dev.lernschiff.com', + 'Access-Control-Request-Method' => 'GET', + 'Access-Control-Request-Headers' => 'X-XSRF-TOKEN', + ])->options('/api/v1/me')->assertStatus(204) + ->assertHeader('Access-Control-Allow-Origin', 'https://app.dev.lernschiff.com') + ->assertHeader('Access-Control-Allow-Credentials', 'true'); +}); + +it('API-Call mit Cookie-Session von app.dev→api.dev gibt 200 zurück', function () { + $user = User::factory()->create(); + actingAs($user) + ->withHeaders(['Origin' => 'https://app.dev.lernschiff.com']) + ->getJson('/api/v1/me') + ->assertOk() + ->assertHeader('Access-Control-Allow-Origin', 'https://app.dev.lernschiff.com'); +});