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

NextAuth v5 auth(req, res) fails in pages/ API route #9307

Closed
howard36 opened this issue Dec 3, 2023 · 34 comments · Fixed by #10122 · May be fixed by #12710
Closed

NextAuth v5 auth(req, res) fails in pages/ API route #9307

howard36 opened this issue Dec 3, 2023 · 34 comments · Fixed by #10122 · May be fixed by #12710
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@howard36
Copy link

howard36 commented Dec 3, 2023

Environment

$ npx envinfo --system --binaries --browsers --npmPackages "{next,react,next-auth,@auth/*}"
  System:
    OS: macOS 14.0
    CPU: (8) arm64 Apple M2
    Memory: 590.48 MB / 16.00 GB
    Shell: 3.6.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 18.18.0 - ~/.local/share/nvm/v18.18.0/bin/node
    Yarn: 1.22.19 - ~/.local/share/nvm/v18.18.0/bin/yarn
    npm: 9.8.1 - ~/.local/share/nvm/v18.18.0/bin/npm
    pnpm: 8.11.0 - ~/.local/share/nvm/v18.18.0/bin/pnpm
  Browsers:
    Chrome: 119.0.6045.199
    Safari: 17.0
  npmPackages:
    next: latest => 14.0.3 
    next-auth: 5.0.0-beta.2 => 5.0.0-beta.2 
    react: ^18.2.0 => 18.2.0 

Reproduction URL

https://github.com/howard36/next-auth-v5-example/tree/api-route-bug-repro

Describe the issue

I have a API route at pages/api/endpoint.ts:

import type { NextApiRequest, NextApiResponse } from "next";
import { auth } from "auth";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const session = await auth(req, res);
  return res.status(200).json({session});
}

Calling auth(req, res) in this API route causes this error:

 ⨯ Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/howard/git/next-auth-v5-example/node_modules/next/headers' imported from /Users/howard/git/next-auth-v5-example/node_modules/next-auth/lib/index.js
