0

I am new to vue and stuck on this problem for quite some time. I have a login method that retrieves an API token and stores it in localStorage. The login API call is the only call that does not send Auth headers. After the Login every call should add the API token to the header.

When I login the interceptor does not set the new header. It needs a page refresh in the browser to work. Why is that, what am I doing wrong?

In my Login component I have this method:

methods: {
    login() {
        api.post('auth/login', {
            email: this.email,
            password: this.password
        })
        .then(response => {
            store.commit('LOGIN');
            localStorage.setItem('api_token', response.data.api_token);
        });
        this.$router.push('reservations') 
    }
}

Additionally I have this axios base instance and an interceptor:

export const api = axios.create({
    baseURL: 'http://backend.local/api/',
    // headers: {
    //  'Authorization': 'Bearer ' + localStorage.getItem('api_token')
    // },
    validateStatus: function (status) {
        if (status == 401) {
            router.push('/login');
        } else {
            return status;
        }
    }
});
api.interceptors.request.use((config) => {
    config.headers.Authorization = 'Bearer ' + localStorage.getItem('api_token');
    return config;
}, (error) => {
    return Promise.reject(error);
});
Sebastian
  • 923
  • 1
  • 9
  • 23
  • At what point are you setting your interceptor? Because if you set a global interceptor before your AJAX request for the token finished it will will not update magically. Rather it will keep using the value you initially provided it(which is nothing since you have no token yet at that point). – Stephan-v Sep 04 '18 at 14:58
  • 1
    @Stephan-v But that is fine isn't it? The very first call is for the token itself, so if the interceptor intercepts before the request nothing will happen. The second request is in the "reservations" component I am redirecting to. That request fails with a 401. – Sebastian Sep 04 '18 at 15:04
  • @Stephan-v the interceptor function will run for each request so the _"Bearer"_ string will be evaluated each time. At least, that's how I believe it works :/ – Phil Sep 04 '18 at 15:05
  • @Sebastian your browser has a debugger. I suggest you use it. Put `debugger` as the first line in your interceptor function – Phil Sep 04 '18 at 15:05
  • 1
    @Phil Ok, so the problem is that in the interceptor function and even in the login function, directly after the api call `localStorage.getItem('api_token')` returns `null`. Thow the response object `response.data.api_token` does a token. – Sebastian Sep 04 '18 at 15:15
  • Is response.data.api_token a plain string or something else? You sure there's no typos and you're calling "setItem"? – Phil Sep 04 '18 at 15:19
  • @Phil yes its a plain string and there are no typos. It is in the response part of the API call as described in the question. – Sebastian Sep 04 '18 at 15:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/179393/discussion-between-sebastian-and-phil). – Sebastian Sep 04 '18 at 15:27
  • @Sebastian Does the second API call occur as a result of `commit('LOGIN')`? If so, the `api_token` hasn't yet been saved to localStorage (the `commit` -- a Vuex mutation -- is synchronous), so the interceptor would not be able to retrieve the token. – tony19 Sep 04 '18 at 22:03
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Phil Sep 05 '18 at 00:20
  • Move your `this.$router.push('reservations')` call up one line. You are navigating **before** your `auth/login` request resolves. I'm assuming you're doing some data fetching in your `reservations` route which will occur **before** you've set your token to `localStorage` – Phil Sep 05 '18 at 00:22

0 Answers0