Search code examples
axiosvuejs3access-tokenauth0pinia

How to retrieve auth0 access token inside Axios Config file?


hope you’re all well and safe!

I'm currently working on a Vue 3 application with Pinia as my store, Auth0 Vue SDK for authentication/authorization and Axios to call my backend API.

In Auth0 docs, they recommend an access token be retrieved using the getAccessTokenSilently() method everytime I want to call my backend API:

const { getAccessTokenSilently } = useAuth0();
const accessToken = await getAccessTokenSilently();

The problem is I have to type this whenever I use axios in my component files to call my backend API with the access token.

Since I have too many endpoints, my plan is to pass the access token once in an axios request interceptor and use Pinia actions to call my APIs.

I’ve created a /config/axios.js file in my application that contains the following:

//Import Axios Library and Auth0
import axios from 'axios';
import { useAuth0 } from "@auth0/auth0-vue"

//Create instance of axios
const instance = axios.create({
    baseURL: 'http://localhost:5000/api/v1'
});

// Create a request interceptor for my instance and get accessToken on the fly
instance.interceptors.request.use(async (config) => {
    const { getAccessTokenSilently } = useAuth0();
    const accessToken = await getAccessTokenSilently();
    config.headers['Authorization'] = accessToken;
    return config;
}, (error) => {
    return Promise.reject(error)
});

export default instance;

Simple enough, just create a baseURL and intercept requests to add the authorization header with the access token.

Now in Pinia, I've created a user store that'll fetch users with the axios config as seen below:

//Import the Pinia Library
import { defineStore } from 'pinia'
//Import the Axios Library for API calls
import axiosConfig from "@/config/axios.js"

export const useUserStore = defineStore('user', {
  state: () => ({
    user:{}
  }),
  getters: {
    getUser(state){
      return state.user
    }
  },
  actions: {
    async fetchUser(){
      try {
        const data = await axiosConfig.get('/profile')
        this.user = data.data
      } catch (error) {
        console.log("User Pinia error: " + error)
      }
    }
  },
})

And lastly in my component file, I just import the store and call the Pinia action fetchUsers.

When trying an axios call, I get the following error!

TypeError: auth0_auth0_vue__WEBPACK_IMPORTED_MODULE_5_.useAuth0() is undefined

I can't figure out how to retrieve the access token from auth0 library in my interceptor function.


Solution

  • A similar question was raised as an issue on auth0-vue github: https://github.com/auth0/auth0-vue/issues/99

    The above link describes numerous approaches. I went for the plugin approach that is described in this PR, namely: https://github.com/auth0-samples/auth0-vue-samples/commit/997f262dabbab355291e5710c51d8056a5b142cf

    But the issue was officially resolved by offering a mechanism to allow the sdk from outside a vue component: https://github.com/auth0/auth0-vue/issues/99#issuecomment-1099704276