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.
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