Skip to content
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

missing csrf #5

Closed
M-Pedrami opened this issue Apr 21, 2024 · 12 comments
Closed

missing csrf #5

M-Pedrami opened this issue Apr 21, 2024 · 12 comments

Comments

@M-Pedrami
Copy link

Hello,
First off thank you for the example.
I cloned your repo and installed all the dependencies. The login page itself is loading however when I click on sign in with GitHub or with credentials nothing happens. The terminal logs out this error:
missing csrf: csrf token was missing during an action sign in.

I appreciate any help.

@ndom91
Copy link
Owner

ndom91 commented Apr 21, 2024

@M-Pedrami thanks for checking it out! I noticed this too and am working on it myself as we speak 🙏

I'll update you here once I find a solution

@smultar
Copy link

smultar commented Apr 23, 2024

Let me know if your solution also works for the bun runtime.

@ndom91
Copy link
Owner

ndom91 commented Apr 24, 2024

@M-Pedrami this issue seems to be solved for this project in prod. However, I think there might be an issue with Next.js still.

I'm using next@14.3.0-canary in main right now, and it works in prod, but it still has this error in local dev.

What seems to be happening is the following, when I first click the "Sign in" button, it takes me to /auth/signin (the default signin page route) but renders the app/auth/login/page.tsx content (from my custom signin page), as it should. So its showing the wrong route initially.

Then, when entering the correct PW and clicking "signin with credentials" there, it responds with the "MissingCSRF" redirect error.

However, if I manually reload the page while its showing /auth/signin, it'll fix and show the /auth/login route correctly in the URL bar then. And thennn the signin works without throwing the "MissingCSRF" error.

I went back through more next.js releases, and the first one to exhibit this weird path behaviour was 14.2.0-canary.48. So anything before that, like -canary.48 or the latest 14.1.3 works both locally and in prod as expected.

@ndom91 ndom91 closed this as completed Apr 24, 2024
@lob0codes
Copy link

lob0codes commented May 3, 2024

Hi ndom91,

I saw the same behavior that you describe with your project and with my own project.

Just a minor thing that I saw is that initially when pressing the Sign In button, the route that is executed is "/api/auth/signin" instead of "/auth/signin", nothing that adds to the discussion xD.

I wonder if somehow this unexpected route and render management just makes a desynchronization of what CSFR token the server expects and what the OAuth provider is giving back.

I will try rolling back to the versions suggested to avoid this issue, thanks for the info!.

@lob0codes
Copy link

It works!, rolling back to 14.1.3 makes it work.

@andresgutgon
Copy link

andresgutgon commented May 19, 2024

This is still not working for me in NextJS 14.2.3

Instead of using default signIn method that does the redirect to /api/auth/ original endpoint. I do my own link

// server action to get from `next/headers` the origin
import { SIGNIN_URL } from '$/auth'
import { headers } from 'next/headers'
import { redirect } from 'next/navigation'

export async function signinLink({ redirectTo }: { redirectTo?: string }) {
  const origin = headers().get('origin')
  const callbackUrl = redirectTo ? redirectTo : origin ?? '/'
  redirect(`${SIGNIN_URL}?callbackUrl=${callbackUrl}`)
}

And then I have a custom component that use that header

import { signinLink } from '$/auth'

function SigninLink({ redirectTo }: { redirectTo?: string }) {
  return (
    <form
      action={async (formData) => {
        'use server'
        const redirectTo = formData.get('redirectTo')?.toString()
        await signinLink({ redirectTo })
      }}
    >
      <input type='hidden' name='redirectTo' value={redirectTo} />
      <button type='submit'>Sign In</button>
    </form>
  )
}

Lastly I use that component. Note that use can pass a custom redirectTo

// My home apps/page.tsx
export default function Home() {
  return <SigninLink redirectTo='/some/page' />
}

@bdermody
Copy link

@andresgutgon Hola Andres!! Did you get this working? I am still stuck on this :(

@andresgutgon
Copy link

andresgutgon commented Jun 11, 2024

Hola : ) Maybe try newer version of nextjs 15.0.0-canary.25. It's working for me now the same code

@ndom91
Copy link
Owner

ndom91 commented Jun 13, 2024

Yeah afaik this is a Next issue with 14.2.1+. Haven't had time to dig in further unfortunately.

There's a thread on the main next-auth repo as well here: nextauthjs/next-auth#10585

@august25
Copy link

august25 commented Jun 26, 2024

The issue here is in env.ts it's setting the default config.basePath to "/api/auth" and so rather than attempting to load /auth/signin it's attempting to load /api/auth/signin, a refresh will cause it to load the proper path.

It's attempting to set the url to either of these: process.env.AUTH_URL ?? process.env.NEXTAUTH_URL

If not found it reverts to /api/auth

This is the code that creates the url, you can see it uses config.basePath, which defaults to /api/auth

const signInURL = createActionURL("signin", // @ts-expect-error x-forwarded-proto is not nullable, next.js sets it by default headers.get("x-forwarded-proto"), headers, process.env, config.basePath);

So for now to bypass I just direct users to "/auth/signin" directly as mentioned above. Setting one of the env vars above will break google. Still new to next-auth so maybe there's additional configurations needed to get it to work, but easiest solution is just to direct the user to "/auth/signin" yourself.

@RushilJalal
Copy link

Guys I received the same error
�[31m[auth][error]�[0m MissingCSRF: CSRF token was missing during an action signin. Read more at https://errors.authjs.dev#missingcsrf at t6 (/var/task/.next/server/chunks/277.js:17:66137) at iN (/var/task/.next/server/chunks/277.js:393:46096) at async iz (/var/task/.next/server/chunks/277.js:393:50436) at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:34666 at async eS.execute (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:25813) at async eS.handle (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:35920) at async es (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:25461) at async ei.responseCache.get.routeKind (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:1026) at async r3.renderToResponseWithComponentsImpl (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:508) at async r3.renderPageComponent (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:5028)

how can I fix this?
My repo: https://github.com/RushilJalal/rushil-ecommerce-store

@andresgutgon
Copy link

andresgutgon commented Jun 28, 2024

Try this @RushilJalal https://stackoverflow.com/a/78577718

Assuming this is a server component you do this:

import { cookies } from "next/headers";

export default async function UserButton() {

  const session = await auth();
  if (!session?.user) {
    const csrfToken = cookies().get("authjs.csrf-token")?.value ?? ""
    return <SignIn csrfToken={csrfToken} />;
  }
  //...
}

Then you change this component:

// ./components/auth-components.tsx
export function SignIn({
  provider,
  csrfToken
}: { provider?: string; csrfToken: string } & React.ComponentPropsWithRef<typeof Button>) {
  return (
    <form
      action={async () => {
        "use server";
        await signIn(provider);
      }}
    >
      <!-- HIDDEN input with the csrfToken --> 
      <input type="hidden" name="csrfToken" value={csrfToken} />
      <Button {...props}>Sign In</Button>
    </form>
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants