Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 927
Afiq Rosli Avatar asked Aug 21 '20 17:08

Afiq Rosli


People also ask

What is laravel Sanctum?

Laravel Sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Sanctum allows each user of your application to generate multiple API tokens for their account.

How do I disable CSRF protection in laravel?

Laravel Disable CSRF Token Protection To disable CSRF protection on all routes. So navigate to app\Http\Middleware and open VerifyCsrfToken. php file. Then update the routes, which you want to disable CSRF protection.


Video Answer


2 Answers

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?

like image 110
gofish Avatar answered Oct 10 '22 09:10

gofish


Enable cookie encryption

In my case it was the encrypt session / cookies functionality that wasn't activated everywhere (it was inconsistent). In my case, I had to activate it. If you disable it, make sure it is disabled everywhere. Otherwise Laravel will compare encrypted with unencrypted values and claim they are not the same.

Check all places where this could possibly be set:

  • config/session.php:

'encrypt' => false,

  • Kernel.php middleware
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
  • Laravel Sanctum config/sanctum.php:

'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,

URL decode encrypted tokens

Additionally, my client sent the encrypted data URL encoded, which led the = at the end to become %3D. More details about that particular issue can be found in this answer.

like image 43
askuri Avatar answered Oct 10 '22 10:10

askuri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!