Auth.js CSRF Token
Unanswered
dilraba posted this in #help-forum
dilrabaOP
Hi guys, I am having trouble to get CSRF Token using auth.js & nextauth without infinite loop on client, or get CSRF Token from the server. I have to include a CSRF Token in the submission form.
I am using Next.js App Router, utilize auth.js with next auth
I am using Next.js App Router, utilize auth.js with next auth
16 Replies
How did you set up your csrf token? can you please provide some snippet of code on how you implemented it?
Using Codeblocks
dilrabaOP
Sure, here's my code. Thanks for replying. This code infinite fetching csrftoken, and then fails because client component not supporting async function.
And then I change my approach like this. But return error that getCsrfToken is not a function
my page component.
my form component
"use client"
import { getCsrfToken } from "next-auth/react";
const LoginComponent = async () => {
const csrfToken = await getCsrfToken();
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
</form>
)
}
And then I change my approach like this. But return error that getCsrfToken is not a function
my page component.
import { Login } from '@/components/pages/Login'
import { getCsrfToken } from 'next-auth/react';
import React from 'react'
const LoginPage = async () => {
const csrfToken = await getCsrfToken();
return (
// <Login />
<Login csrfToken={csrfToken} />
)
}
export default LoginPage
my form component
"use client"
import { getCsrfToken } from "next-auth/react";
const Login = async ({csrfToken} : {csrfToken: string}) => {
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
</form>
)
}
Does your login function needs to be done via client-side fetch() ? or are you able to afford to use the signIn() and signOut() provided by next-auth?
Or is it for other operations that is not for signing in and out
@Alfonsus Ardani Does your login function needs to be done via client-side fetch() ? or are you able to afford to use the signIn() and signOut() provided by next-auth?
dilrabaOP
yes, I use signin & signout provided by nextauth. but that is done in action server, which is in different files. But that csrfToken should present in the form submission, sadly (my ZAP report said it)
when you use server actions, Next.js already uses a built-in preventions to mitigate csrf tokens.
If you want to be extra sure, use the signIn and signOut not for server action but from next-auth/react because they also implemented their csrf built-in into the signIn and Out
If you want to be extra sure, use the signIn and signOut not for server action but from next-auth/react because they also implemented their csrf built-in into the signIn and Out
There are csrf preventions other than putting it in the form submissions
@dilraba Sure, here's my code. Thanks for replying. This code infinite fetching csrftoken, and then fails because client component not supporting async function.
ts
"use client"
import { getCsrfToken } from "next-auth/react";
const LoginComponent = async () => {
const csrfToken = await getCsrfToken();
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
</form>
)
}
And then I change my approach like this. But return error that getCsrfToken is not a function
my page component.
ts
import { Login } from '@/components/pages/Login'
import { getCsrfToken } from 'next-auth/react';
import React from 'react'
const LoginPage = async () => {
const csrfToken = await getCsrfToken();
return (
// <Login />
<Login csrfToken={csrfToken} />
)
}
export default LoginPage
my form component
ts
"use client"
import { getCsrfToken } from "next-auth/react";
const Login = async ({csrfToken} : {csrfToken: string}) => {
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
</form>
)
}
try using a useEffect here
"use client"
import { getCsrfToken } from "next-auth/react";
const LoginComponent = async () => {
const [csrf, setCSRF] = useState('')
useEffect(() => {
getCsrfToken().then(data => setCSRF(data))
}, [])
if (!csrf) return null
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrf} />
</form>
)
}
You can also use double submission so that you can submit a form without hidden input fields but still ensure csrf protection
@Alfonsus Ardani try using a useEffect here
tsx
"use client"
import { getCsrfToken } from "next-auth/react";
const LoginComponent = async () => {
const [csrf, setCSRF] = useState('')
useEffect(() => {
getCsrfToken().then(data => setCSRF(data))
}, [])
if (!csrf) return null
return (
<form>
<input name="csrfToken" type="hidden" defaultValue={csrf} />
</form>
)
}
dilrabaOP
thanks for explaining. let me try this approach
@Alfonsus Ardani when you use server actions, Next.js already uses a built-in preventions to mitigate csrf tokens.
If you want to be extra sure, use the signIn and signOut not for server action but from next-auth/react because they also implemented their csrf built-in into the signIn and Out
dilrabaOP
I couldn't agree more with you. I choose to use server action to secure the authentication. It's just that my security teams that insist to resolve that issue
You could still do csrf stuff with server action!
but
it really depends on your security teams on how the csrf protection needs to be employed haha
simply submitting twice; to check if cookie can be set on first request (sameSite check), and check if cookie is stored before continuing on second request is already a csrf protection. These all can be done in server action