nuxt-auth-utils not updating user on client
Hi, almost complete Nuxt noob here
I'm working on a Nuxt app with
nuxt-auth-utils. Our authentication tokens have a short validity period during which they don't need to be revalidated, so as part of the user session created with setUserSession() we store the expiry time, and then on the client check that time to see if we need to revalidate.
The problem is that, once we do revalidate, the user session on the client is never updated.
The revalidation on the server looks like this:
I can see from the server logs that this gets the correct expiry time from the API, and if I do useUserSession().fetch() on the client I can see the updated value, but the user returned by useUserSession() never updates, no matter what I do.
I've tried setUserSession(), replaceUserSession(), and even createUserSession(), and I can see that the request updates the Nuxt cookie, but the value in useUserSession() is only ever the first one that was set when the user logs in.
I'm totally stuck, so any insight is greatfully recieved!33 Replies
Hi @Hituro. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
You're encountering a common issue in Nuxt apps using session cookies: after updating the session on the server (with setUserSession), the client-side session (as returned by useUserSession) does not immediately reflect the new value—unless you manually call useUserSession().fetch().
This is expected behavior with nuxt-auth-utils, because the session data is stored in a sealed cookie. When you update the session on the server, the new cookie is sent in the response. However, the client-side composable (useUserSession) will only see the updated value after a page reload or after you explicitly call fetch() to re-read the session from the cookie. This is because the composable does not automatically re-fetch the session data after an API call that updates the cookie; it will continue to use the value it had in memory until you tell it to refresh.
From the official Nuxt recipe:
The module exposes a Vue composable to know if a user is authenticated in our application:
...after a successful login, you should call fetch() to refresh the session on the client side and get the updated user data.
Sessions and Authentication
So, after your revalidation API call, you must call useUserSession().fetch() (or the fetch/refreshSession method you destructure from useUserSession) to update the client-side session data. This is the only way for the client to see the new session value without a full page reload.
Summary of what to do:
- After your API call that updates the session, call useUserSession().fetch() on the client to refresh the session data.
- The value in useUserSession().user will then reflect the updated session.
If you already do this and still see stale data, ensure that your API call is actually setting the cookie and that the client is not caching the old value. Also, be aware that useUserSession is not reactive to cookie changes unless fetch() is called.
If you need the session to update automatically after every relevant API call, you could wrap your API calls in a helper that always calls fetch() after a successful response.
The knowledge sources do not mention any automatic reactivity for useUserSession to cookie changes, so manual refresh is required.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@335518469107744768> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
instead of passing your own custom expiry would it not be better to specify the maxAge on the user session?
https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#configuration
Quite possibly. I've just taken over this project from an AWOL dev, so I can't really ask the original reasoning
if you call fetch() it updates the user session
it doesn't automatically update
I could have sworn I tried that already
🤔
And saw the updated result in the fetch, but the next call to
useUserSession() showed the old value. But then I've tried a lot of things in a rather scattershot way, so I'll try it againthe strange thing is
calling
fetch() from useUserSession in the code updates the session value which you'd expect to work
code i'm referencing: https://github.com/atinux/nuxt-auth-utils/blob/main/src/runtime/app/composables/session.ts#L29
i'm wondering if it's maybe a reactivity issueI've just put the fetch back in, and when I go to the next route it still reports the old value
could you show the code?
One sec
ok so when you say it's not updating are yo uchecking
expiry after you call fetchSession() ?Yes, on the next route change the middleware runs again and shows the old value
Let me add some other value to it though, because I'm waiting 5 min between each change on the back end
I'll add some random number to the user
can you see the fetch request in the browser with the correct values
Yes
Ah ha! It's changing the random value 😄
In 2 minutes I'll be able to see if it correctly changes the expiry date as well
It works!
huh what changed?
I am not sure what I changed this time, but apparently it did it
lol
That's a good question. I think last time I used fetch, I was checking the values immediately and they were not updated, of course. Also I was using replaceUserSession instead of setUserSession
Now I have to work out why the jwt is even in the user session
I think it shouldn't be
Because it can get pretty big, and might push the cookie limits
if you were checking them immediately in the same middleware after fetch
the
expiry wouldn't be updated since you destructured it from a reactive value it's no longer reactiveI'm wondering if that's exactly what I did in the middle of my confused floundering, and didn't realise I wasn't even checking the right value
at least it's all sorted now
I should be able to use
loggedIn from useUserSession() rather than having to check the jwt value, right?ye
Ahh wait, I see that the server side code uses
user.jwt throughout
Of course, the server doesn't have persistant state either, I'm being dumbif it's just the server using it you could put it in the
secure part of the session so it's not exposed to the clientThat makes sense. I suspect the original dev just stuffed the whole response into
user because that's easy, no destructuring at all
I'll see if I can make that work 😄
The login route is just:
I guess I would be better destructuring the result and putting part in user and part in serverdepending on what's actually in there yeah it'd probably be better to be explicit so if the api changes for whatever reason you don't end up accidentally exposing something
Well this didn't work:
Not sure why. No errors, but it just doesn't log in
Is that because the value is wrapped in a proxy?
Oh yes,
result.result.jwt.value doesn't make it isntantly fall over 😄the user session object actually has special properties on it
user, secure and anything else you put in there
https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#session-management
if the jwt is only used in nitro (server/) side you can put it in secure which means it doesn't get sent to the client at allAhh, I misnamed it
secure not server 😄i actually thought it said server too