Vue or Axios don't store session cookie

15,023

Solution 1

In my experience this tends to be an issue arising from CORS ( Cross-Origin Resource Sharing ).

Namely if your API_URL is not on the same domain as your application's auth.js is running Axios will not be able to send cookies by default. You can read more about how to allow Cross Domain credential use to your API here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials

Practically speaking you can use the CORS module https://www.npmjs.com/package/cors to apply the necessary headers in some configuration akin to the following on the server side:

var express = require('express')
  , cors = require('cors')
  , app = express()

app.use(cors({
    origin: "myapp.io",
    credentials: true
}))

It is particularly important that you specify the origin url that your auth.js script is running from otherwise an attacker could use a Cross Site Scripting Attack.

Hopefully that helps!

Solution 2

You could also globally set axios credentials:

axios.defaults.withCredentials = true

From within the docs:

// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials: false, // default
Share:
15,023
arckosfr
Author by

arckosfr

Updated on June 04, 2022

Comments

  • arckosfr
    arckosfr almost 2 years

    I face a problem but i don't know where it be and why. I have a backend API based on express4(nodejs) We have implemented Auth with passport.

    When i use postman, i log with post on /login. it store a session cookie and all route is now accesible since the cookie is not expired.

    But with my frontend based on VueJS. I use Axios for doing the Request. The request seems to be good. but any cookie is stored so the browser do a loopback on he login page.

    I have tried without the auth check or not it the same. But on postman it work.

    the main.js for Vue:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Axios from 'axios'
    Vue.use(VueRouter)
    
    import auth from './utils/auth'
    
    import App from './components/App.vue'
    
    import Login from './components/Login.vue'
    import Home from './components/Containers.vue'
    
    require('font-awesome-loader');
    
    function requireAuth (to, from, next) {
      if (!auth.checkAuth()) {
        next({
          path: '/login',
          query: { redirect: to.fullPath }
        })
      } else {
        next()
      }
    }
    
    const router = new VueRouter({
      mode: 'history',
      routes: [
        { path: '/', name: 'containers', component: Home, beforeEnter: requireAuth },
        { path: '/login', component: Login },
        { path: '/logout',
          beforeEnter (to, from, next) {
            auth.logout()
            next('/')
          }}
      ]
    })
    
    new Vue({
      el: '#app',
      router,
      render: h => h(App)
    })
    

    And the auth.js (where the request is done)

    import axios from 'axios'
    import { API_URL } from '../config/app'
    
    export default {
    
      user: {
        authenticated: false
      },
    
      login (email, pass, cb) {
        LoginRequest(email, pass, (res) => {
          this.user.authenticated = res.authenticated
          if (this.user.authenticated) {
            console.log('ok')
            if (cb) cb(true)
          } else {
            console.log('pasok')
            if (cb) cb(false)
          }
        })
      },
    
      checkAuth () {
        if (getAuth()) {
          this.authenticated = true
        } else {
          this.authenticated = false
        }
      },
    
      logout (cb) {
        this.user.authenticated = false
        if (cb) cb()
      }
    }
    
    function LoginRequest (email, pass, cb) {
      axios.post(API_URL + '/api/login', {
        email: email,
        password: pass
      }).then(response => {
        if (response.status === 200) {
          cb({ authenticated: true })
        } else {
          cb({ authenticated: false })
        }
      }, response => {
        cb({ authenticated: false })
      })
    }
    
    function getAuth (cb) {
      axios.get(API_URL + '/me').then(response => {
        return true
      }, response => {
        return false
      })
    }
    

    EDIT : my cors use on the backend :

     // allow CORS:
            app.use(function (req, res, next) {
              res.header("Access-Control-Allow-Origin", "*");
              res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT$
              res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,$
              next();
            });
    

    Thank !