Search code examples
vue.jsjwtes6-promisevuexvuex-modules

call to endpoint unauthorised as auth request not fully resolved


I’m building a small chat app with Vue that hooks up to a Laravel back end.

When the chat app is initialised, there’s a call to the backend to get a JWT and that gets stored in Vuex and localstorage.

Next, to begin a conversation, I’m hitting an end point that passes the bearer token in the header. However, it fails at first as unauthorised but if I used Postman to hit that end point with the token, it works.

So here’s the breakdown. First up, a Vuex action:

register ({ commit, rootState }) {
    const apiRequest = {
      chatprofileuid: rootState.global.chatProfileUid
    }

    return Auth.register(apiRequest)
      .then((data) => {
        commit('setAccessToken', data.data.token)
      })
  }

Auth.register calls a service

import { myApi } from './api'
register (data) {
    return myApi.post('client/register', data)
      .then(response => response.data)
      .catch(error => Promise.reject(error.response))
  },

and then there’s the mutation

setAccessToken (state, token) {
    localStorage.setItem('accessToken', token)
    state.tokens.access = token
    console.log(`access token is now ${token}`)
  }

this works great.

Next, to begin the conversation

createNewConversation ({ commit }) {
    return Conversations.createConversation().then(data => {
      console.log(data)
    })
  }

and like the Auth, I have a Conversation service

import { myApi } from './api'
const endPoint = '/client/conversations'

createConversation () {
    return myApi.post(endPoint)
      .then(response => response.data)
      .catch(error => Promise.reject(error.response))
  }

myApi refers to

import axios from 'axios'

export const myApi = axios.create({
  baseURL: `/api/v1/`,
  headers: {
    Authorization: `Bearer ${localStorage.getItem('accessToken')}`
  }
})

Like I said, fails at first but after a few minutes, succeeds, assuming because the http promises have fully resolved.

I feel like async/await would help here but not entirely sure where that should go. I haven’t fully gotten my head around async/await yet so any pointers would be great.


Solution

  • your problem is that the ${localStorage.getItem('accessToken') is evaluated just once, when the myApi is imported the first time, and presumably you still don't have the correct accessToken stored in localStorage

    if you stop and reload the app, then it will read the accessToken from the previous execution and that may work (depending on the expiration period of the token)

    you need to change your logic a bit so that you read and set the token in the headers when you are actually making the subsequent calls to the chat endpoint