10

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?

serpentow
  • 186
  • 1
  • 1
  • 8
  • You say it sometimes works sometimes doesn't? Does it fail when you're submitting forms? – Jon White Dec 22 '19 at 23:14
  • It's happens randomly (for example when user try to log out or send a message via form). – serpentow Dec 22 '19 at 23:19
  • I recommend [this article](https://laracasts.com/discuss/channels/laravel/how-can-i-use-csrf-token-with-axios-post-method). – Miron Dec 06 '20 at 07:18

5 Answers5

9

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;
Kevin Lynch
  • 24,427
  • 3
  • 36
  • 37
  • Man, thanks you very much! I lost two days before find your answer! It's WORKS!!!! YEAH! – Rikky Feb 08 '21 at 19:53
  • Give this man a medal! Thank you very much man. – Syno Nov 01 '21 at 21:24
  • 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. – Anoxy Jan 24 '22 at 08:32
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

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.

Khalil Laleh
  • 1,168
  • 10
  • 19
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)
    }
)
eightball
  • 970
  • 8
  • 17
  • 1
    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. – Christian Noel May 26 '22 at 01:29
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.

darioosh10
  • 31
  • 4
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33706160) – Jeremie Jan 30 '23 at 20:01