Reputation: 41
I am implementing a login feature to a website project. The backend is Express and the frontend is Nuxt 3. Upon successfully authenticating a user login, the Express backend returns necessary data to the webserver, which then creates an httpOnly cookie and sets any necessary data in a Pinia store. On page refresh, I would like the Nuxt 3 server to look at the cookie and setup the Pinia store (since it is lost on page refresh).
Can someone provide some guidance? I have looked at the useNuxtApp() composable, and I can see the cookie in nuxtApp.ssrContext.req.headers.cookie, but that only provides a K/V pairing of all set cookies, which I would need to parse. I know of the useCookie composable, but that only works during Lifecycle hooks, which seems to only resolve undefined.
Thanks.
Upvotes: 4
Views: 4479
Reputation: 351
I was able to achieve this using the following code. Neither the rest of the 'h3' cookie functions nor the event helped me to retrieve the cookies.
// server/middleware/auth.ts
export default defineEventHandler(async event => {
const cookies = parseCookies(event); // An object containing all the cookies including httpOnly ones
const cookieHeader = Object.entries(cookies)
.map(([key, value]) => `${key}=${value}`)
.join(";");
await $fetch("YOUR ENDPOINT", {
headers: {
Cookie: cookieHeader,
},
})
.then(response => {
console.log(response); // You will see the result in the terminal
// Your redirection logic
})
.catch(error => {
console.error(error);
});
});
For the rest of your question, I'm unsure if I can use the Pinia store inside a server middleware. You need to define a plugin in order to use Pinia.
An example plugin code:
// plugins/auth.ts
import type { Pinia } from "pinia";
export default defineNuxtPlugin(async nuxtApp => {
const store = nuxtApp.$pinia as Pinia;
const auth = useAuthStore(store);
const { someFn, reset } = auth;
try {
await someFn();
} catch (error) {
reset();
}
});
Upvotes: 0
Reputation: 376
Not sure if this is the right way, but it's a solution I used to get through a similar case - dotnet api + nuxt3 client.
First, we need to proxy API (express in your case), this will make it, so our cookie is on the same domain and browser will start sending it to /api/ endpoints.
@nuxtjs-alt/proxy
- npm i @nuxtjs-alt/proxy
.nuxt.config.ts
(my api running on localhost:3000):nuxt.config.ts
:
export default defineNuxtConfig({
modules: [
'@nuxtjs-alt/proxy'
],
proxy: {
enableProxy: true,
fetch: true,
proxies: {
'/proxy': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/proxy/, '')
}
}
}
});
Then we can the request that will set a cookie anywhere on client using proxy instead of a direct call.
Anywhere on client, do a request using newly setup proxy instead of calling API directly.
Adjust parameters based on your setup.
await $fetch('/proxy/user/sign-in', {
method: 'POST',
body: {
email: '[email protected]',
password: 'password'
}
});
Ultimately, should end up with a cookie set on our client domain.
And lastly, when we handle request client side - we read the cookie and set up on forwarding request.
Replace COOKIE_NAME
and API URL accordingly.
server/api/user/me.get.ts
:
export default defineEventHandler(async (event) => {
return await $fetch('http://localhost:3000/user/me', {
headers: {
Cookie: `COOKIE_NAME=${
getCookie(event, 'COOKIE_NAME')
}`
}
});
});
API call will use the same cookie we got when we did a first request using cookie and the server should be able to read it.
Upvotes: 1