Error 419 Page Expired atau CSRF token mismatch di Laravel adalah salah satu masalah yang paling sering muncul saat submit form. Gejalanya sederhana: form terlihat normal, tetapi ketika tombol submit ditekan, aplikasi justru menampilkan halaman 419 atau request gagal tanpa pesan yang jelas. Dalam banyak kasus nyata, masalahnya bukan pada validasi input, melainkan pada token CSRF, session, konfigurasi domain, atau request AJAX yang tidak mengirim header yang dibutuhkan.
Artikel ini membahas cara cepat menemukan akar masalah error 419 Laravel, beserta contoh implementasi yang benar pada form Blade, AJAX, dan fetch. Fokus utamanya adalah solusi praktis yang bisa langsung dipakai saat form submit Laravel gagal.
Apa Itu Error 419 pada Laravel?
Laravel menggunakan mekanisme CSRF protection untuk melindungi aplikasi dari serangan Cross-Site Request Forgery. Setiap request state-changing seperti POST, PUT, PATCH, atau DELETE harus membawa token yang cocok dengan token yang tersimpan di session pengguna.
Jika token tidak dikirim, nilainya tidak cocok, atau session pengguna tidak tersedia saat request diterima, Laravel akan menolak request tersebut. Penolakan ini sering muncul sebagai:
- 419 Page Expired
- CSRF token mismatch
Secara teknis, masalah ini biasanya melibatkan kombinasi antara middleware web, session, cookie, dan input/header token.
Penyebab Paling Umum Error 419 Laravel
1. Token CSRF tidak dikirim di form
Kasus paling umum adalah form Blade tidak menyertakan directive @csrf. Akibatnya, request POST dikirim tanpa token yang dibutuhkan oleh middleware verifikasi CSRF.
Contoh form Blade yang benar:
<form method="POST" action="{{ route('posts.store') }}">
@csrf
<input type="text" name="title" placeholder="Judul">
<textarea name="content" placeholder="Isi konten"></textarea>
<button type="submit">Simpan</button>
</form>Jika @csrf dihapus atau form dibuat manual tanpa hidden input token, Laravel akan menganggap request tidak valid.
2. Session tidak tersimpan atau tidak terbaca
CSRF token disimpan dan diverifikasi melalui session. Jadi, walaupun token dikirim dari form, request tetap bisa gagal jika session tidak tersimpan dengan benar. Ini sering terjadi pada kondisi berikut:
- Driver session tidak berjalan normal.
- Folder penyimpanan session tidak bisa ditulis.
- Cookie session tidak terkirim ke browser.
- Domain atau subdomain tidak cocok dengan konfigurasi session cookie.
- Request dikirim setelah session kedaluwarsa.
Contoh pengecekan konfigurasi session di file config/session.php atau melalui .env:
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_DOMAIN=null
SESSION_SECURE_COOKIE=false
Jika menggunakan driver file, pastikan direktori penyimpanan session bisa ditulis:
storage/framework/sessionsPada server Linux, masalah izin direktori sering menjadi penyebab tersembunyi. Jika Laravel gagal menyimpan session, token yang dikirim dari browser tidak bisa diverifikasi.
3. Form AJAX atau fetch tidak mengirim header X-CSRF-TOKEN
Pada form biasa, @csrf cukup. Namun pada request AJAX, Anda perlu memastikan token dikirim sebagai header atau body request. Banyak kasus terjadi saat developer berpindah dari form biasa ke JavaScript, tetapi lupa menyertakan token CSRF.
Tambahkan meta tag di layout utama Blade:
<meta name="csrf-token" content="{{ csrf_token() }}">Contoh AJAX dengan jQuery:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
});
$.ajax({
url: '/posts',
method: 'POST',
data: {
title: 'Judul artikel',
content: 'Isi artikel'
},
success: function(response) {
console.log(response);
},
error: function(xhr) {
console.error(xhr.responseText);
}
});Contoh dengan fetch:
fetch('/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'Accept': 'application/json'
},
body: JSON.stringify({
title: 'Judul artikel',
content: 'Isi artikel'
})
})
.then(async response => {
const data = await response.json();
console.log(data);
})
.catch(error => console.error(error));Jika request dikirim menggunakan cookie-based session, perhatikan juga apakah browser benar-benar mengirim cookie session. Untuk skenario tertentu, terutama lintas subdomain atau frontend terpisah, masalahnya bukan hanya token, tetapi cookie session yang tidak ikut terkirim.
4. Domain atau subdomain berbeda
Error 419 sangat sering muncul ketika aplikasi diakses dengan kombinasi domain yang tidak konsisten, misalnya:
- kadang menggunakan
localhost - kadang menggunakan
127.0.0.1 - kadang melalui
app.test - frontend di
admin.example.comtetapi backend diexample.com
Karena session Laravel bergantung pada cookie, perbedaan domain bisa membuat browser tidak mengirim cookie yang sama. Akibatnya, token yang ada di halaman tidak cocok dengan session saat request diterima server.
Hal yang perlu diperiksa:
- Gunakan domain akses yang konsisten.
- Periksa
APP_URLdi.env. - Periksa
SESSION_DOMAINjika menggunakan subdomain. - Jika memakai HTTPS di production, sesuaikan
SESSION_SECURE_COOKIE.
Contoh konfigurasi untuk berbagi cookie antar subdomain:
APP_URL=https://app.example.com
SESSION_DOMAIN=.example.com
SESSION_SECURE_COOKIE=trueTitik di depan .example.com memungkinkan cookie berlaku untuk subdomain. Namun ini harus disesuaikan dengan arsitektur aplikasi Anda. Jika salah konfigurasi, cookie justru tidak terbaca.
5. Cache view atau konfigurasi lama
Terkadang kode sudah benar, tetapi aplikasi masih memakai view lama atau konfigurasi lama yang tersimpan di cache. Ini umum terjadi setelah deploy atau setelah mengubah file environment.
Jalankan perintah berikut untuk membersihkan cache penting Laravel:
php artisan view:clear
php artisan config:clear
php artisan cache:clear
php artisan route:clearJika aplikasi production menggunakan optimasi cache konfigurasi, jangan lupa build ulang sesuai kebutuhan deploy Anda.
Jika Anda baru saja mengubah
.envtetapi perilaku aplikasi tidak berubah, sangat mungkin Laravel masih membaca konfigurasi hasil cache sebelumnya.
Contoh Implementasi yang Benar
Blade form standar
<form method="POST" action="{{ route('profile.update') }}">
@csrf
@method('PUT')
<label for="name">Nama</label>
<input id="name" type="text" name="name" value="{{ old('name', $user->name) }}">
<button type="submit">Update Profil</button>
</form>Untuk method selain GET dan POST, gunakan @method agar Laravel mengenali method spoofing dengan benar.
Layout Blade untuk AJAX
<head>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>Letakkan meta token di layout utama agar semua halaman JavaScript bisa mengakses token yang sama.
Route yang harus berada di middleware web
Pastikan route form Anda memakai middleware web, karena session dan CSRF protection berjalan di sana.
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
Route::middleware('web')->group(function () {
Route::put('/profile', [ProfileController::class, 'update'])->name('profile.update');
});Dalam aplikasi Laravel standar, route di routes/web.php biasanya sudah otomatis berada dalam grup middleware web. Masalah sering muncul ketika route dipindah ke api.php atau didefinisikan di tempat lain tanpa middleware session.
Cara Cek Middleware dan Struktur Request
Pastikan route bukan berada di api.php
Route di routes/api.php secara default ditujukan untuk API stateless dan biasanya tidak menggunakan session berbasis cookie seperti route web. Jika Anda mengirim form Blade ke endpoint API tanpa penyesuaian arsitektur, error 419 sangat mungkin terjadi.
Aturan praktisnya:
- Form Blade klasik: gunakan
routes/web.php. - API token/stateless: gunakan
routes/api.phptanpa bergantung pada CSRF form biasa.
Cek middleware yang aktif
Jika Anda ragu route melewati middleware apa saja, periksa definisi route dan grup middleware di aplikasi. Yang paling penting, request form biasa harus memiliki akses ke session dan verifikasi CSRF.
Hindari solusi instan seperti menonaktifkan middleware CSRF untuk semua route hanya agar form bisa submit. Itu memang bisa menghilangkan error 419, tetapi juga menghilangkan perlindungan keamanan yang memang dibutuhkan untuk request berbasis browser.
Langkah Debug Error 419 Laravel Secara Berurutan
Berikut urutan debug yang praktis agar masalah cepat ditemukan:
- Cek form Blade: pastikan ada
@csrf. - Cek jenis route: pastikan endpoint form ada di
web.php, bukanapi.php. - Cek AJAX/fetch: pastikan header
X-CSRF-TOKENbenar-benar dikirim. - Cek cookie session di browser: buka DevTools, lihat apakah cookie session Laravel terkirim pada request.
- Cek domain yang digunakan: hindari campuran
localhost,127.0.0.1, dan domain custom secara acak. - Cek konfigurasi session: periksa
SESSION_DRIVER,SESSION_DOMAIN,SESSION_SECURE_COOKIE, dan masa hidup session. - Cek permission storage: terutama jika session memakai driver file.
- Bersihkan cache Laravel:
view:clear,config:clear,cache:clear, danroute:clear. - Ulangi request dengan DevTools Network: lihat header request, cookie, dan response detail.
- Periksa apakah session kedaluwarsa: jika form dibiarkan terlalu lama terbuka sebelum submit, token lama bisa menjadi tidak valid.
Apa yang perlu dilihat di DevTools browser?
- Apakah request method sesuai, misalnya
POSTatauPUT. - Apakah request memiliki header
X-CSRF-TOKENuntuk AJAX. - Apakah cookie session ikut dikirim.
- Apakah URL tujuan benar dan tidak berpindah domain.
- Apakah ada redirect yang menyebabkan request berakhir di origin berbeda.
Kesalahan Umum yang Sering Terjadi
- Menulis form manual tetapi lupa
@csrf. - Mengirim request AJAX tanpa header token.
- Menguji aplikasi bergantian antara
localhostdan127.0.0.1. - Meletakkan endpoint submit di route API padahal form berasal dari Blade.
- Mengubah
.envtetapi lupa membersihkan config cache. - Mengatasi masalah dengan menonaktifkan CSRF secara permanen.
Solusi terakhir di atas sebaiknya dihindari kecuali Anda benar-benar memahami konsekuensinya dan route tersebut memang didesain untuk integrasi tertentu yang aman dengan pendekatan lain.
Solusi Cepat Error 419 Laravel
Jika Anda butuh checklist singkat, gunakan urutan ini:
- Tambahkan
@csrfdi semua formPOST/PUT/PATCH/DELETE. - Untuk AJAX, kirim
X-CSRF-TOKENdari meta tag. - Pastikan route ada di
web.php. - Gunakan domain yang konsisten.
- Periksa konfigurasi dan penyimpanan session.
- Bersihkan cache Laravel setelah perubahan konfigurasi.
Dengan pendekatan ini, sebagian besar kasus error 419 Laravel bisa diselesaikan tanpa perlu modifikasi berisiko pada middleware keamanan.
Penutup
Error 419 pada Laravel hampir selalu berkaitan dengan satu dari lima sumber utama: token tidak dikirim, session tidak tersimpan, AJAX tanpa header CSRF, domain/cookie tidak cocok, atau cache lama. Kuncinya bukan sekadar menambahkan @csrf, tetapi memahami bahwa verifikasi token bergantung pada session dan cookie yang valid.
Jika Anda menemui kasus form submit Laravel gagal dengan pesan Page Expired, lakukan debug secara berurutan mulai dari form, route, request header, cookie, session, lalu cache. Dengan cara ini, akar masalah biasanya bisa ditemukan jauh lebih cepat dibanding menebak-nebak konfigurasi.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!