'NuxtJs app returns 401 after log in with laravel sanctum

I'm trying to build a PWA with NuxtJS and Laravel is in the backend for the API.

I use Laravel Sanctum for API auth and also I have NuxtJS auth module, I can login (I know this because it returns and sets all of the cookies) but when it's requesting to 127.0.0.8000/api/user auth it returns a 401 error.

Heres is my nuxtjs config

export default {
  /*
  ** Nuxt rendering mode
  ** See https://nuxtjs.org/api/configuration-mode
  */
  mode: 'universal',
  /*
  ** Nuxt target
  ** See https://nuxtjs.org/api/configuration-target
  */
  target: 'server',

  server: {
    host: 'localhost'
  },

  render: {
    // working:
    injectScripts: process.env.NODE_ENV === 'development'

    // HMR not working:
    // injectScripts: false,
  },

  /*
  ** Headers of the page
  ** See https://nuxtjs.org/api/configuration-head
  */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      {charset: 'utf-8'},
      {name: 'viewport', content: 'width=device-width, initial-scale=1'},
      {hid: 'description', name: 'description', content: process.env.npm_package_description || ''}
    ],
    link: [
      {rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'}
    ]
  },
  /*
  ** Global CSS
  */
  css: [
    '~/assets/storefront-ui',
    '~/assets/storefront-ui-custom',
    '~/assets/custom'
  ],
  /*
  ** Plugins to load before mounting the App
  ** https://nuxtjs.org/guide/plugins
  */
  plugins: [
    {src: '~/plugins/helpers', mode: 'client'},
    {src: '~/plugins/storefront-ui', mode: 'client'},
    {src: '~/plugins/icons', mode: 'client'},
    {src: '~/plugins/plugins', mode: 'client'}
  ],
  /*
  ** Auto import components
  ** See https://nuxtjs.org/api/configuration-components
  */
  components: true,
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
    // Doc: https://github.com/nuxt-community/nuxt-tailwindcss
    '@nuxtjs/tailwindcss',
  ],
  /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/pwa',
    '@nuxtjs/auth',
  ],
  /*
  ** Axios module configuration
  ** See https://axios.nuxtjs.org/options
  */
  axios: {
    baseURL: "http://localhost:8000",
    credentials: true
  },

  auth: {
    redirect: {
      login: '/login',
      logout: '/',
      callback: '/login',
      home: '/'
    },
    strategies: {
      local: {
        endpoints: {
          login: { url: '/login', method: 'post', propertyName: false },
          user: { url: '/api/user', method: 'get', propertyName: false }
        },
        tokenRequired: false,
        tokenType: false
      }
    },
    localStorage: false
  },

  router: {
    middleware: ['auth']
  },
  //
  /*
  ** Build configuration
  ** See https://nuxtjs.org/api/configuration-build/
  */
  build: {
    transpile: [/^@storefront-ui/],
    postcss: {
      // Add plugin names as key and arguments as value
      // Install them before as dependencies with npm or yarn
      plugins: {
        // Disable a plugin by passing false as value
        'postcss-url': true,
        'postcss-nested': {},
        'postcss-responsive-type': {},
        'postcss-hexrgba': {},
        "postcss-preset-env": {
          stage: 0,
        },
        "rucksack-css": {}
      },
      preset: {
        // Change the postcss-preset-env settings
        autoprefixer: {
          grid: true
        }
      }
    }
  }
}

Here is my login.vue

<template>
  <div class="flex h-screen items-center justify-center">
    <form ref="loginform" @submit.prevent="login()" class="w-1/4 mx-auto p-4">
      <h1 class="font-semibold mb-2 text-xl">
        Login
      </h1>
      <div class="mb-4">
        <label for="email" class="block mb-1 text-sm">Email</label>
        <input
          type="email"
          name="email"
          class="w-full border rounded px-3 py-2"
          required
        />
      </div>
      <div class="mb-4">
        <label for="password" class="block mb-1 text-sm">Password</label>
        <input
          type="password"
          name="password"
          class="w-full border rounded px-3 py-2"
          required
        />
      </div>
      <button
        type="submit"
        class="bg-blue-500 text-white font-semibold py-2 px-10 w-full rounded"
      >
        Login
      </button>
    </form>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        error: {},
      };
    },
    middleware: 'auth',
    mounted() {
      // Before loading login page, obtain csrf cookie from the server.
      this.$axios.$get('/sanctum/csrf-cookie');
    },
    methods: {
      async login() {
        this.error = {};
        try {
          // Prepare form data
          const formData = new FormData(this.$refs.loginform);

          // Pass form data to `loginWith` function
          await this.$auth.loginWith('local', { data: formData });

          // Redirect user after login
          this.$router.push({
            path: '/',
          });
        } catch (err) {
          this.error = err;
          // do something with error
        }
      },
    },
  };
</script>

The routes/api.php

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

And my cors.php

<?php

return [

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

    'allowed_methods' => ['*'],

    'allowed_origins' => ['http://localhost:3000'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],
 
    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,
];


Solution 1:[1]

The problem was in my Laravel .env configuration

Solution 2:[2]

if you are on localhost you need to add this in env file

SESSION_DOMAIN=127.0.0.1
SANCTUM_STATEFUL_DOMAINS=127.0.0.1:3000

Solution 3:[3]

do check your APP_URL settings in .env file as well. this can also cause 401. as this is used in session cookie key generation for session authentications.

in my case its value is:

APP_URL='https://example.com/api'

but i think APP_URL='http://example.com' will also work though i didn't tested it. for me with /api feels better as it is actually where the backend is.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Aimal Amiri
Solution 2
Solution 3 rajesh_chaurasiya