New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setCookie only works sometimes in getServerSideProps #255
Comments
This is happening both if I pass ctx and not. |
Hi @NicholasG04. Please attach a reproduction CodeSandbox. I can't do much with an issue like this. |
Yeah sorry about that - I've found a solution. Setting/destroying cookies wasn't working for me serverside/client side but did when I used useEffect(); and so what it seems like is that it needs to be set when the browser has loaded the page. This is annoying for me however as I was doing this for security purposes but oh well... |
You should be able to set cookies in getServerSideProps without many problems tho, in getServerSideProps we are talking about a node.js If you provide a small repro we can help you out :) |
That is certainly an interesting point and I see why it should in fact work. I'll try to reproduce it when I have some time. Thanks for your prompt response. |
This seems similar to #249 - using |
When playing around now it did it once randomly, but only once. I'm very confused. |
I wonder if the issue might be related to the fact that I immediately use next/router to switch pages? Edit: nope. |
@NicholasG04 can't do much without reproduction. |
@maticzav
|
@mimiqkz happy/sad to see someone else is having the exact same issue. this guide is what I've been using to try to set up SSR auth through firebase and yeah ... it's been a complete mess. Sometimes the token is there in SSR but other times (most of the time) it's not. |
@KevinKra No kidding! I'm doing the same tutorial, have trying to debug 3 days now, not really sure what causes this. Thinking to open a ticket on nextjs as well. When I check the Cookie, I sometimes see it set another cookie with the same name , for no reason ! like what? |
@KevinKra Ok I managed to fix it by taken out his code in context where he uses However, I don't understand why the package sometimes set cookie 🍪 again with the same name but another path ? |
Okay, I've finally made some headway in determining where the issue is and how to fix it. My solution is based off the tutorial I linked above for setting up SSR auth with cookies and NextJS. I don't know what specifically is causing the issue, but these are the observations and conclusions I've made after troubleshooting this for two days. So, as of writing this it seems that setting cookies with So, the solution I'm using right now after freshly resolving this issue is to use two packages: Context (setting, clearing, destroying)Using the resource I linked above, here are the adjustments I made to the context provider's export function AuthProvider({ children }: any) {
const [user, setUser] = useState<firebase.User | null>(null);
useEffect(() => {
if (typeof window !== "undefined") {
(window as any).nookies = nookies;
}
return firebaseAuth.onIdTokenChanged(async (user) => {
console.log(`token changed!`);
nookies.destroy(null, "token");
if (!user) {
console.log(`no token found...`);
setUser(null);
Cookies.set("token", "");
return;
}
console.log(`updating token...`);
const token = await user.getIdToken();
Cookies.set("token", token);
setUser(user);
});
}, []);
// force token refresh every 10 minutes
useEffect(() => {
const handle = setInterval(async () => {
console.log("Interval token refreshing...");
const user = firebaseAuth.currentUser;
if (user) await user.getIdToken(true);
}, 10 * 60 * 1000);
// clean up
return () => clearInterval(handle);
}, []);
return (
<AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
);
} Page SSR (reading)export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
const { language, lessonID } = ctx.params;
try {
const cookies = nookies.get(ctx);
const token = await firebaseAdmin.auth().verifyIdToken(cookies.token);
// * the user is authenticated
const { uid, email } = token;
// ! Fetch stuff here
} catch (error) {
console.log("auth error", error);
return {
redirect: {
permanent: false,
destination: "/auth/login",
},
props: {} as never,
};
}
if (!data) {
return {
notFound: true,
};
}
return {
props: { data, params: ctx.params },
};
}; |
I think the problem stems from how NextJS handles the new functions. If you use the original You can see it in the example https://github.com/maticzav/nookies/blob/master/examples/typescript/pages/create.tsx If someone could open an issue in NextJS repository that would be invaluable. I wanted to do it for some time but haven't found the time yet. |
I can confirm this issue... I am also trying to follow this tutorial mentioned above and I am facing the exact same issue. Already contacted the author on twitter, but did not get any response yet. |
This works for me too. But actually, I would like to stick with ncookies only... |
This may be specific to my use case and infrastructure, but maybe it may help anyone here. tl;dr: make sure that your cookie value doesn't get URI-encoded without your consent by passing
|
This was an issue for me. When I remove redirection, all works fine. Just debugging. |
I have been struggling with this for days Auth.jsimport React, { useState, useEffect, useContext, createContext } from "react";
import nookies from "nookies";
import { firebaseClient } from "./firebaseClient";
import Cookies from 'js-cookie'
const AuthContext = createContext<{ user: firebaseClient.User | null }>({
user: null,
});
export function AuthProvider({ children }: any) {
const [user, setUser] = useState<firebaseClient.User | null>(null);
console.log("User is ", user)
useEffect(() => {
if (typeof window !== "undefined") {
(window as any).nookies = nookies;
}
return firebaseClient.auth().onIdTokenChanged(async (user) => {
if (!user) {
setUser(null);
Cookies.set("token", "");
return;
}
const token = await user.getIdToken();
setUser(user);
Cookies.set("token", token);
});
}, []);
useEffect(() => {
const handle = setInterval(async () => {
console.log(`refreshing token...`);
const user = firebaseClient.auth().currentUser;
if (user) await user.getIdToken(true);
}, 10 * 60 * 1000);
return () => clearInterval(handle);
}, []);
return (
<AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
);
}
export const useAuth = () => {
return useContext(AuthContext);
}; Authenticated pageexport const getServerSideProps = async (req, ctx) => {
try {
console.log("CTX er ", ctx)
const cookies = nookies.get(ctx);
console.log("Jeg er før cookies, cookies er", cookies.token)
const token = await firebaseAdmin.auth().verifyIdToken(cookies.token);
const slug = req.query.slug;
const revisionQuery = await getClient().fetch(
`*[_type == "revisionTemplate" && slug.current =='${slug}'][0]`
);
return {
props: {
data: "Worked!"
},
};
} catch (err) {
console.log("feil ctx er:", ctx)
const cookies = nookies.get(ctx);
console.log("nookies er", cookies)
console.log("err er:", err)
return {
props: {
data: "Did not worked!"
},
};
}
};
const Revisions = ({ data, ctx }) => {
const { user } = useAuth();
console.log("user er", user)
console.log("Revision data is", ctx)
return (
<Layout>
<Container>
<p>{`User ID: ${user ? user.uid : 'no user signed in'}`}</p>
<p>{data}</p>
</Container>
</Layout>
);
};
export default Revisions Weirdly I never see the user ID in the front end localhost, but some times I see the user ID in the front end on Vercel. |
@AndreasJacobsen Maybe try to set path in the option. Setting path works fine for me |
Thank you for the help mimiqkz, but setting path did not resolve the issue. Nor should it really, the default path for js-cookies is / so if no path is set / should be set automatically. Which is what I want to happen The cookie remains when I open the server rendered page, but the key is deleted every time I refresh the server rendered authenticated page. I find it difficult to understand why it is being deleted, does firebaseAdmin.auth auto-delete cookies somehow? Edit running the authenticated page without using firebaseAdmin (just trying to return the cookie token back to front end) leads to the same issue Edit: const cookies2 = ctx.req.cookies;
const token = await firebaseAdmin.auth().verifyIdToken(cookies2.token);
return {
props: {
data: token.email,
},
}; This is how I set the cookies const token = await user.getIdToken();
setUser(user);
// Tried both nookies and js-cookies
// Cookies.set("token", token, { path: "/" });
nookies.set(null, "token", token, {
path: "/",
encode: (v) => v,
});
}); |
now in 2023 this tuto work... but i have a problem about use it on api route in Nextjs.
using this i can get on serversideprops the cookie
|
Thanks, this just saved my life! |
Hello,
Am using nookies with setCookie (also tried nookies.set) in getServerSideProps to set a cookie using values that I've checked are ok and I know that the code block is running. However, only sometimes is the cookie actually getting set - it seems to go through phases of working and then not working. Thanks.
The text was updated successfully, but these errors were encountered: