We have a Vue application that connects to a Hasura API via the vue apollo client and uses auth0 for authentication.
The app runs fine when we give the apollo client the Hasura admin secret header (see x-hasura-admin-secret commented out below).
However when we try to use the bearer token it fails because auth0.getAccessTokenSilently() returns an empty object even though we can successfully login via auth0's redirect.
We know the auth0 login is working because useAuth0 on the .vue pages returns the correct logged in user data as expected (we can currently only get to these pages by uncommenting the x-hasura-admin-secret headers).
See our main.js below:
import { createApp, provide, h } from 'vue'
import './tailwind.css'
import App from './App.vue'
import { routes } from './routes.js'
import { createRouter, createWebHistory } from 'vue-router'
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { createAuth0 } from '@auth0/auth0-vue';
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { getMainDefinition } from 'apollo-utilities'
import { HttpLink } from 'apollo-link-http'
const auth0 = createAuth0({
domain: import.meta.env.VITE_AUTH0_DOMAIN,
client_id: import.meta.env.VITE_AUTH0_CLIENT_ID,
redirect_uri: window.location.origin
})
function getToken(){
// let token = localStorage.getItem('Auth_token')
let token = auth0.getAccessTokenSilently()
console.log("token="+JSON.stringify(token))
return token
}
const httpLink = new HttpLink({
uri: import.meta.env.VITE_API_URI,
headers: {
"content-type": "application/json",
// "x-hasura-admin-secret": import.meta.env.VITE_HASURA_ADMIN_SECRET,
"Authorization": `Bearer ${getToken()}`,
}
})
const wsLink = new WebSocketLink({
uri: import.meta.env.VITE_API_WS,
options: {
reconnect: true,
timeout: 30000,
inactivityTimeout: 30000,
lazy: true,
connectionParams: {
headers: {
"content-type": "application/json",
// "x-hasura-admin-secret": import.meta.env.VITE_HASURA_ADMIN_SECRET,
"Authorization": `Bearer ${getToken()}`,
}
}
},
})
const link = split(
({ query }) => {
const definition = getMainDefinition(query)
return definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
},
wsLink,
httpLink
)
const cache = new InMemoryCache({
typePolicies: {
Subscription: {
goal: {
goals: {
fields: {
merge(existing, incoming) {
return incoming;
}
}
}
}
}
}
})
const apolloClient = new ApolloClient({
link,
cache,
connectToDevTools: true,
})
const app = createApp({
setup () {
provide(DefaultApolloClient, apolloClient)
},
render: () => h(App),
})
const router = createRouter({
history: createWebHistory(),
routes,
})
app.use(router)
app.use(
auth0
);
app.mount('#app')
getAccessTokenSilentlyreturns a promise. You need toawaitit in order to get the actual value.You may need to use the Apollo
setContextlink in order to inject some async processing before things are passed over to the HttpLink.I haven't used Vue before but a similar approach from a React app could look something like this: