Skip to content
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

server plugin doesn't update server session #314

Open
kleinpetr opened this issue Dec 25, 2024 · 1 comment
Open

server plugin doesn't update server session #314

kleinpetr opened this issue Dec 25, 2024 · 1 comment

Comments

@kleinpetr
Copy link

Hi,

I am facing an interesting situation, where I use listen to a hook in the nitro plugin to extend session by user data, currently I have a custom UserSession interface which includes user and data fields.

When user is logged in (for example over SSO) I set just data which includes only session data such as userId, tokens, expirations, etc.

Then I have this plugin

sessionHooks.hook('fetch', async (session, event) => {
    if (!session.data) return

    const authSession = await useDrizzle().query.sessions.findFirst({
      where: eq(tables.sessions.id, session.data.id),
    })

    if (!authSession) {
      console.error('Session not found')
      clearUserSession(event)
      return sendRedirect(event, '/')
    }

    const user = await useDrizzle().query.users.findFirst({
      where: eq(tables.users.id, session.data.userId),
    })

    if (!user) {
      console.error('User not found')
      clearUserSession(event)
      return sendRedirect(event, '/')
    }

    await setUserSession(event, {
      user: user,
    })
  })

Based on the session I get current user data, to keep fresh data.

But now I have full session on the client side, when I debug the entire session comes from useUserSession() it contains both data and user

but when I debug const session = await getUserSession(event) on the server side, it contains only data which was originally set after login.

Interesting thing is, when I set something like setUserSession(event, {data, user: {test: 'test'}) after the login. Then I can see data and user objects on the client side again, but the user has also test property. But when I debug server session, it includes data again and the user as well but only with the test property.

Thank you for clarification

@claytonchew
Copy link

claytonchew commented Jan 14, 2025

I previously reported a similar issue in #294, but it turns out the problem isn’t related to the server utils – it stems from Nuxt’s SSR behavior.

During SSR, calls to clearUserSession(), setUserSession() and replaceUserSession() don't work as the Set-Cookie header isn't returned. These function only works when:

  • client is calling an api route (not during SSR), or
  • if you are using the "fetch" hook to extend your session, client has to call fetch() from useUserSession().

I haven’t had the time to investigate this further for a potential fix since the issue lies within Nuxt’s SSR.

Temporary Workaround:

To refresh the user session using the "fetch" hook, somewhere in your app.vue script setup, add the following:

onMounted(() => {
  useUserSession().fetch()
})

This will ensure "GET /api/_auth/session" is called at least once from the client on page reload, returning Set-Cookie header and refreshing session cookie.

The downside of this workaround is that any calls to database within the "fetch" hook will be repeated again – not ideal for performance reason.

Better Workaround:

A better workaround would be not use the "fetch" hook, but rather a custom endpoint that does the same thing:

// server/api/_auth/refresh.get.ts
export default defineEventHandler(async () => {
  const session = await getUserSession(event);
  if (!Object.keys(session).length) {
    return;
  }
  
  // extend session code
});

Then, somewhere in your app.vue script setup:

onMounted(() => {
  $fetch("/api/_auth/refresh");
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants