manchenkoff / nuxt-auth-sanctum

Nuxt module for Laravel Sanctum authentication
https://manchenkoff.gitbook.io/nuxt-auth-sanctum/
MIT License
115 stars 16 forks source link

CSRF token mismatch error #108

Closed Jonston closed 1 hour ago

Jonston commented 1 week ago

Hello. Problem during the first login attempt. When using the login method, 2 requests are sent simultaneously to the sanctum/csrf-token cookie installation URL and login authorization. Why am I getting the error? "CSRF token mismatch." When I try to log in again, everything works fine. What am I doing wrong?

manchenkoff commented 1 week ago

Hey @Jonston, most likely, you have misconfigured session domain on Laravel's side. Please check this docs to make sure you have everything set - Nuxt Auth Sanctum - Laravel config.

Jonston commented 1 week ago

Hey @Jonston, most likely, you have misconfigured session domain on Laravel's side. Please check this docs to make sure you have everything set - Nuxt Auth Sanctum - Laravel config.

Cookies are sent to the server by XSRF-TOKEN and laravel_session. cors are configured correctly in my opinion. I don't understand why this error is given.

config/cors.php 'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,

config/sanctun.php

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '', env('FRONTEND_URL') ? ','.parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : '' ))), 'guard' => ['web'], 'expiration' => null, 'middleware' => [ 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, ],

.env SANCTUM_STATEFUL_DOMAINS=localhost:3000 SESSION_DOMAIN=localhost APP_URL=http://localhost FRONTEND_URL=http://localhost:3000

manchenkoff commented 1 week ago

@Jonston Yep, config looks right, thanks. Can you provide a bit more details on your Nuxt setup as well as details/screenshots of the requests sent?

Nuxt info:

manchenkoff commented 1 week ago

@Jonston In the meantime I would also recommend to try removing SESSION_DOMAIN from your .env file, especially if you are using Windows

Jonston commented 1 week ago

nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
import vuetify, { transformAssetUrls } from "vite-plugin-vuetify";

export default defineNuxtConfig({
  build: {
    transpile: ["vuetify"],
  },
  modules: [
    (_options, nuxt) => {
      nuxt.hooks.hook("vite:extendConfig", (config) => {
        // @ts-expect-error
        config.plugins.push(vuetify({ autoImport: true }));
      });
    },
    "@pinia/nuxt",
      'nuxt-auth-sanctum'
  ],
    sanctum: {
        baseUrl: 'http://localhost', // Laravel API
        endpoints: {
            login: '/api/login',
            logout: '/api/logout',
        }
    },
  css: ["~/assets/main.scss"],
  vite: {
    vue: {
      template: {
        transformAssetUrls,
      },
    },
  },
  alias: {
    assets: "/<rootDir>/assets",
  },
  devtools: { enabled: true },
    ssr: true,
});

package.json

{
  "name": "nuxt-app",
  "private": true,
  "type": "module",
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare"
  },
  "dependencies": {
    "@mdi/font": "^7.4.47",
    "@pinia/nuxt": "^0.5.1",
    "@vueuse/core": "^10.10.0",
    "axios": "^1.7.2",
    "nuxt": "^3.11.2",
    "pinia": "^2.1.7",
    "vue": "^3.4.27",
    "vue-router": "^4.3.2"
  },
  "devDependencies": {
    "nuxt-auth-sanctum": "^0.4.0",
    "sass": "^1.77.4",
    "vite-plugin-vuetify": "^2.0.3",
    "vuetify": "^3.6.7"
  }
}

I use SSR

i olso take this error in terminal

[nuxt-auth-sanctum:ssr]  ERROR  Unable to load user identity from API [GET] "http://localhost/api/user": 404 Not Found

  at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
  at async $fetch2 (/C:/OSPanel/domains/carpot-client.loc/node_modules/ofetch/dist/shared/ofetch.37386b05.mjs:268:15)
  at async node_modules\nuxt-auth-sanctum\dist\runtime\plugin.js:58:120
  at async setup (virtual:nuxt:C:\OSPanel\domains\carpot-client.loc\.nuxt\plugins\server.mjs:44:116)
  at async Object.callAsync (/C:/OSPanel/domains/carpot-client.loc/node_modules/unctx/dist/index.mjs:72:16)
  at async applyPlugin (node_modules\nuxt\dist\app\nuxt.js:116:25)
  at async executePlugin (node_modules\nuxt\dist\app\nuxt.js:153:9)
  at async Module.applyPlugins (node_modules\nuxt\dist\app\nuxt.js:161:5)
  at async createNuxtAppServer (node_modules\nuxt\dist\app\entry.js:24:7)
  at async default (/C:/OSPanel/domains/carpot-client.loc/node_modules/@nuxt/vite-builder/dist/runtime/vite-node.mjs:33:18)
manchenkoff commented 1 week ago

i olso take this error in terminal

This one is about missing endpoint in your Laravel app, module cannot load the user during initialization. Make sure that this endpoint is defined and you have access to your laravel app from node via localhost.

For further investigation I still need more logs and request information as mentioned previously. And let me know if you removed SESSION_DOMAIN from env file.

Jonston commented 1 week ago

I remove SESSION_DOMAIN access to app exists at localhost:80

// 20240618125747
// http://localhost/

{
  "Laravel": "10.48.11"
}

api/user route exist but it protected 'auth:sanctum'

manchenkoff commented 1 week ago

api/user route exist but it protected 'auth:sanctum'

That's fine, it is supposed to be secure. I am not sure why you have connection issues between node and laravel, but I assume that it might be the reason why you are getting this weird behavior with authentication and mismatching tokens.

Once you provide all logs from the module and request/headers/cookies details from your browser for all requests, I will try to help.

Jonston commented 1 week ago

If I login manually via axios, everything works. Cookies are set, the user logs in and receives the user successfully

const customLogin = async () => {
  try {
    axios.defaults.withCredentials = true;
    axios.defaults.withXSRFToken = true;
    axios.defaults.baseURL = "http://localhost:80";

    await axios.get("/sanctum/csrf-cookie");
    await axios.post("/api/login", data.value);
    await axios.get("/api/user");
  } catch (error) {
    errors.value = error.response.data.errors;
  }
}
Jonston commented 1 week ago

I also noticed that if I disable the ssr: false option in the configuration, then everything works. I also want to clarify that I use laraver sail wrapper over docker. I have a suspicion that requests sent from the nuxt server do not work correctly with the session

manchenkoff commented 1 week ago

I also noticed that if I disable the ssr: false option in the configuration, then everything works. I also want to clarify that I use laraver sail wrapper over docker. I have a suspicion that requests sent from the nuxt server do not work correctly with the session

It should work fine with sail as well, I created breeze-nuxt and breeze-api templates based on this configuration. Please, provide logs from the module by setting logLevel to 5. It should log all requests and behavior during ssr requests.

manchenkoff commented 1 week ago

By the way, @Jonston do you run node in docker as well?