11

I have problem with csrf token in Laravel. Sometimes request POST (via axios) returns 419 code "CSRF token mismatch" but request header contain CSRF and XSRF tokens. Interestingly, it's not happend in incognito mode.

enter image description here

App.blade:

<meta name="csrf-token" content="{{ csrf_token() }}">

bootstrap.js:

window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';


let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

Kernel.php:

    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,
            \App\Http\Middleware\Localization::class,
        ],

I tried to clear cache and config with no results. Any ideas how to fix it?

4
  • You say it sometimes works sometimes doesn't? Does it fail when you're submitting forms? Commented Dec 22, 2019 at 23:14
  • It's happens randomly (for example when user try to log out or send a message via form). Commented Dec 22, 2019 at 23:19
  • I recommend this article. Commented Dec 6, 2020 at 7:18
  • I answered a related question here: stackoverflow.com/a/78369072/10718307 on csrf token mismatch. Commented Apr 22, 2024 at 22:43

6 Answers 6

12

I encountered this issue. The cause was axios headers not being set. Setting them on the axis object within the component also did not resolve the issue. Setting the headers after the object is defined resolved the issue for me.

In your blade view add the following:

<script>window.Laravel = {csrfToken: '{{ csrf_token() }}'}</script>

In your bootstrap.js file, after declaring window.axios = require('axios'); add the following:

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = window.Laravel.csrfToken;
Sign up to request clarification or add additional context in comments.

3 Comments

Man, thanks you very much! I lost two days before find your answer! It's WORKS!!!! YEAH!
Hi there, i encouter the same problem its very sporadic and most of the time the XSRF token is set. However sometimes its not, Kevin, do you know if this approach will conflict with the automatic behavior that axios has of setting XSRF token in lararvel? Thanks.
it's more recomended to use a meta tag in the header : <meta name="csrf-token" content="{{ csrf_token() }}"> and then document.head.querySelector('meta[name="csrf-token"]').content to retrieve the token
3

I've the problem when fecthing data from laravel database (webA) in another website(webB). After some research, I find Laravel already has one solution for this senario: https://laravel.com/docs/5.7/csrf to exclude the route you are visiting from another web. In VerifyCsrfToken.php, exclude the route or page.

<?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
         */
        protected $except = [
            'stripe/*',
            'http://example.com/foo/bar',
            'http://example.com/foo/*',
        ];
    }

1 Comment

This is not a correct approach and it creates security vulnerabilities.
1

Sometimes?! It sounds like a expired token.

When you're working in incognito tabs, you have a fresh token.

Try location.reload() when you're getting 419 error code and everything goes well.

Comments

1

I think the token is expired in your case. You can intercept http status 419 (non standard status defined by Laravel) and reload the page to generate a new CSRF token :

window.axios.interceptors.response.use(
    response => response.data,
    error => {
        if (error.response && 419 === error.response.status) {
            window.location.reload()
        }

        return Promise.reject(error)
    }
)

1 Comment

this is my preferred approach. though i have made slight changes to my Axios.js module since the returned response from laravel isn't an actual error. the best thing about this solution is that you can centralize the token_mismatch issue in a single file like a middleware instead of verifying within every component.
1

Please note that difference between http and https from client to server creates this error as well; Meaning that even if all your configs are ok, if https is not enforced and client uses http, then this error is produced.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-1

On your front-end application startup, always send a request to /sanctum/csrf-cookie, with axios withCredentials:true set up.

Remember to set supports_credentials => true in laravel cors.php config file.

And set SANCTUM_STATEFUL_DOMAINS in .env file correctly,

SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000,127.0.0.1:3000,localhost:3000

It's better to have exact one root domain in front-end and backend.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.