0
votes

I have a Vue SPA and I'm using Axios for handling requests, vue-axios to apply it and vuex for storing tokens. But when I send a request the header Authorization becomes Bearer undefined or Bearer null.

The flow is that by logging in I retrieve a token, save it to the session storage, dispatch a login action and my vuex store will set a token in the state from the session storage. After my login and router redirect to "/" I want to send a GET request to /foo along with my token. But here my token is undefined. Based on console logs I know that the session storage do have the token before the request is sent.

I am following the structure from this tutorial by Paweljw:

Axios/axios.js

import axios from 'axios'

export default axios.create({
  baseURL: 'http://example.com/api/,
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + sessionStorage.token
  }
})

Axios/index.js

import Vue from 'vue';
import VueAxios from 'vue-axios';
import axios from './axios'

Vue.use(VueAxios, axios);

export default Vue;

Components/login.vue

onLogin(res) {
  if (!res.data.token) {
    return this.onLoginFailed();
  }

  sessionStorage.token = res.data.token;

  this.$store.dispatch("login");
  this.$router.replace(this.$route.query.redirect || "/");

Components/foo.vue

...
this.$http
    .get("foo")
    .then(res => this.doSomething(res))
    .catch(() => this.doSomethingElse());

As previously mentioned this sends a request with Bearer undefined. I'm aware that when axios.create(...) is being exported the sessionStorage.token is null - it hasn't been set when the application starts. And that's probably why, but I don't understand how I'm supposed to set it then and how other people using the same tutorial doesn't have this issue.

Any advice is greatly appreciated.

1
You can easily create axios instance and have convenient access from vue with this package.Илья Зеленько

1 Answers

0
votes

I suspect that this tutorial may have a mistake - if you set your headers in axios.create then the Authorization header will get the current value of the sessionStorage, which at this time is undefined.

Actually, you want to set your headers in axios.interceptors.request.use - so that the header will be populated with the value of the sessionStorage at the moment of performing the AJAX request. Something like this

Vue.prototype.$axios = axios.create(
  {
    headers:
      {
        'Content-Type': 'application/json'
      },
    baseURL: process.env.API_URL
  }
);

Vue.prototype.$axios.interceptors.request.use(
  config =>
  {
    if (store.getters.isUserLoggedin) config.headers['Authorization'] = 'Bearer ' + store.getters.user.token;
    return config;
  }
);

Vue.prototype.$axios.interceptors.response.use(
  response => response,
  error =>
  {
    if (error && error.response && error.response.status && error.response.status === 403)
    {
      store.dispatch('unsetUser');
      router.push('/login');
      return Promise.resolve(); // Avoid showing any errors
    }
    else
    {
      logger.error({
        message: 'Error in HTTP request',
        response: JSON.stringify(extractError(error)),
        status: _get(error, 'response.status', 'unknown'),
        url: _get(error, 'config.url', 'unknown'),
        userId: store.getters.userInfo.id
      });
      throw error;
    }
  }
);