laravelvue.jscsrfquasar

Vue3 + Quasar SPA trying to authenticate with a Laravel API and getting a CSRF token mismatch (419 status code)


I have a application SPA Vue3 + Quasar and a backend Laravel API, on same domain (localhost), my SPA is on port 8080 and my API on port 80.

In SPA, every time my page refresh, I send a GET to /sanctum/csrf-cookie and them the CSRF Token is stored on browser application cookies.

Also, axios is sending correctly the CSRF token on requisition.

I tried to authenticate with my Laravel API (/login without the /api prefix), at dev environment an then I receive a 419 status code.

I don't know if is important, but my API is running with Sails, on a docker container.

Axios config on Quasar/Vue:

axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'http://localhost/'
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'

Laravel .env

...
APP_URL=http://localhost
...
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8080

cors.php

    'paths' => ['api/*', 'sanctum/csrf-cookie', 'login'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,

Kernel.php,

        'api' => [
            EnsureFrontendRequestsAreStateful::class,
            ThrottleRequests::class . ':api',
            SubstituteBindings::class,
        ],

Cookie Header of my request to /login:

Cookie:
XSRF-TOKEN=eyJpdiI6InJ0SXhRZDVEL21JaEUvL0ptTGdmUlE9PSIsInZhbHVlIjoiU28zenNEQ1VOYTR3NXRVd1JtcU1RaUsvK1BCTHpNUGtUZ3c3T3I0d3lKQjhlZzNjMkVIeDBoOFZWanJDVkw2cWc0RGRDM0NWako0cnN1RXdveThwZkE4dW51aS9Ia1FYVXVsSlpqdW9CK1F3amJTMlFITzhpSCtudDYvY2VpUnUiLCJtYWMiOiIyODkyMzhjYjU5YzMzODY2YTkxZTY3M2MzOWZkNDkwMGQyYjBjNDg0ZTgwMzM3ZDc5NjYwYTcyNWFmZTUyZjExIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IlQxYXZ4WGhYZGZ5Lzk2WlF5QzJRUHc9PSIsInZhbHVlIjoidE5QQUpaeFh3WWg4cjFJNG82SXNDY1FGUmplWFN5cG5na08zazRmbXFJRFhJVWdUZS81UzJ1RWNaaC84VWxxcTFPdWNuTXd5K0pDaW0zTDliME5BSHl2ZGw4M01lbk1EUDl6SnlVWWFLM2lxNHBTOFBmei9QQXhMaTZLazJSeEEiLCJtYWMiOiIwNjFlNTFkNzIzZTIyZDhjYTg0MmVhMGViMGZjYTU4MmZjY2VmOGMyOWRjODgyNGY3NmE3NjExZDIyYWVhMDU1IiwidGFnIjoiIn0%3D; 3mcV2b1Mp2zT3MoKAWWTOeGlp0TkNFu9FneRzMLK=eyJpdiI6InY1cUYwaXhjdnZlQVRiNDNqaFRMMEE9PSIsInZhbHVlIjoiaE52dVg0dnRYdmE2dDVUT0lUUkJWeXAyaXNkaXMvZkw3RjJwT0hrbkdybUx4K0JyZ2RZV2lMYjEvT3F2TUEvOWQzejkxN05SaHlZMVliUktmUnhVRkwwYTB4cDYzUVB5VFA3MnA5SmlhMmc1Y0VSY3NyMm1JVnd2Vk1XZmFlWU05dEZJWVQrSjFqQ2h6aktFemdFVWZ6cjJBM2MydHNIMlcxRSsvWk1xaDU0Y1RDcHBFUndOL2ZlMXBVWVhyUEQrNS8vOTI5Qmx0TmpMQUtZQ0sxUHZLMEd5MnpGdC91SnVDeDJ5RkF4Tkc0dUphNHhLRFQwUE5Vc0hlR29JaVZqQ3p4Yi9wTFpMUE42UmJOWXoxN0V2bGZlZHduTVRmZUdkcHVnLzBkOWQ0emQyajhjelptSG9XUzRDb3lmZVlpMk5OK1p0R2R2eTdET2FjcTVhVGR4WmRtNVd4ekQ4SHZaeEg3cTUxY0Y2ZVhFdWhJeDh1SUkreUkwdFBmMjErUmdGIiwibWFjIjoiYWVmY2NkY2NiZmJiY2ZhNjkyMTVhODE2MTg0MjkxNTYxZWQ0N2I4NzMyY2RjOWE2NDdiNGY4NjljYjk5NDY0YyIsInRhZyI6IiJ9

Edit:

I discover a new point:

Axios added a header named "Cookie" and inside put the XSRF-TOKEN.. I manually added a header named "X-XSRF-TOKEN" with my cookie which has stored early on Application's Cookies... And finally worked. But I saw in many tutorials this proccess is automatically done by Axios... How can I achieve this?

    const login = async () => {
      let cookies;
      await axios.get("/sanctum/csrf-cookie").then((response) => {
        const { get } = useCookies(['XSRF-TOKEN']);
        cookies = get('XSRF-TOKEN');
      });

      axios.defaults.headers['X-XSRF-TOKEN'] = cookies;
      await axios.post("/login", form).then((response) => {
        console.log(response)
      });
    }

Solution

  • It's a known issue after Axios 1.6.0. You have to modify your axios configuration and set withXSRFToken to true, as below:

    axios.defaults.withCredentials = true;
    axios.defaults.withXSRFToken = true;
    

    Take a look at https://github.com/laravel/docs/pull/9152