What is the 419/page expired error and its solution in Laravel?

widget

Laravel is a PHP framework that is very much concerned about security, and as such, it uses tokens out of the box to verify that the application sending the request at a particular time is not compromised by hijackers. Laravel uses the CSRF token to actualize this simple check.

The 419/page expired error

That being said, you can get a 419/page expired error for two reasons:

  1. The page takes too long to send its request and, as such, the token expires (page expired).

  2. You probably did not add the @csrf blade code with your form, so the token expected from your form is not present.

Solutions

  • Solution for reason 1: Refresh the page.

  • Solution for reason 2: Add @csrf just beneath the form, like so:

<form action="/action" method="post">
@csrf

// your inputs goes here

</form

Here is another solution for this type of error in a Laravel application, we can disable CSRF protection for certain routes by modifying the VerifyCsrfToken middleware. By default, the VerifyCsrfToken middleware checks that a CSRF token is present and valid for all non-GET requests to the application, in order to prevent cross-site request forgery attacks. However, you may want to disable CSRF protection for specific routes, such as receiving requests from third-party APIs or other trusted sources. To disable CSRF protection for specific routes, you can modify the $except property of the VerifyCsrfToken middleware. This property is an array of route patterns that should be excluded from CSRF protection. Here’s an example of how to disable CSRF protection for a specific route:

To disable CSRF protection for specific routes, you can modify the $except property of the VerifyCsrfToken middleware. This property is an array of route patterns that should be excluded from CSRF protection.

Here’s an example of how to disable CSRF protection for a specific route:

namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
protected $except = [
'webhook/*', // Disable CSRF protection for routes matching the "webhook/*" pattern
];
}

In this example, any route that matches the webhook/* pattern will not be subject to CSRF protection.

Note: Disabling CSRF protection can be a security risk, so you should only do it for routes that are guaranteed to be secure and trusted.

Live demonstration

To proceed, begin by clicking the "Run" button in the provided widget and completing the form. Following submission, you may encounter a 419 page expired error, which is expected. In the subsequent widget, we'll explore the solution to this issue in the next widget.

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:b7+51jaHTkygv1leS/H9RI9zhkUD5DJXrNF7QnTnt9Y=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=project_name
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Basic Laravel application

Now let's fix this by adding @csrf and then again fill the form.

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:b7+51jaHTkygv1leS/H9RI9zhkUD5DJXrNF7QnTnt9Y=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=project_name
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Solution

If you follow the solutions above, you will not have issues with the 419 error on your application or a third-party application because you now know that you simply need to refresh the page.

Free Resources