Solving Laravel 12 + Livewire 419 "Page Expired" in an iframe
After upgrading one of our projects to Laravel 12 with Livewire, I encountered a frustrating issue: every Livewire request inside an iframe returned 419 Page Expired.
The architecture looks like this:
Website (Laravel)
│
│ iframe
▼
UUI (Laravel + Livewire)
https://uui-v5.local/forms/...
The public website embeds the UUI application, where users can complete and submit forms.
The symptom
The form loaded successfully, but as soon as the user interacted with it, Livewire sent a request to:
POST /livewire/update
Laravel responded with:
419 Page Expired
At first, I temporarily "fixed" it by excluding Livewire from CSRF validation:
$middleware->validateCsrfTokens(except: [
'livewire/*',
]);
Although this worked, it wasn't the correct solution because it disabled CSRF protection for every Livewire request.
The real problem
The issue wasn't Livewire.
It wasn't Laravel.
It wasn't even CSRF.
The real problem was that the browser wasn't sending the session cookie.
While debugging, I noticed Chrome showed:
Not Secure
https://uui-v5.local
Since my local HTTPS certificate wasn't trusted, the browser didn't consistently treat the connection as secure. As a result:
the session cookie wasn't available inside the iframe,
Laravel couldn't restore the user's session,
the CSRF token couldn't be validated,
every Livewire request failed with a 419 response.
The fix
After configuring HTTPS correctly for my local environment and trusting the certificate, I updated the session configuration:
APP_URL=https://uui-v5.local
SESSION_DOMAIN=null
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=none
Because the application is embedded in an iframe on another origin, SESSION_SAME_SITE=none and SESSION_SECURE_COOKIE=true are required.
After clearing the configuration cache:
php artisan optimize:clear
the browser began sending the laravel_session and XSRF-TOKEN cookies correctly.
Livewire started working immediately.
CSRF configuration
Once the session issue was fixed, I removed the unnecessary CSRF exclusions:
$middleware->validateCsrfTokens(except: [
'stripe/webhook',
]);
I no longer needed:
'livewire/*',
'form/*',
Key takeaway
A public form does not mean you should disable CSRF protection.
Laravel can generate a session and CSRF token for anonymous users just as it does for authenticated users.
Only endpoints that receive requests from external systems—such as Stripe webhooks, GitHub webhooks, or other third-party callbacks—should typically be excluded from CSRF validation.
Debugging checklist
If you encounter a 419 Page Expired error with Livewire, check the following before disabling CSRF:
Is the application using HTTPS?
Is the HTTPS certificate trusted?
Does
POST /livewire/updateinclude thelaravel_sessioncookie?Does the request include the
XSRF-TOKENcookie?Are
SESSION_SECURE_COOKIEandSESSION_SAME_SITEconfigured correctly?If using an iframe, are third-party cookies being blocked by the browser?
Final thoughts
If excluding livewire/* "fixes" a 419 error, there's a good chance the real issue is your session or cookie configuration, not Livewire itself.
Fix the underlying session problem first, and you can keep Laravel's built-in CSRF protection fully enabled—exactly as intended.
Comments
Post a Comment