next-auth: in the middleware, the session is not extended with custom fields
Environment
System: OS: Windows 11 10.0.22631 CPU: (12) x64 AMD Ryzen 5 3600 6-Core Processor Memory: 7.60 GB / 15.95 GB Binaries: Node: 20.11.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.19 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 10.2.4 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Chromium (120.0.2210.91) Internet Explorer: 11.0.22621.1 npmPackages: @auth/prisma-adapter: ^1.1.0 => 1.1.0 next: 14.1.0 => 14.1.0 next-auth: 5.0.0-beta.5 => 5.0.0-beta.5 react: ^18 => 18.2.0
Reproduction URL
https://github.com/SebastianNarvaez11/TesloShop
Describe the issue
I am trying to get the custom field “role” in the middleware using req.auth but the custom fields that I added when creating the session previously are not there
In middleware.ts console.log(req.auth)
:
but with use auth()
in the component it works :
const session = await auth(); console.log(session)
:
How to reproduce
My file src/auth.ts
:
My file src/auth.config.ts
:
My file src/middleware.ts
, the problem is here:
Expected behavior
In the middleware you should have access to the custom fields that you added when creating the session
About this issue
- Original URL
- State: open
- Created 5 months ago
- Reactions: 4
- Comments: 40 (9 by maintainers)
@SebastianNarvaez11 @deltasierra96
I also faced this issue, what seems to have worked for me was combining my NextAuth instantiations.
The Fix
You have called
NextAuth(...)
insrc/middleware.ts
andsrc/auth.ts
using two different configurations. I was doing a similar thing. What you will want to do is move the content of theNextAuth(...)
instantiation insrc/auth.ts
intosrc/auth.config.ts
so that you have one main config with all your params forNextAuth(...)
.Your
src/auth.ts
should now look a little something like:Your
src/auth.config.ts
should now have ALL your configuration in it:This should resolve the issue. I have freehand typed this in GitHub so this code will probably not be perfect and will almost 100% have at least 1 error, but the idea should be there enough to hopefully help the issue.
The (assumed) Root Cause
It seems the actual cause is because the instantiations are different, calling
NextAuth(...)
insrc/middleware.ts
andsrc/auth.ts
works perfectly fine after moving all the configuration settings into one file. Thinking logically now (after rage researching all day over not being able to find the solution to this) it makes perfect sense as in the example you provided (very similar to mine) the middleware would have no idea that the session needs manipulating as the session callback is not in the config being used insrc/middleware.ts
TL;DR
You need to use one configuration/NextAuth instantiation for both your providers & middleware
Just follow the full fix, its not too long…
I hope that fixes your issue - If this is the problem for you, it seems the problem is NOT with next-auth. It may be worth documenting this somewhere though as its (IMO) an easy mistake to make!
Big thanks to ConnorC18 for the amazing help! ⭐⭐⭐⭐⭐
Right again, this happens on
"next-auth": "^5.0.0-beta.5"
. After installing the"next-auth": "^5.0.0-beta.9"
, it disappeared. I am now fully happy! Right before, I was about to give up. 😅@AmphibianDev I think this is almost 100% a workaround, but it seems to work and is why my one currently works. If you are running it in a non-edge environment, I think this approach is fine.
To check this actually works, I’ve made the changes and made a PR for this. Others can check the code here for an easier to read breakdown of the required changes but the explanation below might be useful
Fix PR …For AmphibianDev
https://github.com/AmphibianDev/todo-app/pull/1
auth.config.ts
auth.ts
middleware.ts
/data/user.ts
So whats the workaround?
Basically it looks like the workaround is to import a function that calls prisma independently and then just await that function. Doing this seems to solve the issue. If this is a valid work around this 100% needs documenting, and if it is, it really needs to be made clearer.
Hey guys, I found what worked for me was to define the session callback in both auth.ts and auth.config.ts. The Credentials and other callbacks is defined in auth.ts. Now I can retrieve the custom field in the session on both the server and client as well as in the middleware.ts. I am not sure why this works, but here is the code if anyone wants to give it a try (using next-auth-5.0.0-beta.15): auth.config
auth.ts
middleware.ts
Here are the versions of my libraries:
While debugging my callbacks and middleware, I discovered the issue. It appears to be related to the prisma query on the JWT callback function, although I’m unsure why. However, placing my Prisma query within a try-catch block resolved the issue!
Here is the code:
Hey folks, this issue seems to have gotten a bit off track…
Initially the issue was about session data not being available in middleware, right? And then it shifted towards prisma not working in edge environments. I think we’ve all gotten to the bottom of the prisma issue, right? If not, here’s my current understanding - using
prisma@5.9.1+
,session: { strategy: 'jwt' }
and not doing any database calls with prisma in your middleware or other edge runtime environments should work as of now with the latest versions of everything. Right? I’m pretty sure you no longer have to do the split config thing either since as ofprisma@5.9.1
they changed when the errors throws (query time vs. client instantiation).Regarding the middleware
req.auth
issue, I’ve just double checked with the latestnext-auth@5.0.0-beta.15
andreq.auth
is available with both OAuth and Credential providers when setup like how the docs describe:If you’re having problems that aren’t related to the original middleware session issue, please open a new issue.
To the latest commenters, @SebastianNarvaez11 this is an error you’re throwing yourself because your
getUserById
funciton is not findign the user, correct? In the case of credentialsProvider, thetoken.sub
defaults to theprofile.id
. So make sure yuo’re returning at least anid
from yourauthorize
fn.You can enable
debug: true
in the auth config and see whattoken.sub
you’re getting back from the provider, or simply log it in yourgetUserById
. Then you can manually confirm that you have a user in your database with that ID. Is that all good so far?@renatoastra can you provide more details about your setup and which versions of next-auth and next.js you’re using?
Thanks everyone 🙏
No worries! So, I am exclusively looking at this from a Non Edge standpoint, as that is what myself and @AmphibianDev are both using in this case. As far as I can see, it builds fine and runs (with the exception of the session callback having a es-line type issue in @AmphibianDev s case, but I believe that is because he needs to update his next-auth version, as I do not have this issue with the same approach). After building, the following successful output can be seen for @AmphibianDev s project
Hi everyone. Here’s a thumb rule you can follow:
auth.config.ts
handlers
in/api/auth/[...nextAuth]/app.ts
.All is good until you want to add
middleware.ts
.Now you should be able to use the same exported
auth
fromauth.ts
but since there are adapters that are not compatible with middleware, you cannot use them YET. I am trying to use postgres with drizzle-orm and at the time of writing this, only neon serverless has a postgres connector.How did I resolve this?
I moved the adapter and any callbacks requiring DB access into
auth.ts
. I had to reinitialize NextAuth in middleware as follows:Use the above hack until the adapters support running on edge. BTW - I spent 2 days setting up the Next Auth v5. I finally completed it. Here are my thoughts:
userId
to be an integer, which is not possible at all without raising a bunch of errors in NextAuth. Used the cal.com GitHub repo to understand how to do this.Im currently battleing this behaviour too, fighting it for 6 days now. Can you please share your code so we can see what was done in order to get this going? I have tried using prisma - only with accelerate which is paid, drizzle - “edgeFunction is not defined”.
@AmphibianDev
Also make sure you are copying over
session: { strategy: "jwt" },
into theauth.config.js
as not having this in the config whileadapter: PrismaAdapter(prisma)
is present might also cause this issue.@AmphibianDev make sure you are not calling prisma in the
middleware.ts
handler. I don’t believe this error is caused by the PrismaAdapter; the PrismaClient causes it. Just make sure you are not using prisma in the middlewareThanks for reporting, and thanks @ConnorC18 for explaining, that is exactly what we recommend at the moment. Some of us are working on a new doc to address this use-case, cc @ndom91 @ubbe-xyz 🙏