This is a very common issue when you got the 419 page expired issue in the Laravel application. This happens due to inactivity on the page for a long time. Laravel handles the form request with a CSRF (Cross-Site Request Forgery) token. For every form submit, Laravel generates a new token. This is a secure way to handle the form. Through this token, Laravel detects the form request. If it is coming from outside of the application then it prevents the request. But, this form request detection using CSRF token is checked only on the web applications. If you are creating a REST API in Laravel then that CSRF token won’t work. That’s why we use JWT, Passport, or Sanctum API authentication package.
Today, in this post, we will see how you can resolve this 419 page expired issue. We will see the different routes with parameters or without parameters in POST requests. Let’s have a quick look through a demo application.
Prerequisites
I am assuming, you already have the Laravel application set up. If not then you will require the below configurations for creating a new application in Laravel 8.
- PHP >= 7.3
- MySQL (version > 5)
- Apache/Nginx Server
- VS Code Editor
- Composer
I already have the Laravel application set up. Hence, I am not going to create a new application for now. I will be using that one.
Create a Form in Laravel For Resolving 419 Page Expired Issue
Here, you will require at least a controller and a view. I am not going to store any data in the database. Instead, I will just submit the form and check the response. Here, I will be submitting the form without the CSRF token.
So, firstly, create a view in the resources folder and add the below form snippet. I have created a view with the name create.blade.php.
<!doctype html>
<html lang="en">
<head>
<title> Laravel 419 Page Expired Issue </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container mt-5">
<form action="{{ route('posts.store') }}" method="POST">
<div class="row">
<div class="col-xl-8 col-lg-8 col-sm-12 col-12 m-auto">
<div class="card shadow">
<div class="card-header">
<h4 class="card-title font-weight-bold"> Laravel Form Handling Without CSRF Token </h4>
</div>
<div class="card-body">
<div class="form-group">
<label> Title </label>
<input type="text" class="form-control" name="title" placeholder="Enter the Title">
</div>
<div class="form-group">
<label> Body </label>
<textarea class="form-control" id="description" placeholder="Enter the Description"
name="description"></textarea>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success"> Save </button>
</div>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
In the above form, I haven’t added the CSRF token. So, when this form is submitted, it will throw the 419 page expired error.
How to Implement Sweet Alert in Laravel For Dialog Alert
However, before submitting the form, we will require a controller to handle the form request. Hence, create a controller.
Create a Controller For Form Handling without a CSRF token
You will require a controller in which you will handle the form request. Therefore, come back to the terminal and hit the below command.
php artisan make controller:HomeController
After creating the controller, let’s add the below code.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function index() {
return view('create');
}
public function store(Request $request) {
return $request->all();
}
}
Respectively, add the routes for running your application.
Add Routes in Laravel 8
Open the web.php file and add the below routes.
<?php
use App\Http\Controllers\HomeController;
use Illuminate\Support\Facades\Route;
Route::get('posts', [HomeController::class, 'index'])->name('posts');
Route::post('posts', [HomeController::class, 'store'])->name('posts.store');
Now, run your application and navigate to the above route.
When you will submit this form, you will get the 419 page expired error.
Now, to resolve this issue, you have to exclude the POST request route.
Exclude Route From Verify CSRF Token in Laravel
Navigate to the app/Http/Middleware folder in your Laravel application. You will have the VerifyCsrfToken.php. When you click on that, it will look like shown below.
Currently, the except array is empty. So, you have to pass the route here in the array for which you don’t want CSRF token on the form submission. So, as per the routes, we have the route that is posts for submitting the form defined in the POST method.
Hence, you have to enter the route name in the array as shown below.
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
'posts'
];
}
Check Result of 419 Page Expired Issue
Now, try to submit the form by filling up the details.
After submitting the form, you will get the form data. You can see this in the below result.
This was a simple route with no parameters. However, sometimes you will have a route with parameters defined in the POST method. You will not have the exact name of that parameter because that will be a dynamic value every time. So, let’s see how to handle that type of route without CSRF Token.
Exclude Parameterized Route From CSRF Token
Let’s modify the form action in the view. Here, I added a token in the form action.
@php $token = md5(now()); @endphp
<form action="{{ url('posts', $token) }}" method="POST">
This will generate a token and now, we have the form action with a parameter. But, the form method is POST. Let me show you how this will look. I opened the developer console in the browser and under the elements tab, I have the form action like this.
<!doctype html>
<html lang="en">
<head>
<title> Laravel Page Expired Issue </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container mt-5">
@php $token = md5(now()) @endphp
<form action="{{ url('posts', $token) }}" method="POST">
<div class="row">
<div class="col-xl-8 col-lg-8 col-sm-12 col-12 m-auto">
<div class="card shadow">
<div class="card-header">
<h4 class="card-title font-weight-bold"> Laravel Form Handling Without CSRF Token </h4>
</div>
<div class="card-body">
<div class="form-group">
<label> Title </label>
<input type="text" class="form-control" name="title" placeholder="Enter the Title">
</div>
<div class="form-group">
<label> Body </label>
<textarea class="form-control" id="description" placeholder="Enter the Description"
name="description"></textarea>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success"> Save </button>
</div>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
Now, add one more route below those routes.
Route::post('posts/{token}', [HomeController::class, 'store']);
Let’s try to submit the form again. In the below result, you can see we have the same result of 419 page expired.
Now, let’s exclude this route from verifying CSRF token. Therefore, come back to the same file (VerifyCsrfToken.php) and add the parameterized route as shown below.
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
'posts',
'posts/*'
];
}
In the above array, I have passed 'posts/*'
it means whatever parameter will be after posts, it will exclude it from verifying the token.
Now, check the result by submitting the form.
The result is shown below, you can see the form has been submitted successfully without any token issue.
Similarly, if you have the token before the endpoint then you can pass the ‘*’ before the endpoint. You can have more than one parameter in the form action. You can exclude them in the same way.
Conclusion
We got to know how to resolve the 419 page expired issue in Laravel. We excluded the routes from verifying a CSRF token. You can exclude the parameterized route and non-parameterized route as well. However, it is not recommended in the web application to exclude the route. Generally, the middleware checks the requests if it is coming from outside the application then it asks for a CSRF token. I hope you will find helpful to this post.
Rishi Rastogi says
Thanks for sharing this Amazing Article
Doc Brown says
Thanks, you save my day
Mahesh Narain says
Thank you. The issue was solved.