Laravel 7 Vue 2 Sanctum Login Error 419; CSRF Token Mismatch

Afiq Rosli picture Afiq Rosli · Aug 21, 2020 · Viewed 8.4k times · Source

I am using Laravel with default integration of Vue (Not separate project using Vue CLI). I'm trying to authenticate a user but it always shows 419 error. I have included the csrf token to the Axios's header but it still provides mismatch error.

bootstrap.js

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.withCredentials = true;
window.axios.defaults.baseURL = "http://localhost:8000/";
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');

Kernel.php

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
]

cors.php

'paths' => [
    'api/*',
    '/login',
    '/logout',
    '/sanctum/csrf-cookie'
],
.
.
.
'supports_credentials' => true,

web.php

Route::get('/{any?}', function() {
    return view('welcome');
});

Route::post('/login', 'AuthController@login');
Route::post('/logout', 'AuthController@logout');

LoginModal.vue

<template>
    <form @submit.prevent="submit" method="POST">
        <input type="text" class="form-control" placeholder="Email" v-model="email" />
        <input
            type="password"
            class="form-control"
            placeholder="Password"
            v-model="password"
        />

        <button>SIGN IN</button>
    </form>
</template>

<script>
import { mapActions } from 'vuex'

export default {
    data() {
        return {
            email: '',
            password: '',
        }
    },
    methods: {
        ...mapActions('user', ['login']),
        async submit() {
            await this.login({
                email: this.email,
                password: this.password,
            })

            this.$router.replace({ name: 'Topic' })
        },
    },
}
</script>

user.js | Vuex modules

async login({ dispatch }, credentials) {
    await axios.get('/sanctum/csrf-cookie')
    await axios.post('/login', credentials)

    return dispatch('me')
},

I am configuring my project similar to this article. His is a separate project while mine within the Laravel project. I've also refer to Laravel's sanctum documentation on configuring authentication and it still didn't work. Review a lot of StackOverflow Q&A and no luck thus far. Most are talking about adding CSRF headers to Axios which I've done already within bootstrap.js. I did try including a hidden input to hold the CSRf and still no luck.

Answer

gofish picture gofish · Aug 21, 2020

Did you remember to check your config/session.php domain?.

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */
    'domain' => env('SESSION_DOMAIN', null),

And then SESSION_DOMAIN in .env should be .localhost

Also, did you remember to check config/sanctum.php stateful?

    /*
    |--------------------------------------------------------------------------
    | Stateful Domains
    |--------------------------------------------------------------------------
    |
    | Requests from the following domains / hosts will receive stateful API
    | authentication cookies. Typically, these should include your local
    | and production domains which access your API via a frontend SPA.
    |
    */
    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1')),

With SANCTUM_STATEFUL_DOMAINS in .env being localhost,127.0.0.1?