nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
24.17k stars 3.35k forks source link

Session and JWT callback is called twice with the SessionProvider #8152

Open Natchii59 opened 1 year ago

Natchii59 commented 1 year ago

Environment

System:

Binaries:

Browsers:

Reproduction URL

https://github.com/Natchii59/next-chat

Describe the issue

I would like to update my JWT data, and for that I need to put the SessionProvider at the root of the page. To then use the useSession which gives access to the update function. The problem is that it creates 2 calls to the jwt and session callbacks each time the page is refreshed. How to fix this?

How to reproduce

Add a SessionProvider to the project and put a console.log in a NextAuth options callback.

Expected behavior

I wish I didn't have callbacks double call with a SessionProvider. Or another way to update my JWT data without using SessionProvider.

18888628835 commented 8 months ago

the same as you

petejodo commented 7 months ago

hard to tell if this is the I'm seeing but I'm seeing something similar whenever the user comes back to the tab and a session is retrieved via a visibilitychange event. What's happening is that a broadcast occurs as a result of retrieving the session which the active tab that already retrieved the session also receives that broadcast message and triggers another session retrieval. Potentially, other code paths like update can be causing the same behavior which it triggers a broadcast and the active tab unnecessarily handles that broadcast message

petejodo commented 7 months ago

stepping through the code for the visibiltychange example

  1. visibilitychange calls _getSession
  2. _getSession calls getSession with broadcast set to `true
  3. getSession triggers broadcast
  4. broadcast handler triggers another _getSession call

due to the broadcast handler calls _getSession with storage event, it prevents any more session retrievals from happening

petejodo commented 7 months ago

this is impacting v5.0.0-beta.5

Denoder commented 6 months ago

the solution here would be to edit this line:

https://github.com/nextauthjs/next-auth/blob/9a5416bdf226099c457badd3d7d7d9f922c9b1a7/packages/next-auth/src/react.tsx#L400

and make it:

__NEXTAUTH._session = await getSession({ broadcast: false })

since getSession by default calls storage to broadcast, the visibiltychange gets called calls getSession({ broadcast:false }), it doesn't loop back into a storage broadcast, but instead just updates the user and ends at that, so everything else that explicitly calls storage will only do it once, and every other event name will have broadcast off and call once.