Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

localStorage item not updating in axios headers

I am using a JWT Token auth system, and when I login I get the token like this:

axios.post('/login', data)
    .then(response => {
        localStorage.setItem('token', response.data.token);
   });

This works well and the token is saved in localStorage. However, the token is not included in the later requests. The Authorization header is Bearer null.

This is how I set up my global axios object.

window.axios = axios.create({
    baseURL: '/api/',
    timeout: 10000,
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
        'Authorization': 'Bearer ' + localStorage.getItem('token')
    }
});

If I refresh the site, the token is set, and is used properly.

Edit:

I got it to work by removing the Authorization header from the create() method and instead using window.axios.defaults.headers.common['Authorization']. But now the same problem appears with Laravel Echo. I create the instance like this:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'xxx',
    cluster: 'eu',
    encrypted: true,
    namespace: 'xxx',
    auth: {
        headers: {
            'Authorization': 'Bearer ' + localStorage.getItem('token')
        }
    }
});

And I update the header like this:

window.setAuthToken = (token) => {
    window.axios.defaults.headers.Authorization = 'Bearer ' + token;
    window.Echo.options.auth.headers.Authorization = 'Bearer ' + token;
    localStorage.setItem('token', token);
}

The axios header is successfully updated, but not Echo.

like image 577
Fredrik Avatar asked Dec 08 '17 13:12

Fredrik


People also ask

Is it possible to pass headers in the configs of Axios?

However, this option does not allow us to pass in the configs. To correctly set up the headers for each request, we can create an instance of Axios using axios.create and then set a custom configuration on that instance:

How to add Axios interceptors to the localStorage?

You can use axios interceptors for this task. 1-) Inside the successfull login, put the retrieved token to the localStorage. Remove setAuthToken line. .then ( (res) => { setCurrentUser (res.data); localStorage.setItem ("token", res.data.accessToken); setLoading (false); }) 2-) Add this interceptor to your axios instance.

What is Axios in Node JS?

Axios is a flexible and robust solution for making HTTP requests and for intercepting HTTP responses from both Node. js applications and the browser. But, Axios also does much more.

How do I get the existing data from localStorage?

// Get the existing data var existing = localStorage.getItem('myLunch'); // If no existing data, create an array // Otherwise, convert the localStorage string to an array existing = existing ?


3 Answers

Use axios interceptors for this purpose. It will run for every request call.

Better to keep axios methods in a separate file and make call to it than using it directly in all components. This way we can replace axios with another library if we want with minimal effort. Here's what I'm doing in my project.

import axios from "axios";
import AuthService from "./auth";

import config from '../config'

const instance = axios.create({
  baseURL: config.apiServer.url,
  timeout: config.apiServer.timeout
});

instance.interceptors.request.use(
  config => {
    const token = AuthService.getToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => Promise.reject(error)
);

const ApiService = {

  get(url) {
    return instance.get(url)
      .then(res => res)
      .catch(reason => Promise.reject(reason));
  },

  post(url, data) {
    return instance.post(url, data)
      .then(res => res)
      .catch(reason => Promise.reject(reason));
  },

  awaitAll() {
    return axios.all(Array.from(arguments))
      .then(axios.spread((...responses) => responses))
      .catch(reasons => Promise.reject(reasons));
  }

};

export default ApiService;

Now to use it in a component:

ApiService.get(YOUR_GET_URL)
      .then(res => {
        Console.log(res);
      ))
      .catch(reason => {
        console.log(reason);
      })
like image 178
Drunken Daddy Avatar answered Oct 18 '22 21:10

Drunken Daddy


The problem is that your are using localStorage.getItem('token') at page load. When you are setting it in localStorage, you have to update it in axios header.

window.axios = axios.create({
    baseURL: '/api/',
    timeout: 10000,
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
        'Authorization': 'Bearer ' + localStorage.getItem('token')
    }
});

axios.post('/login', data)
    .then(response => {
        localStorage.setItem('token', response.data.token);
        window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
    });
like image 29
Vipin Kumar Avatar answered Oct 18 '22 21:10

Vipin Kumar


I faced the same problem before and I found out that the file that contains my axios config was being loaded at the time of storing the token, so it was accessing it before it is stored.

The solution is, in axios config:

  const axiosInstance = axios.create({
  baseURL: `${API_BASE_URL}`,
  headers: {
    Accepted: 'appication/json',
    'Content-Type': 'application/json',
  },
});

axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.authorization = token;
    }
    return config;
  },
  (error) => Promise.reject(error),
);

export default axiosInstance;

After that, use this instance where you need to make a request.

like image 7
Francois MUGOROZI Avatar answered Oct 18 '22 22:10

Francois MUGOROZI