Aplikasi web modern berbasis Inertia.js sering mengalami kegagalan saat mengarahkan pengguna ke layanan pihak ketiga, seperti OAuth (Google, GitHub) atau payment gateway (Stripe Checkout, Midtrans). Respons backend standar berupa HTTP 302 Redirect menyebabkan browser mencoba melakukan cross-origin fetch secara transparan, yang berujung pada error CORS di konsol browser.
Akar Masalah: Mengapa HTTP 302 Gagal pada Inertia
Inertia.js bekerja dengan membungkus semua interaksi HTTP (seperti submit form atau klik tautan) ke dalam request AJAX via axios atau fetch dengan menyertakan header X-Inertia: true. Ketika controller backend mengembalikan redirect HTTP standar:
// SALAH: Memicu CORS error pada request Inertia
return redirect()->away('https://accounts.google.com/o/oauth2/v2/auth?...');Browser memproses respons HTTP 302 tersebut secara internal di level network XHR. Browser mencoba melakukan request AJAX lanjutan ke URL tujuan (domain eksternal). Karena domain eksternal tidak menyertakan header Access-Control-Allow-Origin untuk domain aplikasi Anda, browser memblokir respons tersebut dengan pesan kesalahan CORS:
Access to XMLHttpRequest at 'https://accounts.google.com/...' from origin 'https://myapp.test' has been blocked by CORS policy.
Protokol Inertia: HTTP 409 dan Header X-Inertia-Location
Untuk menghindari batasan browser XHR, Inertia menetapkan kontrak protokol khusus untuk redirect eksternal:
- Backend tidak boleh mengirim HTTP 301/302 jika request berasal dari Inertia.
- Backend harus mengirim respons HTTP 409 Conflict.
- Backend wajib menyertakan header
X-Inertia-Location: <target_url>.
Ketika client-side adapter Inertia mendeteksi respons HTTP 409 dengan header tersebut, adapter langsung menghentikan pipeline AJAX dan mengeksekusi navigasi penuh (hard redirect) di tingkat browser menggunakan window.location.href = url.
Implementasi Backend di Laravel
Laravel menyediakan helper bawaan Inertia::location() yang secara otomatis mendeteksi apakah request berasal dari Inertia atau request HTTP reguler.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Laravel\Socialite\Facades\Socialite;
use Symfony\Component\HttpFoundation\Response;
class OAuthController extends Controller
{
public function redirect(string $provider): Response
{
$targetUrl = Socialite::driver($provider)
->stateless() // Gunakan stateless jika tidak mengikat state ke session PHP standard
->redirect()
->getTargetUrl();
// ponytail: Gunakan Inertia::location() untuk hard redirect.
// Jika request non-Inertia, method ini otomatis fallback ke standard 302 redirect.
return Inertia::location($targetUrl);
}
}Handling di Sisi Frontend
Inertia menangani respons X-Inertia-Location secara otomatis di balik layar. Anda tidak perlu menambahkan custom handler pada pemanggilan router.post atau form helper.
<script setup>
import { useForm } from '@inertiajs/vue3';
const form = useForm({});
const initiateOAuth = () => {
// Inertia secara otomatis membaca HTTP 409 + X-Inertia-Location
// dan memicu window.location.href ke endpoint OAuth provider.
form.post('/auth/google/redirect');
};
</script>
<template>
<button @click="initiateOAuth" :disabled="form.processing">
Login with Google
</button>
</template>Jika menggunakan tag tautan HTML murni tanpa intervensi Inertia, Anda cukup menonaktifkan interceptor dengan menambahkan atribut standar browser atau tidak menggunakan komponen <Link>:
<!-- Alternatif: Gunakan tag <a> reguler tanpa atribut data-inertia -->
<a href="/auth/google/redirect">Login with Google</a>Mitigasi Masalah Session State (SameSite Cookie)
Salah satu kendala umum pasca-redirect dari domain pihak ketiga kembali ke aplikasi Anda (callback URL) adalah hilangnya session Laravel (error InvalidStateException pada Laravel Socialite).
Ketika pihak ketiga mengirim redirect via HTTP GET kembali ke aplikasi Anda, browser menerapkan aturan cookie cross-site. Periksa konfigurasi pada config/session.php:
// config/session.php
'same_site' => 'lax', // JANGAN gunakan 'strict' jika menerima inbound redirect dari OAuthNilai strict akan mencegah browser mengirim session cookie saat navigasi berasal dari domain eksternal. Nilai lax mengizinkan cookie dikirim pada navigasi top-level dengan method GET, mempertahankan session pengguna.
Unit Testing Redirect Eksternal di PHPUnit
Untuk memastikan endpoint backend merespons sesuai protokol Inertia, tulis integration test yang memverifikasi kode status dan header HTTP:
<?php
namespace Tests\Feature\Auth;
use Tests\TestCase;
class OAuthRedirectTest extends TestCase
{
public function test_inertia_request_receives_409_with_location_header(): void
{
$response = $this->withHeaders([
'X-Inertia' => 'true',
])->post('/auth/google/redirect');
$response->assertStatus(409);
$response->assertHeader('X-Inertia-Location');
$location = $response->headers->get('X-Inertia-Location');
$this->assertStringStartsWith('https://accounts.google.com', $location);
}
public function test_standard_request_receives_302_redirect(): void
{
// Request biasa tanpa header X-Inertia harus tetap fallback ke 302
$response = $this->get('/auth/google/redirect');
$response->assertStatus(302);
}
}
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!