getClaims JwtPayload not updating

I'm migrating to getClaims, but when I make a change on user_metadata for example, it doesn't get updated - normally expected. When I do .refreshSession() before getting claims, I get latest changes normally, but whenever I remove refreshSesssion claims go back to old version. I expect to get latest changes on claims after I call refresh once time, what am i missing or is this a bug ? I want to get latest changes on claims after i make an update basically ?
16 Replies
garyaustin
garyaustin4w ago
Probably need more info. Are you using asymmetric JWT's with this? How are you looking at the claims in each case? How are you updating user_metadata? In general the JWT claims will only reflect user_metadata changes made when the JWT gets refreshed.
Fëanor
FëanorOP4w ago
yes, using asymmetric new api keys, getting claims using
const { data, error } = await supabase.auth.getClaims();
const { data, error } = await supabase.auth.getClaims();
I updated metadata through dashboard sql editor. Changes reflected when user logged out and re-login. I also see changes reflected if I call
await supabase.auth.refreshSession()
await supabase.auth.refreshSession()
just before getting claims I normally expect await supabase.auth.refreshSession() to permanently refresh jwt payload, but whenever I do a claims call without refreshSession called, it uses old jwt payload again
garyaustin
garyaustin4w ago
This would say somehow you are returning to an older JWT between your tests? getClaims will not reflect your changes to the user table until the JWT does refresh. Can you log out the expire time claim from both cases and see if you are gong back to an older JWT?
Fëanor
FëanorOP4w ago
I tried that, it'll indeed revalidate claims and works as intended, but between data changes its not very ideal to logout the client each time ? or is it ?
garyaustin
garyaustin4w ago
RefreshSession should update the session including the JWT.
Not sure what you are doing in your testing to run again without the refreshSession. But at least for plain supabase-js it stores the session in local storage so should have the refreshed JWT. SSR does the same thing with a Cookie. There is no way to know if auth.users changed in a REST client without refreshSession, getUser or signout/signin.
Fëanor
FëanorOP4w ago
to be more clear case1: 1-get claims 2-change something on payload through dashboard sql editor 3-get claims result: claims not updated (expected) case2: 1-get claims 2-change something on payload through dashboard sql editor 3-call refreshSession 4-get claims result get claims has updated payload case3: 1-get claims 2-change something on payload through dashboard sql editor 3-call refreshSession 4-get claims 5-result get claims has updated payload 6-call get claims again without invoking refreshSession before result: see old payload even though i get updated payload on step4 case4: 1-get claims 2-change something on payload through dashboard sql editor 3-logout and login, then getClaims result: get updated claims each time i call it without refreshing session
garyaustin
garyaustin4w ago
case 3... How are you calling getClaims in relation to the previous refreshSession / getClaims? If you have inline code ... refresh, getC, getC are you saying the 2nd getC does not work?
Fëanor
FëanorOP4w ago
I have this code:
export async function getUserClaims(supabase: SupabaseClient): Promise<UserClaims> {
// await supabase.auth.refreshSession()
const { data, error } = await supabase.auth.getClaims();
// some object destructing and creating userClaims
return userClaims;
}
export async function getUserClaims(supabase: SupabaseClient): Promise<UserClaims> {
// await supabase.auth.refreshSession()
const { data, error } = await supabase.auth.getClaims();
// some object destructing and creating userClaims
return userClaims;
}
for supabase param, i provide server client and this code runs on ssr. after update, it continues to show old value, but it shows updated value if i uncomment this refresh line, but even after using it with refresh line uncommented and see the updated payload a few times, after i comment refresh line i'm getting old payload from getClaims again
garyaustin
garyaustin4w ago
I think something is going wrong with your session management between those two clients/functions. Try logging the session details out and seeing if you are getting an old session that did not get refreshed. That eliminates getClaims and new JWTs as the issue and means your session handling is not correct. I won't be any/much help with that as I don't use SSR.
Fëanor
FëanorOP4w ago
so, normally if i use the same client and refresh session on it, claims should be updated as well, do i get it right ? in that case i need to investigate whats wrong with sessions or clients
garyaustin
garyaustin4w ago
SSR I think coordinates all session data in the cookie. I assume if you call refreshSession it knows to update the cookie for use in other sections of code. But you have to follow certain processes to insure the clients are all working with the current cookie.
Fëanor
FëanorOP4w ago
aside from claims i get all clients works properly - also clients are not much different than in the offical docs, cookies updated properly
garyaustin
garyaustin4w ago
Are you using refreshSession or just relying on the built in refresh? Change your JWT expire time to like 5 minutes and see if your new claim shows up if you just wait 5 minutes is another check. But log out the actual session info and look at the expire time and see if they are all the same after you have done a refresh session. If not then something is going wrong. Probably best then to ask a new topic about refreshSession and SSR Normally an old session would work for REST DB calls until it actually expires even if you refreshed the session in another spot in your code. Only getUser actually checks if the session is really the current one versus just the JWT.
Fëanor
FëanorOP4w ago
session and token timestamps version1 { "session_id": "39fa546f-b294-4737-8c90-aa806015828d", "exp": 1754178645, "iat": 1754175045, } session and token timestamps version2 { "session_id": "39fa546f-b294-4737-8c90-aa806015828d", "exp": 1754178513, "iat": 1754174913, } here's an interesting point, when i run it without calling refreshSession I get version2, with refreshSession I get version1 but the thing is even though session_id fields are exactly the same between objects, exp and iat are completely different
garyaustin
garyaustin4w ago
I'm not really up on what session id represents. It may be a login in session and last a long time with multiple refreshes of the jwt. This makes sense as Pro users can manage number of sessions and time I believe. But the issue is not with getClaims, but instead with refreshSession where you call it not being propagated by SSR correctly. I suspect that is you needing to do something different but I really don't know the details of SSR and how it deals with multiple server clients and browser client all potentially refreshing the JWT (session). A new topic on this or checking the SSR repository in case there is some bug with refreshSession and not using getUser which does not really look at the current JWT as long as it is valid.
Fëanor
FëanorOP4w ago
I might have solved the issue, I'll double check and test it and write findings here tomorrow, its related to middleware client and server client handle cookies differently whole issue is related to calling refreshSession in ssr and not in route handlers or server actions, setting cookie array can only be done in those functions and not ssr scope. that was the main issue and moving refresh session call to route handlers or server actions solves the problem completely. Yet, partially revalidating the claims even though cookies are not set properly in my case still seems weird and might underline a bug. I appreciate you Gary, even though not directly pointing the issue, you guided me to the correct place to narrow down the issue

Did you find this page helpful?