【For Beginners】What to Do When a 419 Error Occurs and POST Fails in Laravel
Thank you for your continued support.
This article contains advertisements that help fund our operations.
Table Of Contents
関連動画
Related Video
This is a video where we actually tried out the content from the article! If anything is unclear in the article, please check out the video.
The video provides further explanations and demonstrations, so it should be helpful.
Subscribe to Our Channel
If you found this video helpful, please consider subscribing to our channel or giving it a thumbs up! It really motivates us to create more content.
Questions and Feedback
If you have any questions or feedback regarding this article or the video, feel free to leave them in the comment section of the video. Your input is greatly appreciated and will help us improve our content in the future!
This time, I’ll be writing about how to handle 419 errors when you try to POST in Laravel, a PHP framework.
⇨ Laravel Articles Table of Contents Here
Environment
MacOS
Laravel 11
When does the 419 error occur?
Laravel comes with several security systems enabled by default.
In regular PHP, you can send a POST request without doing anything special, but Laravel doesn’t allow this.
In fact, sending a POST request without any protection is very bad from a security perspective. Laravel’s default settings prevent POST requests without proper protection.
What we’ll cover today is mainly a protection mechanism using tokens, one of the countermeasures against CSRF (Cross-Site Request Forgery) attacks.
The cause of the 419 error is often due to issues with token setup or the failure of session and token matching.
What is a CSRF Token?
A CSRF token is a string used to determine whether the POST request is from a legitimate website.
In raw PHP, you need to create a system to generate tokens during login and attach them to the session manually.
Then, the token in the session is validated on the server, and the request is blocked if the token is invalid.
In raw PHP, you typically write it like this:
<input type="hidden" name="token" value="Generated Token Here" />
You need to code this manually.
Concrete Solutions
Add @csrf
<form method="POST" action="{{ route('post') }}">
// Add this!!!
@csrf
// Various <input /> tags go here
# </form>
For the most part, forgetting this is the main cause.
Let’s inspect the generated page.
// This is the generated source code
<form method="POST">
<input
type="hidden"
name="_token"
value="vond93ovKGBBXpALpxAu4Ka9V646MW8tm9BvLRFp"
/>
</form>
Without this, a 419 error occurs.
For asynchronous requests like Ajax (within Laravel projects)
First, add a meta tag (common for all)
When building features like a “like” button that sends data using jQuery or similar methods rather than a form, you may not create a form.
In such cases, the steps differ slightly.
First, add this inside the <head> </head>
tags.
<head>
<!-- Other various tags should be here -->
<meta name="csrf-token" content="{{ csrf_token() }}" />
</head>
In JavaScript
function post() {
const url = "/post"
fetch(url, {
method: "POST",
headers: {
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
"Content-Type": "application/json",
},
body: JSON.stringify({
// Your data to send
}),
})
.then(res => {})
.catch(err => console.log(err))
}
Write it like this.
Attach the CSRF token in the headers.
This includes the CSRF token embedded in the meta tag, so it must be written inside the head
section.
In jQuery
let url = '/post';
$.ajax({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
url: url,
type: 'POST',
data: {
}
})
.done(function() {
})
.fail(function(data) {});
}
It looks like this.
When using Axios with Vue, etc.
Since adding the token every time is a hassle, write the code to fetch the CSRF token when you post.
In js/bootstrap.js
window.axios = require("axios")
// Set up CSRF token for axios
window.axios.defaults.headers.common = {
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
}
This setup is necessary. The reason for doing this in bootstrap.js
is that it would be tedious to write it every time, so it’s done in one place.
When using an external JS framework outside of Laravel projects
With Sanctum and Axios
You can retrieve the CSRF token from the server and save it as a cookie named XSRF-TOKEN
. When you make a POST request, you send the CSRF token via the X-XSRF-TOKEN
header, allowing you to protect against CSRF and prevent 419 errors.
During this request, Laravel sets an
XSRF-TOKEN
cookie containing the current CSRF token. This token must be passed with subsequent requests via theX-XSRF-TOKEN
header. Some HTTP client libraries like Axios or Angular's HttpClient do this automatically. If not, you need to manually set theX-XSRF-TOKEN
header with the value of theXSRF-TOKEN
cookie.
Reference: https://readouble.com/laravel/11.x/en/sanctum.html#csrf-protection
In practice, frameworks like Axios and Angular's HttpClient handle this automatically, so there’s not much to do.
To initialize the CSRF token, you need to send a GET request to the following URL (by default). The request timing will vary depending on the service, so consider that.
axios.get("/sanctum/csrf-cookie").then(response => {
// Login process…
})
For separate projects (subdomains), you’ll need to modify the CORS settings.
In the config/cors.php
file, change the settings.
supports_credentials: true
Also, change the settings in resources/js/bootstrap.js
.
axios.defaults.withCredentials = true
axios.defaults.withXSRFToken = true
For completely separate domains, this method doesn’t work
In the case of subdomains, the above implementation works, but when using a completely separate domain as the API server, you need to be careful.
A subdomain is a way to use a domain by adding any string in front, such as:
Main domain: laratech.jp
Subdomain: example.laratech.jp
For subdomains, Axios will set the cookies if you set withCredentials
to true, but for completely separate domains, this method doesn’t work. You’ll need to find another approach.
※ I couldn’t find the source article I read at the time.
※ If you know of other methods or recent updates, please let me know through the contact form (Google Forms, no email input required).
Additional Notes
This CSRF token system is defined in the middleware.
The middleware is used in web.php
which is commonly used for this purpose.
※ Starting from Laravel 11, the following description has been removed, and it is added in bootstrap/app.php
.
In app/Http/Kernel.php
(Laravel 10 and earlier)
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// \App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
Here, it specifies that the middleware VerifyCsrfToken::class
is used.
Let’s remove this.
<form method="POST" action="{{route('post')}}">
<input name="post" />
<button type="submit">post</button>
</form>
We’ve removed @csrf
.
Now, if you submit a POST request, the 419 error no longer occurs.
This means that without this middleware, the CSRF protection doesn't work.
By the way, if you remove the StartSession
middleware, CSRF tokens will no longer be generated, so that is also necessary. Although, you probably won’t need to remove it.
It’s rare to look into the internals of middleware, but it might be interesting to write an article about it if I get the chance.
Summary
There were quite a few digressions, but I wrote an article about how to resolve 419 errors and why this error occurs—a common issue for anyone who has touched Laravel.
Thanks to this error, you won’t be able to implement POST requests without tokens, which is actually reassuring.
Also, the features provided by the framework out of the box are often “must-have” features if you're writing things from scratch, which is why I really appreciate frameworks.
Feel free to leave your thoughts or corrections via the contact form or in the comments section of the YouTube video.