Calling useSession().update with no body should not set trigger = undefined in server JWT callback
#13451
ElijahMSmith
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Goals
Always set
trigger = "update"in the jwt callback parameters when invokinguseSession().updatefrom the client, regardless of whether a body was sent.Non-Goals
jwtcallback between a body/bodyless update request.Background
It is a documented feature that calling
update()from theuseSession()hook will pass anundefinedtrigger instead ofupdate.https://authjs.dev/reference/nextjs#parameters
- user sign-in: First time the callback is invoked, user, profile and account will be present.
- user sign-up: a user is created for the first time in the database (when AuthConfig.session.strategy is set to "database")
- update event: Triggered by the useSession().update method. In case of the latter, trigger will be undefined.
My use case is that we have a NextJS app with a BFF that manages authentication with our custom OAuth2 provider running in a separate microservice. We receive an access token to the external API from that provider and make direct API requests with the bearer token, rather than serving an API from the NextJS backend. We've opted into the JWT session strategy so that the access token can live encrypted on a browser cookie and the backend server only has to decrypt it and let the browser store the access token in memory.
We want to trigger a session update from the browser when the access token is expired to obtain a new access token from the provider (implemented with refresh tokens, but that is not super important here). This goes to the
jwtcallback, and so I naturally wrote some code looking fortrigger = "update", which I expected to be set when callinguseSession().update.However, the actual behavior I noticed is that when I call
update()with no argument, the trigger is set to undefined but with any argument (ex:update({})) it is instead "update".In
next-auth@5.0.0-beta.31,useSession().update(next-auth/react.js):and
fetchData(next-auth/lib/client.js):No arguments => GET with no body.
{} => POST with JSON string body.
In
@auth/core/lib/index.js, the GET branch callsactions.session(options, sessionStore, cookies)with noisUpdateargument, while the POST branch calls
actions.session(options, sessionStore, cookies, true, request.body?.data).In
@auth/core/lib/actions/session.js:On a GET,
isUpdateis falsy, so thetriggerkey is never added and thecallback sees
trigger === undefined.Our
jwtcallback only rotates ontrigger === "update"(
webgui/ark-webgui/app/auth/[...nextauth]/route.ts):Result: refresh fires →
jwtruns withaccountundefined andtriggerundefined → the same expired token is returned.
There are legitimate cases where the
jwtcallback may be called with trigger = undefined:But if I call
update()client side, I am deliberately telling the server to update my session (even if I am not passing any new data to spread into the session object). In this case, I do this so that my callback can use its OAuth2 refresh token to get a new access token and store it in the new session.Proposal
The
updatefunction from theuseSession()hook should always call the POST endpoint to indicate the session should be updated, even if there was no body passed (undefined). A user should not callupdate()from theuseSession()hook if there is no intended action to update the session, they could instead just read the session value fromuseSession()or any of the other client methods.I expect that the GET route on the server is used by more than just the
update()function and matches the HTTP method with the callback function - return the JWT from the active session. Thus, this fix should be client-side to theuseSession()hook where this unexpected behavior occurs.Beta Was this translation helpful? Give feedback.
All reactions