N
Nuxt2w ago
marvin

Where to store Accesstoken for SSR?

Hi, I am trying to upgrade my Nuxt App + external REST API to OAuth. I tried a few Nuxt OAuth options listed on the Nuxt Modules Page, but all of them seem to be designed for the built-in Nuxt API. I then decided to use nuxt-auth-utils. I found no way to access the OAuth Accesstoken on client side, so because I needed the OAuth Accesstoken for my API I also added an Nuxt-API endpoint which returns the accessToken. The client can call that, gets identified via its nuxt-auth-utils session, and gets the Accesstoken, which is currently cached in localStorage to not strain the Nuxt-API on every useFetch request which handles getting the Accesstoken. I also added Accesstoken refreshing via an Nuxt-API endpoint, but that works without problem so I will not go deeper into that. Problem: It of course has no access to the localStorage in SSR, and because of that the custom useApiFetch composable (which handles getting the AccessToken and adds it to the Authorization headers) tries to call the "get Accesstoken from Nuxt-API" endpoint first, and after that it injects the accessToken into the header options and finally the custom useFetch composable returns a new return useFetch(url, options) so that the vue components can work with the returned data. This unfortunately gives me the following error: A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. I tracked it down to be caused by multiple useFetch usages within the composable: 1) useFetch to fetch the accesstoken endpoint to get the accesstoken because there is no localStorage, and 2) the return statement which has a useFetch. When not fetching the Accesstoken endpoint or alternately return null instead of useFetch, this error doesn't occur. This crashes only on backend, and not on client side. I don't quite understand why this is happening. Does anybody have an idea about the error? Thanks!
2 Replies
kapa.ai
kapa.ai2w ago
Hi @marvin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, I can offer some insights and suggestions regarding your question about storing and accessing the access token for server-side rendering (SSR) in Nuxt. The error you're encountering ("A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function") is a common issue when using Nuxt composables in the wrong context or asynchronously. This error occurs because Nuxt tracks temporary instances during the component lifecycle, and using composables outside the correct context can lead to issues, especially during server rendering Nuxt Docs on Auto-imports (https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables). To address your specific problem and store the access token for SSR, consider the following approaches: 1. Use useCookie instead of localStorage: Instead of storing the access token in localStorage, which is not available during SSR, you can use the useCookie composable. This will work both on the client and server side Stack Overflow - Accessing tokens (https://stackoverflow.com/questions/78634376).
const accessToken = useCookie("accessToken");

// Set the token
accessToken.value = "your_access_token";

// Get the token
const token = accessToken.value;

const accessToken = useCookie("accessToken");

// Set the token
accessToken.value = "your_access_token";

// Get the token
const token = accessToken.value;

2. Create a custom fetch wrapper: You can create a custom fetch wrapper that handles the authentication token automatically. This can be done using a Nuxt plugin Nuxt Docs on Custom Fetch (https://nuxt.com/docs/guide/recipes/custom-usefetch#custom-fetch). Here's an example of how you might implement this:
// plugins/api.ts
export default defineNuxtPlugin((nuxtApp) => {
const api = $fetch.create({
baseURL: '<https://your-api-url.com',>
onRequest({ options }) {
const accessToken = useCookie('accessToken').value
if (accessToken) {
options.headers = {
...options.headers,
Authorization: `Bearer ${accessToken}`
}
}
},
async onResponseError({ response }) {
if (response.status === 401) {
// Handle token refresh or redirect to login
}
}
})

return {
provide: {
api
}
}
})

// plugins/api.ts
export default defineNuxtPlugin((nuxtApp) => {
const api = $fetch.create({
baseURL: '<https://your-api-url.com',>
onRequest({ options }) {
const accessToken = useCookie('accessToken').value
if (accessToken) {
options.headers = {
...options.headers,
Authorization: `Bearer ${accessToken}`
}
}
},
async onResponseError({ response }) {
if (response.status === 401) {
// Handle token refresh or redirect to login
}
}
})

return {
provide: {
api
}
}
})

3. Use runWithContext or callWithNuxt: If you need to use Nuxt composables in an async context, you can use runWithContext or callWithNuxt to ensure the correct Nuxt instance is available YouTube - Nuxt Instance Unavailable (https://www.youtube.com/watch?v=ofuKRZLtOdY). 4. Consider using the experimental asyncContext feature: Nuxt has an experimental feature called asyncContext that allows you to use Nuxt composables in async functions Stack Overflow - How to properly wrap useFetch (https://stackoverflow.com/questions/77391591). Remember that when wrapping useFetch, you should be careful about how you structure your composable to maintain reactivity. Returning the result of useFetch directly, rather than awaiting it, can help preserve reactivity Stack Overflow - How to properly wrap useFetch (https://stackoverflow.com/questions/77391591). By implementing these suggestions, you should be able to store and access your access token in a way that works for both client-side and server-side rendering, avoiding the error you're currently experiencing. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@318106208995377152> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server