refetchInterval does not send "update" trigger
Environment
System:
OS: macOS 14.3
CPU: (12) arm64 Apple M2 Pro
Memory: 2.55 GB / 32.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 18.18.0 - ~/.nvm/versions/node/v18.18.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.0/bin/yarn
npm: 10.3.0 - ~/.nvm/versions/node/v18.18.0/bin/npm
pnpm: 8.7.6 - ~/.nvm/versions/node/v18.18.0/bin/pnpm
bun: 1.1.8 - ~/.nvm/versions/node/v18.18.0/bin/bun
Browsers:
Chrome: 125.0.6422.78
Safari: 17.3
Reproduction URL
https://github.com/sandervspl/next-auth-refetchinterval
Describe the issue
I might be misunderstanding the point of refetchInterval, but currently it does not pass a value to the "trigger" prop in the JWT callback. The update() function DOES have a "update" value on trigger in the JWT callback.
When I read the docs (https://next-auth.js.org/getting-started/client#refetch-interval) there is a link to an "alternative" option that uses the update() function to achieve the same thing. So my understanding is that refetchInterval should also fire with an "update" trigger, just like the update() function does.
How to reproduce
- Clone the repo
npm installnpm run dev- go to http://localhost:3000/
- Login with any username
- Check the terminal for logs to see that the jwt callback is fired without a trigger (should be "update")
Expected behavior
I expect the JWT callback trigger to have a value of update when I read the docs.
I have been facing a same issue. After email is verified I want to update the session because it holds the isEmail verified property. The v5 docs allow you to use the unstable_update method but it does not seem to work. Here is how I am using it. `import { auth, unstable_update } from "@/auth"; // Correctly import unstable_update import User from "@/utils/db/models/user.model"; import { NextResponse } from "next/server"; import dbConnect from "@/utils/db/dbConnect";
export async function GET(request) { const { searchParams } = new URL(request.url); const token = searchParams.get("token"); console.log("token", token);
const session = await auth();
if (!session) {
return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
}
await dbConnect();
const userId = session.user.id;
const user = await User.findById(userId);
if (!user) {
return NextResponse.json({ message: "User not found" }, { status: 404 });
}
const currentTime = new Date().getTime();
if (
token === user.verificationToken &&
currentTime < user.verificationTokenExpiry
) {
user.isVerified = true;
await user.save();
// Update the session and token with the new isVerified status
await unstable_update({
user: {
...session.user,
isVerified: true
}
});
// console.log("Route Session", session);
return NextResponse.json({ message: "Verification successful" });
}
return NextResponse.json(
{ message: "Verification failed" },
{ status: 400 }
);}`
import NextAuth from "next-auth"; import GitHub from "next-auth/providers/github"; import Google from "next-auth/providers/google"; import CredentialsProvider from "next-auth/providers/credentials"; import { SignInWithEmailAndPassword, oauthSignIn, } from "@/actions/user/user.actions";
const providers = [ Google, GitHub, CredentialsProvider({ name: "Credentials", credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { const user = await SignInWithEmailAndPassword(credentials); // User verification logic if (user.status === 400) { return null; } return user.data; }, }), ];
export const providerMap = providers.map((provider) => { if (typeof provider === "function") { const providerData = provider(); return { id: providerData.id, name: providerData.name }; } else { return { id: provider.id, name: provider.name }; } });
export const { handlers, auth, signIn, signOut, unstable_update } = NextAuth({ providers, pages: { signIn: "/auth/sign-in", }, callbacks: { async signIn({ user, account }) { if (account.provider === "google" || account.provider === "github") { const { name, email, image } = user; const payload = { name, email, avatar: image, authType: "Oauth", };
await oauthSignIn(payload);
return true;
}
// Default to allow sign-in
return true;
},
async jwt({ token, user }) {
// Add user information to the token during sign-in
if (user) {
token.id = user._id.toString();
token.email = user.email;
token.name = user.name;
token.isVerified = user.isVerified;
token.picture = user.avatar;
}
return token;
},
async session({ session, token }) {
// Add custom properties to the session object
session.user.id = token.id;
session.user.email = token.email;
session.user.name = token.name;
session.user.image = token.picture;
session.user.isVerified = token.isVerified;
return session;
},
}, });
same problem, with “next-auth”: “^5.0.0.0-beta.25”, I think when using credentials provider, I don't know if it has something to do with it.
unstable_update() doesn't seem to work, and in order for update() to do the function that the (v4) documentation says, I have to send an update(null) for the trigger: update to be executed
I am taking as reference v4 because as far as I understand the documentation in v5 is incomplete.
I haven't explored it thoroughly, but I have another project where I use magic links and I don't have these problems
Is this being worked on? Very strange behavior, trigger is always undefined, except on sign in.
Is this being worked on? Very strange behavior,
triggeris always undefined, except on sign in.
that might be how u are sending the data from the client side. I had achieved triggering successfully it just had to do with how I was sending the data.
I also encountered the same issue where trigger was undefined in the JWT callback. Following @nasatome's suggestion, I was able to resolve it by using update(null). This successfully triggers the JWT callback with trigger: "update" as expected.
Thank you for sharing the workaround!