nuxt-auth-utils icon indicating copy to clipboard operation
nuxt-auth-utils copied to clipboard

🐞 Bug Report: getUserSession(event) returns partial session in cachedEventHandler

Open mrkaashee opened this issue 6 months ago • 6 comments

When using getUserSession(event) inside a cachedEventHandler, the returned session object only includes the id:

// inside cachedEventHandler
const session = await getUserSession(event);
console.log(session);
// Output: { id: '99ca50c6-297f-429c-8f53-5903d6ecd74b' }

However, in defineEventHandler, the same call returns the full session with the user object populated:

// inside defineEventHandler
const session = await getUserSession(event);
console.log(session);
// Output includes: session.user = { id, username, roles, etc. }

Expected Behavior

Calling getUserSession(event) should return the same structure and data, regardless of whether the handler is wrapped in defineEventHandler or cachedEventHandler.

Actual Behavior

  • In cachedEventHandler, session.user is missing.

  • In defineEventHandler, session.user is present.

Notes

  • We're not caching session data.

  • Session is being retrieved solely to enrich or filter unrelated cached data.

  • The inconsistency leads to partial functionality or the need for workarounds.

mrkaashee avatar Jul 11 '25 17:07 mrkaashee

I'd honestly like to understand at a core level why I'm seeing similar partial results during normal defineEventHandler execution, but only on a Full Page refresh.

JessicaSachs avatar Aug 07 '25 22:08 JessicaSachs

I initially thought it was an issue with Nuxt Auth Utils, but after digging in, I found that the root cause is in Nitro — specifically, defineCachedEventHandler clones the req/res objects, which breaks session/auth detection. I’ve documented the details here: https://github.com/nitrojs/nitro/issues/3468

Might be worth checking out if you're seeing anything similar or are curious about the underlying behavior.

mrkaashee avatar Aug 08 '25 14:08 mrkaashee

No worries — I found a workaround that works well!

You can use defineEventHandler to handle session logic (e.g. getUserSession()), and then call a defineCachedFunction inside it, passing the user/session data as needed. This way, you avoid the issue with cloned req/res objects.

Let me know if you want a code example — happy to share!

mrkaashee avatar Aug 08 '25 14:08 mrkaashee

I'd honestly like to understand at a core level why I'm seeing similar partial results during normal defineEventHandler execution, but only on a Full Page refresh.

I'm having exactly the same issue, have you found out more about this? Thanks.

tibor-cernak avatar Aug 19 '25 15:08 tibor-cernak

I’ve documented the details here: https://github.com/nitrojs/nitro/issues/3468

mrkaashee avatar Aug 20 '25 14:08 mrkaashee

I believe this is indeed related to Nitro.

I just tested locally in my playground and I cannot reproduce this behavior, can you try with latest Nuxt & Nitro versions?

atinux avatar Sep 09 '25 16:09 atinux

On nuxt 4.2.1 with nuxt-auth-utils 0.5.25 getUserSession(event) also returns an empty session (inside defineEventHandler) only containing the id in contrast to the output of the composable on client side: (keycloak provider, OIDC)

// inside defineEventHandler
const session = await getUserSession(event);
console.log(session);
// Output: { id: '9c6894b5-7d14-41e3-b6ee-c314eebe5647' }

Regular session from composable:

{ "user": 
  { 
     "userId": "bb960eac-f44c-4d8d-ac4f-9f739bfe3126", 
     "firstName": "Test", 
     "lastName": "User", 
     "email": "[email protected]", 
     "preferred_username": "test", 
     "expirationDate": "2025-11-26T12:07:44.447Z" 
  }, 
 "access_token": myAccessToken,
 "refresh_token": myRefreshToken,
 "expires_in": 360, 
 "refresh_expires_in": 420, 
 "loggedInAt": "2025-11-26T12:01:44.447Z", 
 "id": "d6db010c-d68b-483c-adde-ac134652c9bf" 
} 

mpgalaxy avatar Nov 26 '25 12:11 mpgalaxy

On nuxt 4.2.1 with nuxt-auth-utils 0.5.25 getUserSession(event) also returns an empty session (inside defineEventHandler) only containing the id in contrast to the output of the composable on client side: (keycloak provider, OIDC)

// inside defineEventHandler
const session = await getUserSession(event);
console.log(session);
// Output: { id: '9c6894b5-7d14-41e3-b6ee-c314eebe5647' }

Regular session from composable:

{ "user": 
  { 
     "userId": "bb960eac-f44c-4d8d-ac4f-9f739bfe3126", 
     "firstName": "Test", 
     "lastName": "User", 
     "email": "[email protected]", 
     "preferred_username": "test", 
     "expirationDate": "2025-11-26T12:07:44.447Z" 
  }, 
 "access_token": myAccessToken,
 "refresh_token": myRefreshToken,
 "expires_in": 360, 
 "refresh_expires_in": 420, 
 "loggedInAt": "2025-11-26T12:01:44.447Z", 
 "id": "d6db010c-d68b-483c-adde-ac134652c9bf" 
} 

I was able to reproduce this error on an Ubuntu environment, but it works fine on Debian. I made sure to check the versions, and both environments are running [email protected] and [email protected]. This error is quite strange.

@atinux

TutorFx avatar Dec 05 '25 15:12 TutorFx

Using useRequestFetch instead of $fetch to make requests on API routes using getUserSession(event), seems to solve the partial session data issue inside defineEventHandler when a full-page refresh occurs.

I got the idea from here

useRequestFetch documentation

Let me know if this is in fact the right solution.

dankerow avatar Dec 06 '25 05:12 dankerow