-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getSession call does not trigger session object update until window loses focus #596
Comments
I just noticed the same issue: if I call The first thing would be that we need to pass However, the code responsible to update the session following such a message has an explicit check to not update the session if the window is coming from the same window: this line The problem is that the only way to update the Context is to call the internal I think this part of the doc is misleading: It's actually "you can can trigger an update of the session object across all other tabs/windows". Are we trying to do something that is not intended or is there a way to imperatively trigger a session update that would update the context of the current window? |
@ValentinH @blms Thanks to you both! This is helpful and I think we understand it well enough to fix now. It's supposed to work as described in the docs, but I think is inadvertently relying on localStorage to trigger the event and the way localStorage events work is they only trigger updates in windows other than the window that triggered the event. |
Hi, is there a temporary solution? |
For now, I'm doing a full-reload navigation as a workaround. |
I'm using this workaround for now: #371 (comment) |
@iaincollins couldn't this be the cause? Lines 52 to 55 in 65504d6
Although MDN says:
"another document" might just mean how you described it. |
In case someone looking for a workaround. I just replace useSession hook and use const { data, error } = useSWR('/api/auth/session', async (url) => {
const res = await fetch(url)
if (!res.ok) {
throw new Error()
}
return res.json()
})
// For loading
if (!error && !data) {
}
// For no session
if (!data) {
}
// For session existing
if (data) {
}
// Make change on user
async function handleSubmit(e: React.SyntheticEvent) {
// e.g. update user profile
// Get the latest session
mutate('/api/auth/session')
} |
I'm using this workaround right now (see demo request handler below for GET). Essentially this handler is doing what next auth
|
Any news on the issue? following @timshingyu I'm also doing it via import useSWR, { mutate } from 'swr'
// allows to mutate and revalidate
export const mutateSession = (data?: Session, shouldRevalidate?: boolean) => mutate('/api/auth/session', data, shouldRevalidate)
// parse the response
const fetcher = (url) => fetch(url).then((r) => r.json())
export function useUser({ redirectTo = '', redirectIfFound = false } = {}) {
const [, loading] = useSession() // check if provider is still loading (avoid redirecting)
const { data: session, isValidating } = useSWR<Session>('/api/auth/session', fetcher)
const hasSession = Boolean(session?.user)
const isLoading = loading || (!session && isValidating)
useEffect(() => {
if (!redirectTo || isLoading) return
if (
// If redirectTo is set, redirect if the user was not found.
(redirectTo && !redirectIfFound && !hasSession) ||
// If redirectIfFound is also set, redirect if the user was found
(redirectIfFound && hasSession)
) {
Router.push(redirectTo)
}
}, [redirectTo, redirectIfFound, hasSession, isLoading])
return session?.user ?? null
} |
I believe this and #371 deal with a number of different issues. I need to update jwt and session (with jwt:true) after user has logged in, whenever user updates some underlaying data (name or image, for example) via a separate api route handler. This definitely not the case when SWR can help, because /api/auth/session always returns whatever was stored in jwt callback initially. Looks like the jwt callback only receives 'user' on signIn (so, once per session). So, what's the simplest way to make jwt and/or session update without logging out/in (not an option, obviously) and without querying database for changes every time the jwt callback is called? |
I think triggering a re-signin is the easiest method here. this will invoke the jwt callback with the new data, and a second login on most OAuth providers is barely visible as it will be a fast redirect (unless some params explicitly require the user to give their credentials again) |
@balazsorban44 not really viable in case of credentials or email signin and I'm trying to offer both along with some oAuth providers. |
@zanami did you find the right solution for this? I'm in the same situation as you... |
Nope, sorry, I gave up and dropped NextAuth. |
Hi. are there any solution already for this to update client session with getSession? |
One way to trigger the internal session re-validation on the active(!) window (thx to @ValentinH for providing some insights) might be to manually trigger a https://github.com/nextauthjs/next-auth/blob/main/src/client/index.js#L72 document.addEventListener(
"visibilitychange",
() => {
!document.hidden && __NEXTAUTH._getSession({ event: "visibilitychange" })
},
false
) this seems to be a working hack for me that does not require a full page reload or const reloadSession = () => {
const event = new Event('visibilitychange');
document.dispatchEvent(event)
} |
Ok, it works. Doing as @PhilippLgh said : const reloadSession = () => {
const event = new Event('visibilitychange');
document.dispatchEvent(event)
} just works ! it does refresh the session. @balazsorban44 Could this be a way ? |
Can you plaese be mode specific? How to use it in serverside getSession? |
This hack stopped working in NextAuth@4. Not 100% sure why, but haven't been able to get an alternative hack working yet. Anyone have a workaround yet for this in v4? |
any luck on this so far? |
Any solutions/workarounds for latest versions? :) |
Only solution so fat is to call your db and update the session yourself in the session callback... |
Call database many time not really good, btw I use JWT too :( |
Seems to work for me. Here's my set up.
export default function refreshSession () {
const event = new Event('visibilitychange')
document.dispatchEvent(event)
} Here's how I'm using it. function create (data) {
return post('/groups', { name: data.name })
.then(() => refreshSession())
} |
It seems that dispatch event visibilitychange is not helpful for version 4. (I'm using ^4.6.1) The client session state is lost every time the tab is switched or hangs too long. Is there any solution to this problem? Thanks! |
The new implementation uses a BroadcastChannel based on the localStorage API. export default function refreshSession () {
const message = { event: 'session', data: { trigger: "getSession" } }
localStorage.setItem(
"nextauth.message",
JSON.stringify({ ...message, timestamp: Math.floor(Date.now() / 1000) })
)
} Alternatively use |
The solution with In case we don't want to auto-update the session when a user switches windows we're kind of stuck. @PhilippLgh Looks like it's also possible to use the exported import { BroadcastChannel, BroadcastMessage } from 'next-auth/client/_utils'
const reloadSession = () => {
const { post } = BroadcastChannel()
const message: Partial<BroadcastMessage> = {
event: 'session',
data: { trigger: 'getSession' },
}
post(message)
} Unfortunately, it doesn't really trigger XHR to update the session. Even if we add const reloadSession = async () => {
const { post } = BroadcastChannel()
const message: Partial<BroadcastMessage> = {
event: 'session',
data: { trigger: 'getSession' },
}
post(message)
await getSession({
event: 'session',
broadcast: true,
triggerEvent: true,
})
} It's possible that PR #4744 fixes it, but it's still pending review. |
I want to give this issue a bump and see if we can move this along. Not being able to refresh sessions and have updates propagate is a big problem for us. The work that's been done on NextAuth provides a ton of value and I really appreciate it. Unfortunately, not having token refresh is a pretty critical flaw that makes the rest of the library not particularly useful in all but the simplest of cases. It looks like #4744 has been open for some time. Could I kindly ask that it's either merged or it's made clear why it can't be merged so that we can work on an updated solution? |
+1. NextAuth gets me to the 99 yard line and then fumbles the ball by not being able to trigger a session state update from within the client (w/o needing to resort to fragile hackery). Calling getSession exhibits all the right behaviors throughout the stack except for updating state :0( Frankly, I'm surprised to see how old this issue is (and others like it) w/o any resolution for such an essential capability. NextAuth is an overall excellent, well-maintained library IMHO, and super appreciate the contrib, but I may need to bail on it over this issue given the inaction. |
Such an old and important issue, and no progress at all? :( |
Indeed it's so essential but it seems the dev team is focused on NextAuth.js to Auth.js migration. |
+1 , Been having the same issue over here |
Related thread here: #4229 |
Heads up, my earlier suggestion still works (
|
Hi all, let's continue the discussion in #3941, which I think should address this. Here is our latest update: #3941 (comment) |
I'm currently trying to update some page components when the session changes after an
onClick
-triggeredPromise
is fulfilled. Here the functionDeleteGroup
returns aPromise
. I print the value of the session before thePromise
is returned, and then print it again after it is fulfilled by callinggetSession()
.According to the console, everything I've logged looks right. The initial
console.log(session)
output showsgroups
as anArray
of length 2, while the secondconsole.log(await getSession())
output shows it as length 1.However, until the window loses focus, my UI continues to show 2 groups despite the console output clearly showing the result of the
getSession
call having only 1 group. My UI is immediately synced once the window loses focus, so I do not believe there is anything wrong with the way I've written my UI components. If that is the case, why wouldn't mygetSession()
call immediately update the UI accordingly?Apologies if this is a repeat; I find session updating to be the trickiest part of Next-Auth.
The text was updated successfully, but these errors were encountered: