N
Nuxt3w ago
Leo

No Cookies sent in Header?

Hello everyone, does anyone have any idea why no cookies are sent when a request is made via the plugin? It doesn't work in the ssr or the spa. https://paste.gg/p/anonymous/c723ccf5af994f65a376dc56c2909d08 Thank you in advance!
8 Replies
kapa.ai
kapa.ai3w ago
Hi @Leo. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To address your question about why no cookies are being sent in the header when making a request via a plugin in Nuxt, there are a few important points to consider: 1. By default, during server-side rendering (SSR), cookies are not automatically included in internal fetch requests. This is because the request is made on the server, not from the user's browser. 2. To forward cookies and other headers from the original client request to your internal API calls during SSR, you need to use special utilities provided by Nuxt. Here are some approaches to solve this issue: 1. Use useRequestFetch: The useRequestFetch composable is designed to forward the request context and headers when making server-side fetch requests. Here's how you can use it:
<script setup lang="ts">
const requestFetch = useRequestFetch()
const { data } = await useAsyncData(() => requestFetch('/api/your-endpoint'))
</script>

<script setup lang="ts">
const requestFetch = useRequestFetch()
const { data } = await useAsyncData(() => requestFetch('/api/your-endpoint'))
</script>

This will automatically forward the user's headers, including cookies, to your API endpoint Docs > Api > Composables > useRequestFetch (https://nuxt.com/docs/api/composables/use-request-fetch). 2. Use useRequestHeaders: If you need more control over which headers to forward, you can use useRequestHeaders:
<script setup lang="ts">
const headers = useRequestHeaders(['cookie'])
const { data } = await useFetch('/api/your-endpoint', { headers })
</script>

<script setup lang="ts">
const headers = useRequestHeaders(['cookie'])
const { data } = await useFetch('/api/your-endpoint', { headers })
</script>

This approach allows you to specifically forward the cookie header Docs > Getting-started > Data fetching > Passing Headers and cookies (https://nuxt.com/docs/getting-started/data-fetching#passing-headers-and-cookies). 3. For server routes, use event.$fetch: If you're making fetch requests within server routes, you can use event.$fetch to automatically forward the request context and headers:
export default defineEventHandler((event) => {
return event.$fetch('/api/your-endpoint')
})

export default defineEventHandler((event) => {
return event.$fetch('/api/your-endpoint')
})

This method ensures that relevant headers are forwarded in server-side API calls Docs > Guide > Directory-structure > server > Recipes > Forwarding Context & Headers (https://nuxt.com/docs/guide/directory-structure/server#forwarding-context-headers). Remember, certain headers that are not meant to be forwarded (like host, accept, etc.) will be automatically excluded from these requests for security reasons. If you're still experiencing issues after implementing these solutions, you might want to double-check that your cookies are being set correctly in the first place. You can use the useCookie composable to set and retrieve cookies in Nuxt 3 Docs > Api > Composables > useCookie > Cookies in API Routes (https://nuxt.com/docs/api/composables/use-cookie#cookies-in-api-routes). Hmm, I do not have enough information to answer your question. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@809685585374740480> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
manniL
manniL3w ago
Alexander Lichter
YouTube
Passing Cookies with event.$fetch and useRequestFetch in Nuxt
Ever wondered why cookies are not passed correctly to subrequests - e.g. during SSR or when using Nitro/H3? Then this video is for you. Together we have a look how to pass all the important information, including event context and headers to further calls, eliminating different behavior on server and client. #nuxtjs #nuxt #vue #webdevelopment ...
manniL
manniL3w ago
(kapa.ai wasn't wrong)
Leo
LeoOP3w ago
@kapa.ai Can you refer to the following code? I'm not sure how I can implement your suggestions and still keep my custom fetch. Or are there other options? export default defineNuxtPlugin((nuxtApp) => { const api = $fetch.create({ baseURL: ${useRuntimeConfig().public.backendUrl}, credentials: 'include', async onRequest({ options }) { const accessTokenCookie = useCookie('access_token'); const { renewAuth, isTokenExpired } = useAuth(); const { obtainToken } = useCsrf(); const headers = options.headers;
if (!useCookie('csrf_token').value) { await obtainToken(); } const cookies = process.server ? useRequestHeaders(['cookie']) : null; debugger; if (useCookie('refresh_token').value) { if (isTokenExpired(accessTokenCookie.value as string)) { if (!(await renewAuth())) { await nuxtApp.runWithContext(() => navigateTo('/login') ); return; } } headers.set( 'Authorization', Bearer ${accessTokenCookie.value} ); } }, async onResponseError({ response, options }) { if (response.status == 401) { useCookie('access_token').value = null; useCookie('refresh_token').value = null; await nuxtApp.runWithContext(() => navigateTo('/login')); } }, }); return { provide: { api, }, }; });
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on your code and the previous suggestions, I can see that you're using a custom fetch instance with some authentication logic. To incorporate the suggestions for forwarding cookies while maintaining your custom fetch setup, you can modify your code as follows:
export default defineNuxtPlugin((nuxtApp) => {
const api = $fetch.create({
baseURL: `${useRuntimeConfig().public.backendUrl}`,
credentials: 'include',
async onRequest({ options }) {
const accessTokenCookie = useCookie('access_token');
const { renewAuth, isTokenExpired } = useAuth();
const { obtainToken } = useCsrf();
const headers = options.headers;

if (!useCookie('csrf_token').value) {
await obtainToken();
}

// Forward cookies on server-side
if (process.server) {
const cookieHeaders = useRequestHeaders(['cookie']);
if (cookieHeaders.cookie) {
headers.set('cookie', cookieHeaders.cookie);
}
}

if (useCookie('refresh_token').value) {
if (isTokenExpired(accessTokenCookie.value as string)) {
if (!(await renewAuth())) {
await nuxtApp.runWithContext(() =>
navigateTo('/login')
);
return;
}
}
headers.set(
'Authorization',
`Bearer ${accessTokenCookie.value}`
);
}
},
async onResponseError({ response, options }) {
if (response.status == 401) {
useCookie('access_token').value = null;
useCookie('refresh_token').value = null;
await nuxtApp.runWithContext(() => navigateTo('/login'));
}
},
});

return {
provide: {
api,
},
};
});
export default defineNuxtPlugin((nuxtApp) => {
const api = $fetch.create({
baseURL: `${useRuntimeConfig().public.backendUrl}`,
credentials: 'include',
async onRequest({ options }) {
const accessTokenCookie = useCookie('access_token');
const { renewAuth, isTokenExpired } = useAuth();
const { obtainToken } = useCsrf();
const headers = options.headers;

if (!useCookie('csrf_token').value) {
await obtainToken();
}

// Forward cookies on server-side
if (process.server) {
const cookieHeaders = useRequestHeaders(['cookie']);
if (cookieHeaders.cookie) {
headers.set('cookie', cookieHeaders.cookie);
}
}

if (useCookie('refresh_token').value) {
if (isTokenExpired(accessTokenCookie.value as string)) {
if (!(await renewAuth())) {
await nuxtApp.runWithContext(() =>
navigateTo('/login')
);
return;
}
}
headers.set(
'Authorization',
`Bearer ${accessTokenCookie.value}`
);
}
},
async onResponseError({ response, options }) {
if (response.status == 401) {
useCookie('access_token').value = null;
useCookie('refresh_token').value = null;
await nuxtApp.runWithContext(() => navigateTo('/login'));
}
},
});

return {
provide: {
api,
},
};
});
The main change here is in the onRequest function. We've added a section that uses useRequestHeaders to forward cookies when on the server side:
if (process.server) {
const cookieHeaders = useRequestHeaders(['cookie']);
if (cookieHeaders.cookie) {
headers.set('cookie', cookieHeaders.cookie);
}
}
if (process.server) {
const cookieHeaders = useRequestHeaders(['cookie']);
if (cookieHeaders.cookie) {
headers.set('cookie', cookieHeaders.cookie);
}
}
This modification ensures that cookies are forwarded during server-side rendering, which should solve the issue of cookies not being sent in the header Docs > Getting-started > Data fetching > Passing Headers and cookies (https://nuxt.com/docs/getting-started/data-fetching#passing-headers-and-cookies). By implementing this change, you're maintaining your custom fetch instance with all its authentication logic while also ensuring that cookies are properly forwarded during server-side requests. Remember that this solution will only work for server-side requests. For client-side requests, cookies are automatically included by the browser, so no additional handling is needed there. If you're still experiencing issues after this modification, you might want to double-check your cookie settings, especially the httpOnly, secure, and sameSite attributes, as these can affect how cookies are sent with requests. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@809685585374740480> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
manniL
manniL3w ago
FYI - using useCookie in an interceptor is not the correct usage.
Want results from more Discord servers?
Add your server