new API: update
session
#3941
Replies: 61 comments 41 replies
-
Hi, and thanks for opening this. So when the session value changes and is being persisted either in a database or in the HttpOnly session cookie as JWT, the value can only be written server-side, so a trip to the server is inevitable. But I think we could expose a new function, something like const { data: session, update } = useSession()
...
const handleUpdate = async () => {
update((prev) => {...prev: foo: "new session value"})
}
I am currently refactoring the Would like to know what you think, and if you would be willing to open a PR for this @phileasmah |
Beta Was this translation helpful? Give feedback.
-
Hi, glad you liked my idea, didn't know it could only be written server-side, but yea, what you suggested was exactly what I was thinking about! I'm just a student but would love to take another look and possibly open a PR for this. I'm trying to set up my local environment and was just wondering how I should go about trying to implement this with your refactoring in #2236 or should I just try to implement this without your refactor? |
Beta Was this translation helpful? Give feedback.
-
I'll try to get it done this week, so hopefully you will be able to use the I think we will need a new endpoint for this, or we have to extend this one: https://github.com/nextauthjs/next-auth/blob/main/src/server/routes/session.js |
Beta Was this translation helpful? Give feedback.
-
I'm guessing we could just have a Personally, I think a new endpoint would be better overall for readability, maintenance and maybe performance(?) since I don't think much would be needed to change data in the session as opposed to validating/refreshing it. |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
I am using JWT and have a need to update the session (after onboarding). I implemented this "hack" to get proper cookie with JWT. Current No relogin by user needed. Update api/auth/[...nextauth].ts handler: export default async (req: NextApiRequest, res: NextApiResponse) => {
if (req.url === "/api/auth/session?update") {
// Session call updates cookie, redirect to / afterwards
const endResponse = res.end as (cb?: () => void) => void;
res.end = (cb: () => void) => {
res.setHeader("Location", "/");
res.status(301);
return endResponse.apply(res, [cb]);
};
return NextAuth(req, res, options);
} else {
return NextAuth(req, res, options);
}
} When needed, forward user to |
Beta Was this translation helpful? Give feedback.
-
Not sure I understand @huksley. How would that retrieve the new information about a user from an OAuth provider? I'm not really sure what it actually does either. So if NextAuth calls res.end, you redirect to the homepage? Why? Could you please explain? 😊 |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
@phileasmah #2236 is now merged, so if you want to have a look at it and create a PR, please do. I'll try looking at this myself whenever I get the time. |
Beta Was this translation helpful? Give feedback.
-
@balazsorban44 If you need to fetch something from OAuth provider, you can do it manually or in Current implementation of next-auth/src/server/routes/session.js Line 55 in 2155c93 My "hack" is to avoid outputting JSON and instead forward user to other page, as needed. |
Beta Was this translation helpful? Give feedback.
-
And what other page would you send the user? and why? I am just curious to understand. |
Beta Was this translation helpful? Give feedback.
-
Just saw that it was finally released, Thank you guys very much @balazsorban44 and the contributors |
Beta Was this translation helpful? Give feedback.
-
Hi all! Thanks to all contributors for making this happen. I have a little question though. I'm not seeing the expected behavior for update and I wonder if I've implemented incorrectly. I store my whole "User" object inside of my session.user. In here, my user has a city_id which stores the ID of the last viewed city. When the city updates, I await the patch for my user's city_id and then I'm trying to update my session by updating session.user.city_id. When I log the responses, I'm seeing that the user is updated in the DB but not in the session. Wondering what I might be doing wrong. Here is the code that fires when a city is changed:
|
Beta Was this translation helpful? Give feedback.
-
Hi there! It's great to see the progress made on the update() method, and I appreciate your hard work on it. Regarding your question, I have a dashboard for an admin to update user information on my platform, and I am trying to figure out the best way to handle JWTs. I am considering two options: Force the user to sign out, which would require them to sign in again and create a new JWT with updated role data. Update the JWT of a specific user with the new role data. Which approach would you recommend, and do you have any suggestions on how to implement it? Thank you for your help! |
Beta Was this translation helpful? Give feedback.
-
I really appreciate the progress on |
Beta Was this translation helpful? Give feedback.
-
Hi, |
Beta Was this translation helpful? Give feedback.
-
Hi everyone why i am getting this error const { data: session, status, update } = useSession() this is how I am using it Using following versions |
Beta Was this translation helpful? Give feedback.
-
Is there a way to trigger this similarly via |
Beta Was this translation helpful? Give feedback.
-
I want to update the session from the server components, any ideas? |
Beta Was this translation helpful? Give feedback.
-
Maybe this is the solution with getSession():
and in callbacks:
|
Beta Was this translation helpful? Give feedback.
-
I would love to see something similar for SvelteKitAuth. As of today, there is no means to update session manually. Even using POST request. The "trigger" never updates and JWT remains stale. Only workaround is to re-login :( |
Beta Was this translation helpful? Give feedback.
-
I've just created my own session cookie and updated it in the next-auth session flow.
|
Beta Was this translation helpful? Give feedback.
-
Is there a way to get it to work for unauthenticated users? I'm trying to use some code similar to this, but it doesn't fetch the import {useEffect} from 'react';
import {useSession} from 'next-auth/react';
const useMyHook = () => {
const session = useSession()
useEffect(()=>{
if (session.status === 'unauthenticated') {
session.update();
}
}, [session.status])
} I also tried the following, more involved code, but this also did not update the internal session stored by next-auth client-side. import {useEffect} from 'react';
import {useSession, getSession} from 'next-auth/react';
const manualSessionUpdate = async (updateFn) => {
const newSession = await getSession()
updateFn(newSession)
}
const useMyHook = () => {
const session = useSession()
useEffect(()=>{
if (session.status === 'unauthenticated') {
manualSessionUpdate(session.update);
}
}, [session.status])
} |
Beta Was this translation helpful? Give feedback.
-
IGNORE all this comment if you're working with server actions 👇 check my comments below I'm following this guide: I don't receive ./auth.ts
callbacks: {
jwt({ token, trigger, user }) {
if (!user?.id) return token
if (trigger === 'update') {
// This never happen
console.log("JWT_CALLED_UPDATE")
}
token.id = user.id
return token
},
session({ session, trigger, token }) {
console.log("SESSION_CALLED")
session.user.id = token.id
if (trigger === 'update') {
// This never happen
console.log("SESSION_CALLED_UPDATE")
}
return session
},
} I'm logged in. My use case is that after signin I redirect users to What I want is to update the This is what I'm trying import { useSession } from 'next-auth/react'
const navigate = useRouter()
import { useServerAction } from 'zsa-react'
const { update } = useSession({ required: true })
const { execute } = useServerAction(onboarding, {
initialData: { name },
onSuccess: async (response) => {
// DATA is updated here.
await update({ name: response?.data?.name! })
navigate.push('/')
},
}) useServerAction is working nicely. So I think something I'm missing in the client "next": "14.3.0-canary.59",
"next-auth": "5.0.0-beta.18",
"react": "19.0.0-beta-26f2496093-20240514",
"react-dom": "19.0.0-beta-26f2496093-20240514",
|
Beta Was this translation helpful? Give feedback.
-
People from SvelteKit ecosystem, here is how we can pass data from client to server and vice versa - https://blog.aakashgoplani.in/how-to-exchange-data-between-client-and-server-using-sveltekitauth |
Beta Was this translation helpful? Give feedback.
-
I tried different ways to solve the problem of using the update funcion from 'useSession' it turned out that when calling 'update' the 'trigger' on callback session was always async session({ session, token,trigger }) {
if(trigger === "update"){
// do some update stuff here
// this tigger never gets 'update' even though I am calling 'update' from 'useSession'
}
// @ts-expect-error
session.expires = token.user.expiresIn;
// @ts-expect-error
session.user = token.user;
return session;
}, I've also realized that trigger does get 'update' on jtwt callback async jwt({ token, user, trigger, session }) {
if (trigger === "signIn" && user) {
// user is the database info returned by your adapter and from what I can tell is not available in other triggers
token.user = user;
}
if (trigger === "update" && session) {
// the trigger is `update` when calling update from client side useSession().update function
// but `session` is always `undefined`
}
return token;
}, but the problem was that the prop 'session' never reflected the actual value I was passing to the 'update' function from useSession. So I ended up with that solution Instead of calling async function handleSubmitUpdateProfile(values: Admin) {
try {
const csrfToken = await getCsrfToken();
await getSession({
req: {
body: {
csrfToken,
data: { user: { ...user, ...values } },
},
},
});
toast.success("Perfil alterado!", {
description: "Seu perfil foi alterado com sucesso!",
});
window.dispatchEvent(new CustomEvent("userUpdated"));
} catch (e: any) {
toast.success("Erro ao alterar o perfil", {
description:
"Lamentamos, houve um erro inesperado ao alterar o perfil do administrador.",
});
}
} and in my jwt callback async jwt({ token, user, trigger, session }) {
if (trigger === "signIn" && user) {
// user is the database info returned by your adapter and from what I can tell is not available in other triggers
token.user = user;
}
if (trigger === "update" && session) {
await apiCore.post("/user/admin/update", {
name: session.user.name,
email: session.user.email,
telephone: session.user.telephone,
id: session.user.id,
});
// session is the data sent from the client in the update() function above
// Note, that `session` can be any arbitrary object, remember to validate it!
token.user = session.user;
}
return token;
}, this solved my problem, now I am getting the trigger 'update' and the actual data I'm sending through getSession... it might not be the best solution but it definetly solved the problem |
Beta Was this translation helpful? Give feedback.
-
Update on 25/03/2023: #3941 (comment)
Discussed in #2267
Originally posted by phileasmah June 28, 2021
Summary 💭
Include a
setState
to mutate thesession
state when using theuseSession()
hook.Description 📓
In my app, I'm trying to build a settings page for profiles, like changing the display name etc, but I found that after changing the display name (name in database has been changed), the
session
state inuseSession()
stayed the same.So, I was trying to find a way to mutate the session object of the current user and stumbled upon
getSession()
which (correct me if I'm wrong) is suppose to get a new session and replace it with the current one but according to thisissue
it doe not work as intended.I was looking at the source code and thought wouldn't it be easier to just allow us to mutate the session state directly? (or are there security concerns I'm not aware of? In which case, it would be interesting to know). Looking at the code, it should be pretty easy to implement.
An advantage when compared to
getSession()
would obviously be that 1 less call needs to be made to the database, but again, I'm not sure if I am glossing over any security concerns etcThere are probably other related issues, which could be resolved with this. I'll try to gather them below, but if anyone reading this knows any, please comment below, and I would also like to hear your thoughts on this!
Beta Was this translation helpful? Give feedback.
All reactions