Replies: 13 comments 7 replies
-
As a temporary solution I am importing the cookie from next/headers to get the next-auth.csrf-token value. |
Beta Was this translation helpful? Give feedback.
-
Interesting discovery: if you just invoke import { cookies } from 'next/headers';
import { getCsrfToken } from 'next-auth/react';
export default async function SignInPage() {
cookies();
console.log(await getCsrfToken()) // you will see the csrf token being logged
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={await getCsrfToken()} />
</form>
)
} |
Beta Was this translation helpful? Give feedback.
-
Nice, I could get the csrfToken after that but for some reason unknown to me it only got the token and the custom page stopped calling the credentials. So I had to change to a client rendered component and call signIn. what I found strange is that it works from the client but not from the server |
Beta Was this translation helpful? Give feedback.
-
Yup, I got the same experience. Calling the auth endpoint from the server does not work, and needed to switch to client component and call |
Beta Was this translation helpful? Give feedback.
-
I couldn't use client because of other factors so ended up adding const cookieVals = cookies().getAll().find((item)=> item.name.includes('next-auth.csrf-token'))
const csrfToken = decodeURI(cookieVals?.value || "").split('|')[0] This works in dev but haven't deployed a preview yet in vercel, Can't see why it wouldn't though but will update if it doesn't EDIT: Changed the match to includes as Vercel at least seems to have a different cookies value name with __Host appended and decode it as in production is URI encoded |
Beta Was this translation helpful? Give feedback.
-
I would like to add that if the login page is accessed first time (one can try from incognito mode), csrf cookie is not available. I have not found the solution to it yet. |
Beta Was this translation helpful? Give feedback.
-
+1 same issue |
Beta Was this translation helpful? Give feedback.
-
Using the default signIn flow on the client produce three requests only to login. 1- Get the providers info I think it would be better to handle the login on a custom function with the data, and the csrf provided from the Server Component. This approach only use one request. Also I don't like the idea to make a POST from the form it self. I prefer to use fetch and keep the page without refreshing. I have been trying passing the csrf token from the Server Component after using getCsrfToken, but when I make the request to http://localhost:3000/api/auth/callback/credentials I always get a redirect to http://localhost:3000/api/auth/signin?csrf=true NextJS: 13.5.4 using App Router. Note: getCsrfToken is invoked without parameters because from the app router I don't know how to get the request from the server component, like the sample code for pages folder. |
Beta Was this translation helpful? Give feedback.
-
Ok, I think I found the problem. the A) const csrf = cookies().get("next-auth.csrf-token")?.value.split("|")[0] B) const csrfToken = await getCsrfToken({
req: {
headers: {
cookie: cookies().toString(),
},
},
}); |
Beta Was this translation helpful? Give feedback.
-
Calling
works as it returns always the same CSRF token, but still fails on the first request (incognito) |
Beta Was this translation helpful? Give feedback.
-
@tikoflano @rahul-reveation @felixng1028 @dylanngph I figured this out by looking at the network calls |
Beta Was this translation helpful? Give feedback.
-
Hey I've spent way too much time and ending up to the same conclusion. Hoping for a better resolution rather than having to submit the form twice! |
Beta Was this translation helpful? Give feedback.
-
My current requirement is to customize the login page using next-auth@4.23.1. One of the sub-steps is to obtain the csrftoken. Initially, I tried to obtain the csrftoken on the server-side using the method suggested by someone upstairs. However, I found that this approach would cause the csrftoken validation to fail and redirect to const csrfToken = await getCsrfToken({
req: {
headers: {
cookie: cookies().toString(),
},
},
}); The newest solution is to move the getCsrfToken() function to the client-side useEffect after initialization is complete. It has been tested and can solve the above problem. "use client";
export default function SignInPage(props: {
providers?: Provider[];
callbackUrl?: string;
email?: string;
error?: SignInPageErrorParam;
}) {
// more code
const [csrfToken, setCsrfToken] = useState("");
useEffect(() => {
getCsrfToken().then((token) => setCsrfToken(token || ""));
}, []);
// more code
} |
Beta Was this translation helpful? Give feedback.
-
Question 💬
Using the next.js 13 app router, I'm finding CSRF tokens returned from
getCsrfToken
(on the server) are not correct -- presumably because neither a request nor a context are available to be passed in.I dug around in the source code and I didn't see any exposed API that would enable getting a CSRF token on the server render (obviously it's possible to call
getCsrfToken()
on the client). As best as I can tell, there should be a wrapper aroundcreateCSRFToken
that works likegetServerSession
and can take theauthOptions
object and use theheaders
function to get to the cookie. However, as it is right now, thecreateCSRFToken
function isn't even exposed, so as far as I can tell there's no possible way to do this even manually, with the exception of just manually duplicating the whole function.How to reproduce ☕️
uh, I don't think a reproduction is necessary here, but let me know if one would help and I'll put a simple skeleton project together using next 13 and the app router.
Contributing 🙌🏽
Yes, I am willing to help answer this question in a PR
Beta Was this translation helpful? Give feedback.
All reactions