Did you mean to import next-auth-v5-example/node_modules/next/headers.js?
    at new NodeError (node:internal/errors:405:5)
    at finalizeResolution (node:internal/modules/esm/resolve:327:11)
    at moduleResolve (node:internal/modules/esm/resolve:946:10)
    at defaultResolve (node:internal/modules/esm/resolve:1132:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

This is with next-auth 5.0.0-beta.2, next 14.0.3, and node 18.18.0. If I switch to nextjs v13 (specifically v13.5.6), the error changes to:

 ⨯ node_modules/next-auth/lib/index.js (117:0) @ eval
 ⨯ TypeError: Cannot read properties of undefined (reading 'append')
    at eval (webpack-internal:///(api)/./node_modules/next-auth/lib/index.js:128:52)
    at Array.forEach (<anonymous>)
    at cloneSetCookie (webpack-internal:///(api)/./node_modules/next-auth/lib/index.js:128:21)
    at eval (webpack-internal:///(api)/./node_modules/next-auth/lib/index.js:73:13)
    at async handler (webpack-internal:///(api)/./pages/api/endpoint.ts:11:21) {
  page: '/api/endpoint'
}
null

How to reproduce

git clone -b api-route-bug-repro https://github.com/howard36/next-auth-v5-example.git
cd next-auth-v5-example
npm install
cp .env.local.example .env.local
npm run dev

Then visit http://localhost:3000/api/endpoint to trigger the error

Expected behavior

Calling auth(req, res) should successfully return the session without throwing an error.

@howard36 howard36 added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Dec 3, 2023
@howard36 howard36 changed the title v5 auth() fails in pages/ API routes NextAuth v5 auth(req, res) fails in pages/ API routes Dec 3, 2023
@howard36 howard36 changed the title NextAuth v5 auth(req, res) fails in pages/ API routes NextAuth v5 auth(req, res) fails in pages/ API route Dec 3, 2023
@jonluca

This comment was marked as off-topic.

@JasonZhLiang

This comment was marked as off-topic.

@jonluca
Copy link

jonluca commented Dec 11, 2023

Docs say pages is still supported

https://authjs.dev/guides/upgrade-to-v5

I think it's just a messed up import. Maybe making it an asynchronous conditional import inside the RSC check would fix it?

@pinelibg
Copy link
Contributor

This was working in next.js v13 and after upgrade to next.js v14 it's not working.

I think import of RSC-only Next.js packages (next/headers) in next-auth package cause the error.
As jonluca suggested, I suppose making those imports dynamic would solve the issue.

@glenntws
Copy link

glenntws commented Dec 22, 2023

Seems like the V5 beta removed the conditional loading of next/headers only for RSC (which was added in a certain minor/patch version of V4), so people using pages router (like myself) essentially can't work with nextauth right now (which is a bummer because I just upgraded in order to be able to use the edge runtime). Moving to app router may not be the way to go for everyone, as some would like to stay with tRPC and spamming "use client" in every file seems a little bit counter-intuitive...

@jonluca
Copy link

jonluca commented Dec 22, 2023

Hey @balazsorban44 it looks like the issue was first introduced here 65aa467 at this file https://github.com/nextauthjs/next-auth/blame/main/packages/next-auth/src/lib/index.ts#L2

Is it intentional that next-auth v5 should no longer work with pages router?

@me-imfhd

This comment was marked as off-topic.

@JustJoostNL

This comment was marked as off-topic.

@cfkarakulak

This comment was marked as off-topic.

@yousifsamir0
Copy link

yousifsamir0 commented Jan 7, 2024

I found a temp. solution for this issue by modifying these 2 files :
(NextProject)\node_modules\next-auth\lib\index.js
(NextProject)\node_modules\next-auth\lib\actions.js

in actions.js file:
add .js extension to the path 'next/headers' and 'next/navigation'

import { headers as nextHeaders, cookies } from "next/headers";
import { redirect } from "next/navigation";

to

import { headers as nextHeaders, cookies } from "next/headers.js";
import { redirect } from "next/navigation.js";

in index.js file:
add .js to the path 'next/headers' and 'next/server'

import { headers } from "next/headers";
import { NextResponse } from "next/server";

to

import { headers } from "next/headers.js";
import { NextResponse } from "next/server.js";

and in function initAuth(config) you will find it in line 32 in index.js file :
comment/disable these 2 lines that add auth cookies to response as we just need to get session from our req and ignore res headers :

for (const cookie of authResponse.headers.getSetCookie())
     response.headers.append("set-cookie", cookie);

@julienben

This comment was marked as off-topic.

@AlessandroAries
Copy link

AlessandroAries commented Jan 27, 2024

@julienben For the time being you can patch your package using: https://www.npmjs.com/package/patch-package.
But for me after applying the fix of @yousifsamir0 I get null when I call await auth(req, res) from an api route

@stefanoimperiale
Copy link

stefanoimperiale commented Jan 31, 2024

I changed the line

response.headers.append("set-cookie", cookie);

to:

if('headers' in response) {
     response.headers.append("set-cookie", cookie);
} else {
    response.appendHeader("set-cookie", cookie);
}

because I didn't know if the first method could be used in other part of the code; in any case it worked for me

@fabiopk

This comment was marked as off-topic.

@avarayr

This comment was marked as off-topic.

@dengelke
Copy link

dengelke commented Feb 5, 2024

@avarayr agree especially since on the documentation page we have App Router-first (pages/ still supported). as a feature!

@maiconcarraro
Copy link

@avarayr @dengelke appreciate you both trying to be helpful, but we have multiple people receiving alerts from this issue, v5 is not production ready, if you go to https://next-auth.js.org/getting-started/example you won't see any reference to v5 yet, so it makes no sense complaining about warning on this version since it already says Experimental and you can only install forcing it to be beta.

this issue is already open, pretty sure balazsorban44 is going to address or share updates once he has, and the project is always open to fork and send PRs, is not an easy task to maintain large/complex projects like this one, so let's try to be respectful to each other's time.

@avarayr
Copy link

avarayr commented Feb 5, 2024

@avarayr @dengelke appreciate you both trying to be helpful, but we have multiple people receiving alerts from this issue, v5 is not production ready, if you go to next-auth.js.org/getting-started/example you won't see any reference to v5 yet, so it makes no sense complaining about warning on this version since it already says Experimental and you can only install forcing it to be beta.

this issue is already open, pretty sure balazsorban44 is going to address or share updates once he has, and the project is always open to fork and send PRs, is not an easy task to maintain large/complex projects like this one, so let's try to be respectful to each other's time.

With all due respect, there's no indication of auth.js not being production ready. Please link one resource that explicitly says to not use auth.js in production.

FWIW, not being production ready is completely irrelevant to this issue. I don't really care if you think this library is experimental, if it has the features I want to use, and I have a way to vet the code myself, why shouldn't I use it?
The issue is the docs saying pages are supported, but it actually is not working. So having a clear warning would save people time trying to make v5 work in their apps, even if it's just a hobby project that doesn't require "production-ready state"

@julienben
Copy link

Contributor/maintainer burnout is a real thing. Please be respectful of people's time and work and don't place expectations on code that you get for free.

@cfkarakulak

This comment was marked as off-topic.

@maiconcarraro
Copy link

maiconcarraro commented Feb 6, 2024

tad bit excessive, considering people who also spend time on developing things, only to find out v5 is not compatible with the system they have.

You can downgrade to v4 while it doesn't have a proper solution yet, I'm currently using v4 in production. It works great w/ pages.

The migration between v4 and v5 is simple. And if you are on next-auth website it only says v4, not v5, if you are in authjs website it has a big warning "Guides are being migrated" + "site is under active development". I doubt you guys really read the documentation. Note that https://next-auth.js.org/guides and https://authjs.dev/guides have different states and warnings

If you have the issue, just follow the instructions and open a new issue, please stop using this issue as social media, open a discussion topic instead.

@cfkarakulak
Copy link

cfkarakulak commented Feb 6, 2024

No need to be this aggressive, this whole thread seems to have started as an issue, thinking if the developers are doing something wrong integrating v5, or a presence of a bug that hasn't yet been discovered. It was not until a couple of us figured it out that it was actually not working. (to make it clearer to you, this is the point where it turned into a discussion).

Anyhow, let's stop arguing at this point. You already have the necessary links and guidance for the ones who seek to get this right.

Thanks

@wiredmatt
Copy link

Well, if there's something that can be done is to update the page that says this is supported in v5 as mentioned above; even if the tone wasn't right, the point is clear. If it doesn't work, don't say it does.
I landed in the brand new AuthJS page and by default the experimental version is checked which doesn't happen in any other framework/library... I've just noticed v4 for the actual next auth has a different site (i assume that's the original one, first time using this), but this repo points you to the new one (rather confusing).

Summing this all up, the migration process is being handled poorly and that's just something to learn from. Perhaps better clarification / onboarding to the ecosystem is just what's needed here. Also leaving next auth v4 in its own repo and pointing that to the original next auth site would've been more clear.

To be fair, many projects handle this poorly. It was (is lol) the same with NextJS's app directory... And if you think about it, that's the entire reason why we are here.

No rush to patch / fix anything, but updating that section in the documentation can be done right away. For my use case I 100% need to use auth() in /pages/api. I chose v5 because I read exactly what was linked above.

@fabiopk
Copy link

fabiopk commented Feb 9, 2024

I found a temp. solution for this issue by modifying these 2 files : (NextProject)\node_modules\next-auth\lib\index.js (NextProject)\node_modules\next-auth\lib\actions.js

in actions.js file: add .js extension to the path 'next/headers' and 'next/navigation'

import { headers as nextHeaders, cookies } from "next/headers";
import { redirect } from "next/navigation";

to

import { headers as nextHeaders, cookies } from "next/headers.js";
import { redirect } from "next/navigation.js";

in index.js file: add .js to the path 'next/headers' and 'next/server'

import { headers } from "next/headers";
import { NextResponse } from "next/server";

to

import { headers } from "next/headers.js";
import { NextResponse } from "next/server.js";

and in function initAuth(config) you will find it in line 32 in index.js file : comment/disable these 2 lines that add auth cookies to response as we just need to get session from our req and ignore res headers :

for (const cookie of authResponse.headers.getSetCookie())
     response.headers.append("set-cookie", cookie);

Does anyone knows the impact of doing what is suggested by @yousifsamir0 above? I quickly tested it and it seems to fix the problem of it not working on the pages router. I was already doing the migration for my app, and unfortunately started by the app router portion. Wondering if it is viable to patch as mentioned above and continue developing for the meanwhile. I imagine that some other portions might break by removing some lines of code, just wondering how things would differ in my development between that version and a proper fix.

Thanks :)

@bnsngltn
Copy link

I created a patch-package for this issue. This handles my basic use case of using next-auth on an application with hybrid pages/app router handlers. This is just a temporary fix for those who wants to try out the latest features before they are officially released.

Save this as patches/next-auth+5.0.0-beta.9.patch (cannot upload the file, so just manually save this on your repo)

diff --git a/node_modules/next-auth/lib/index.js b/node_modules/next-auth/lib/index.js
index c2b9043..b02bfb4 100644
--- a/node_modules/next-auth/lib/index.js
+++ b/node_modules/next-auth/lib/index.js
@@ -106,8 +106,15 @@ export function initAuth(config, onLazyLoad // To set the default env vars
         // @ts-expect-error
         new Headers(request.headers), config).then(async (authResponse) => {
             const auth = await authResponse.json();
-            for (const cookie of authResponse.headers.getSetCookie())
-                response.headers.append("set-cookie", cookie);
+            for (const cookie of authResponse.headers.getSetCookie()) {
+		if ("headers" in response) {
+                	response.headers.append("set-cookie", cookie);
+	        // This should handle correct header addition on Next.JS API routes
+		} else {
+			response.appendHeader("set-cookie", cookie)
+		}
+	    }
+		
             return auth;
         });
     };

You can then call this inside your api routes as:

// make sure to supply req, res since we are on pages router and not app router
const session = await auth(req, res)

Thanks to @stefanoimperiale for the original code

@chistyakofff
Copy link

looks like the new authjs beta v5 is not designed for the pages router, only works for the app router

Also in example of next-auth-v5 they use only App Router

@ThangHuuVu
Copy link
Member

hey everyone, I want to confirm that we are not dropping the Pages Router support in v5. I'm working on the fix in the linked PR, appreciate the digging @stefanoimperiale, @bnsngltn and all 🙏

@balazsorban44
Copy link
Member

balazsorban44 commented Feb 24, 2024

Lead maintianer here. Please hold your horses... v5 is in beta, the expected behavior is that things work in the Pages Router, as documented and mentioned above.

The project is open-source, open for PRs. Please only engage in the discussion if you have something net positive/meaningful to add. Guessing what is and isn't supposed to be supported is counter productive. If you just follow the issue, subscribe to it or 👍 the OG post instead.

#9307 (comment) put it very nicely

@kwu-soundhound
Copy link

I am little bit confused. Did the PR fixed this issue? I am currently using 5.0.0-beta.15. Still see this issue.

@ThangHuuVu
Copy link
Member

@kwu-soundhound please open a new issue with minimal reproduction if you're still seeing it, thanks!

@kwu-soundhound
Copy link

@ThangHuuVu Sorry, I cannot solve the issue. I have moved to v4 which I do not have any issues for now. I will try v5 later if I have time.

@addlistener
Copy link

addlistener commented Jun 24, 2024

Any updates folks?

And @balazsorban44 we'd love to see a example of next-auth5 * pages router

And some people uses pages router tend to use trpc. And example of trpc support would also be nice. I myself stuck on sth like this when integrating trpc.

❌ tRPC failed on <no-path>: Invariant: headers() expects to have requestAsyncStorage, none available.
cause Error: Invariant: headers() expects to have requestAsyncStorage, none available.
    at headers (/node_modules/next/src/client/components/headers.ts:22:11)
    at file:////node_modules/next-auth/lib/index.js:88:31
    at Object.createTRPCContext [as createContext] (webpack-internal:///(api)/./src/server/api/trpc.ts:53:70)
    at Object.createContext ...
export const createTRPCContext = async (opts: CreateNextContextOptions) => {
  const { req, res } = opts;

  const session = await auth();
  // below works for next-auth v4
  // const session = await getServerAuthSession({ req, res });

  return createInnerTRPCContext({
    session,
  });
};

@nextor2k
Copy link

still broken in beta.19.

@Zareix
Copy link

Zareix commented Feb 26, 2025

Issue is still present in Beta 25.

However I fixed the issue temporarily by doing :

export const createTRPCContext = async (opts: CreateNextContextOptions) => {
  const { req, res } = opts;

  const session = await auth({ req, res });

  return createInnerTRPCContext({
    session,
  });
};

And patching the next-auth index.js file replacing every instance of

 response.headers.append("set-cookie", cookie);

by

 response.setHeader("set-cookie", cookie);

I guess one possible fix would be to consider something like this :

if("setHeader" in response)
        response.setHeader("set-cookie", cookie);
else if ("headers" in response)
    response.headers.append("set-cookie", cookie);
else
    response.appendHeader("set-cookie", cookie);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet