K
Kinde•9mo ago
TotalScrub

Refresh claims approach

Hi, I'm trying to figure out how to refresh claims / user details with Kinde. There are few scenarios I'm trying to solve this for: - As part of registration activities a user might be allocated to an organisation & role via the M2M API. Their original access token doesn't have these claims and they end up with forbidden access. I understand the why as the Nuxt server is using the cached values. - Users might have their roles changes within an admin section using the M2M API. If I log the user out and in again, it works fine. If I refresh the claims using refreshUserClaims() in the management API (either via the JavaScript SDK or .NET SDKs) then nothing happens and the user still gets forbidden access issues from my application (I do get a success response from Kinde when calling the refresh API). With Kinde, how are you supposed to handle this? Ideally without logging out and in again.
31 Replies
Woet
Woet•9mo ago
Just came here to ask the exact same question, cause I'm having the same use-case as described above and want the user changes reflected immediately in my app instead of them only being reflected after logging out and back in again
Oli - Kinde
Oli - Kinde•9mo ago
Hey @Stephen and @Woet, Thanks for reaching out on refreshing claims. The logic to refresh claims is different per SDK. Are you able to let me know what SDKs you want to know how to refresh claims, and I can get back to you with some advice?
Woet
Woet•9mo ago
Hey @Oli - Kinde , thanks for the response! I'm currently using the Next.js app router SDK
TotalScrub
TotalScrubOP•9mo ago
Hey @Oli - Kinde. - I'm using Nuxt (Vue) to perform auth / registration using your SDK. In the case of the API call to refreshing claims I'm using your TypeScript SDK as that's your current guidance. - I'm also using the .NET SDK to try and force a claims refresh. My .NET APIs are the one's doing the M2M 'heavy lifting', I'm only using TypeScript SDK to do the claims refresh as that is the Nuxt server which 'owns' the Kinde cookie / JWT. (I do also force a claims refresh for actions which change claims values in the .NET API but I understand why it does nothing, my .NET API only validates the JWT with Kinde) I guess one question I would have for your team is why an API call to Kinde's servers via refreshUserClaims() is needed at all, at least in terms of understanding what is actually happening. I would have thought just forcing a refresh of the users auth token would in turn refresh the claims. It's been a minute since I looked at your Nuxt SDK source code, but IIRC there was another method to refresh claims (that didn't require a M2M app) but because it was using your sessionManager the session manager already saw that there was a 'valid' auth token and so doesn't call your servers to refresh, at least to my understanding. P.S. working on Christmas day Oli? That's dedication 😁
Oli - Kinde
Oli - Kinde•9mo ago
Hey @Woet, We have some major changes to our NextJS SDK that will fix a whole range of refresh claims issues - so stay tuned for this.
Oli - Kinde
Oli - Kinde•9mo ago
I'm using Nuxt (Vue) to perform auth / registration using your SDK. In the case of the API call to refreshing claims I'm using your TypeScript SDK as that's your current guidance. I'm also using the .NET SDK to try and force a claims refresh. My .NET APIs are the one's doing the M2M 'heavy lifting', I'm only using TypeScript SDK to do the claims refresh as that is the Nuxt server which 'owns' the Kinde cookie / JWT. (I do also force a claims refresh for actions which change claims values in the .NET API but I understand why it does nothing, my .NET API only validates the JWT with Kinde)
It sounds like you are using the TypeScript SDK to refresh claims and it's not working as expected. So I would suggest raising an GitHub issue on the TypeScript SDK GitHub repo around your use-case of refreshing claims - it's easier for my expert TypeScript teammate to address TypeScript queries raised on GitHub when he has time to look into them
GitHub
GitHub - kinde-oss/kinde-typescript-sdk: Kinde SDK for TypeScript
Kinde SDK for TypeScript. Contribute to kinde-oss/kinde-typescript-sdk development by creating an account on GitHub.
Oli - Kinde
Oli - Kinde•9mo ago
I guess one question I would have for your team is why an API call to Kinde's servers via refreshUserClaims() is needed at all, at least in terms of understanding what is actually happening. I would have thought just forcing a refresh of the users auth token would in turn refresh the claims. It's been a minute since I looked at your Nuxt SDK source code, but IIRC there was another method to refresh claims (that didn't require a M2M app) but because it was using your sessionManager the session manager already saw that there was a 'valid' auth token and so doesn't call your servers to refresh, at least to my understanding.
By default, Kinde caches tokens for performance. The cache becomes invalid when user information is updated via UI or API, including: - Profile information updates - Organization membership changes - Role changes - Permission updates - Property changes - User-level feature flag updates Why refreshUserClaims() is needed: There are specific scenarios where individual user tokens don't automatically update, including: - Feature flag changes at organisation/environment level that users inherit - Permissions added to a role that the user has For these cases, the refreshUserClaims endpoint explicitly invalidates the cache for that specific user. This ensures the next token refresh will pull fresh claims from Kinde rather than using cached data. Token Refresh Behaviour You raise an interesting point about the session manager and token validation. While I can't speak to the specific Nuxt SDK implementation, I can explain that just refreshing an auth token alone may not force new claims if the cache is still valid. The refreshUserClaims endpoint specifically invalidates that cache to ensure fresh data on the next token refresh. Let me know if you have any further questions.
P.S. working on Christmas day Oli? That's dedication 😁
We keep our eyes on Kinde businesses and systems, whilst you enjoy your holiday period 😉
TotalScrub
TotalScrubOP•9mo ago
Thanks @Oli - Kinde I've added to https://github.com/kinde-oss/kinde-typescript-sdk/issues/63 as I suspect this 'behaviour' might be the root cause of the issue and it may be intentional, not a bug. If it's intentional I'm presuming it's because different organisations can have different authentication policies, particularly for your upgraded Organisations.
GitHub
Bug: unable to reload users information when reassigning organizati...
Prerequisites I have searched the repository’s issues and Kinde community to ensure my issue isn’t a duplicate I have checked the latest version of the library to replicate my issue I have read the...
Oli - Kinde
Oli - Kinde•9mo ago
Hey @TotalScrub, Thanks so much for raising this GitHub issue. My TS teammate will look at this when he is back online in the new year. We are in the process of building out our js-utils package. Once its it at a state we are comfortable with, we will get all our JS-based SDKs to depend on the js utils package. I am confident our js utils package solves your token refresh issues, e.g. when reassigning orgs. Please don't hesitate to raise anymore GitHub issue - they are the best way for my teammates to investigate and communicate on our progress on issues that come up.
GitHub
GitHub - kinde-oss/js-utils
Contribute to kinde-oss/js-utils development by creating an account on GitHub.
TotalScrub
TotalScrubOP•9mo ago
Thanks @Oli - Kinde, any rough timeframe for when you think you might have the js utils package in place? Right now it's just annoying, because I don't have any customers as I build out my MVP. But it would be a significant issue for me were I live, to the point where I'd need to heavily change my onboarding workflow to work around it.
Oli - Kinde
Oli - Kinde•9mo ago
Hey @TotalScrub, I cannot provide any timelines at the moment. But when my teammate is back online on Jan 6 his #1 priority will be getting the new JS Utils package live.
TotalScrub
TotalScrubOP•9mo ago
NP @Oli - Kinde I understand. If I could get some rough ballpark at some point in Jan once your teammate has a better sense of the effort involved that would be appreciated as it would allow me to plan accordingly. E.g. if I can just wait for it to be released, if I need to do a workaround, or if I just go with early customers and advise them of the issue / workaround. Not expecting / asking it to be delivered in Jan, just some 'no promises' indication of when it might drop
Oli - Kinde
Oli - Kinde•9mo ago
Hi @TotalScrub, Totally understand info around when you can expect the new JS Utils package. I am on break from New Years until Jan 13, and I will speak to my teammate then and post here when we think the new JS Utils package will be released.
TotalScrub
TotalScrubOP•9mo ago
@Woet if you follow the GitHub thread https://github.com/kinde-oss/kinde-typescript-sdk/issues/63 it might solve your issue for you. With guidance from Coel (Kinde) I was able to redirect the user to log in (with no prompt so they don't see the Kinde UI) with the organisation and get the expected claims. cc @Oli - Kinde
GitHub
Bug: unable to reload users information when reassigning organizati...
Prerequisites I have searched the repository’s issues and Kinde community to ensure my issue isn’t a duplicate I have checked the latest version of the library to replicate my issue I have read the...
Woet
Woet•9mo ago
@Stephen thanks for sharing! I think our needs to refresh claims are similar, so I'll take a look if this thread can help me. My exact use-case is that if an ADMIN changes the role of a user, that the change in permissions is reflected immediately for that user after changing the role. So what I think would need to happen, is that the change in roles done by the ADMIN user, needs to trigger a refresh of the claims for another user. Same for when deleting users
TotalScrub
TotalScrubOP•9mo ago
Ahh, my use case might be slightly different @Woet.
The problem was that upon Kinde user creation the user didn't belong to any Kinde organisations (and roles are assigned to users in an org, not to the user itself). After initial registration I would then assign the user to the appropriate organisation. I would call refreshUserClaims() using Kinde's Management API but it did nothing. Based on the GitHub thread I later learned it was because the user was still signed into no organisations and I needed to sign the user into the organisation they had been added to (which could be done 'silently'). This fixed my issue. But I still also need to start working on your use-case at some point as well. According to Kinde's document this should just happen - https://docs.kinde.com/authenticate/manage-authentication/sync-with-kinde/. However, most systems will cache a valid JWT so it isn't clear to me how a web server (or browser) would know that the JWT is no longer valid unless it's using something like Token Introspection (https://www.oauth.com/oauth2-servers/token-introspection-endpoint/) or as suggested by Kinde using short expiry tokens. @Oli - Kinde I know you're on leave, but it would be good if we could get some guidance on this when you get back, happy to jump on a call as well. It's likely it's just documentation but I would say for many developers (including myself) it would be good to get some more crystal clear guidance on how this works to save on confusion.
Kinde docs
Keep your product in sync with Kinde
Our developer tools provide everything you need to get started with Kinde.
OAuth 2.0 Simplified
Token Introspection Endpoint - OAuth 2.0 Simplified
When an OAuth 2.0 client makes a request to the resource server, the resource server needs some way to verify the access token. The OAuth 2.0 core spec
Paul E
Paul E•2mo ago
I know this an older thread, but I was wondering - how are we supposed to do the token refresh in SvelteKit 2? @Oli - Kinde Thanks 🙂
Roshan
Roshan•2mo ago
Hi Paul E,

If you are using our SDK. Token refresh in SvelteKit 2 is handled automatically by the SDK. Just make sure you’ve included the offline scope in your config (KINDE_SCOPE=profile email offline openid). You can retrieve the access token like this:
const access_token = await kindeAuthClient.getToken(request as unknown as SessionManager);
const access_token = await kindeAuthClient.getToken(request as unknown as SessionManager);
No need to manually refresh—Kinde handles it behind the scenes.

Let me know if this is what you had in mind, and if there's anything else I can assist with.
Paul E
Paul E•5w ago
Hi Roshan, thank you for your message! When I change a user role, claim or custom property of the ID token on the server side, then I want to silently refresh the client token, without the user having to logout / login again. There are two casses: a) process is synchronously (client calls server, server changes property) I b) process is async (server changes property without user/client interaction) I wrote the following helper, but it doesn't really work reliable (? maybe it does, but not sure) to refresh the token on the client ('prompt' set to 'none'). Do you plan to offer an official helper in the SvelteKit SDK to do something like this, or am I missing something? 🙂 see message.txt attachment
Paul E
Paul E•5w ago
My code snippet solves a) process is synchronously, but what about b) - do I have to wait for a token refresh cycle here? Thanks for your support!
Roshan
Roshan•4w ago
Hi Paul E, Thanks for your question. You’re correct that there’s no way to “push” new claims into an already issued token — a new token has to be issued for the changes to appear. Here’s how we recommend handling each scenario: (a) Synchronous (client calls server, server changes claims/roles) 1. After changing the user’s roles/claims on the server, call the Management API refreshUserClaims endpoint for that user. 2. On the client, call kindeAuthClient.getToken(request as SessionManager). If the user has a valid session, the SDK will refresh the token silently and return updated claims. (b) Asynchronous (server changes without client interaction) - Best UX: Send the client a notification (via SSE/WebSockets/in-app signal) that claims have changed, then call getToken(...) to trigger a refresh. - Simpler approach: Lower the ID token lifetime so regular SDK refreshes pick up changes sooner. - Critical paths: For sensitive actions, have the backend verify the user’s permissions directly via the Management API to ensure the latest state. A few notes on your current helper: - prompt=none only works if the Kinde session cookie is present and valid; otherwise, the user will be prompted to log in. - Calling refreshUserClaims doesn’t update the current token — it simply invalidates the cached claims so the next token issuance reflects the changes. - Where possible, try getToken(...) first, as the SDK’s built-in refresh will handle most cases without needing to redirect. At the moment, there isn’t an “official” SvelteKit helper that combines claim invalidation and silent refresh into one call. The supported path is what you’re doing now — SDK-managed refresh via getToken(...) or silent re-auth via prompt=none if needed.

Let me know if you have any other questions or if there’s anything else I can assist you with.
Paul E
Paul E•4w ago
Hi Roshan! Thank you for your response! How do I know that getToken has given me a new token, such that I don’t need to do a token refresh using the redirect with prompt=none? When is the Kinde session cookie not present or invalid? Does getToken refresh both the ID and access tokens? I think it would be great to have official helper methods to make this easier for someone jumping into Auth with Kinde 🙏🏻 The current user feedback is that having to login too often because the token lifetime ran out is very annoying for them. (I am using passwordless login) That’s why I am actually considering to increase the token lifetime from the Kinde defaults.
Roshan
Roshan•4w ago
An official helper for this kind of workflow would definitely streamline things — I’ll pass that suggestion on to the team.

Thanks for the feedback, Paul.
Paul E
Paul E•4w ago
Hello Roshan, when trying to call getToken on the client (not server) I receive following error:
Cannot import $env/dynamic/private into client-side code. This could leak sensitive information.
Imported by: node_modules/@kinde-oss/kinde-auth-sveltekit/dist/index.js.
Tips:
- To resolve this error, ensure that no exports from $env/dynamic/private are used, even transitively, in client-side code.
- If you're only using the import as a type, change it to `import type`.
- If you're not sure which module is causing this, try building your app -- it will create a more helpful error.
Cannot import $env/dynamic/private into client-side code. This could leak sensitive information.
Imported by: node_modules/@kinde-oss/kinde-auth-sveltekit/dist/index.js.
Tips:
- To resolve this error, ensure that no exports from $env/dynamic/private are used, even transitively, in client-side code.
- If you're only using the import as a type, change it to `import type`.
- If you're not sure which module is causing this, try building your app -- it will create a more helpful error.
Am I misunderstanding something? Here is my code :
import { getToken } from '@kinde-oss/kinde-auth-sveltekit';

// Get current auth token to ensure it's valid
$effect(() => {
if (user) {
getToken()
.then((token) => {
console.log('Auth token retrieved successfully');
// Token is current and valid
})
.catch((error) => {
console.warn('Failed to get auth token:', error);
});
}
});
import { getToken } from '@kinde-oss/kinde-auth-sveltekit';

// Get current auth token to ensure it's valid
$effect(() => {
if (user) {
getToken()
.then((token) => {
console.log('Auth token retrieved successfully');
// Token is current and valid
})
.catch((error) => {
console.warn('Failed to get auth token:', error);
});
}
});
Thank you again.
Roshan
Roshan•4w ago
Paul,

The error is happening because getToken in the SvelteKit SDK is designed for server-side usage only — it depends on SessionManager and server-side environment variables, which aren’t available in the browser.
const access_token = await kindeAuthClient.getToken(request as unknown as SessionManager);
const access_token = await kindeAuthClient.getToken(request as unknown as SessionManager);
If you need to access the token on the client, you’ll need to: Call getToken in a server context (+page.server.js, +layout.server.js, or server actions) and pass the token to your client code, or The SvelteKit SDK is primarily intended for backend/session handling, which is why it tries to import server-only modules when run in the browser.
Paul E
Paul E•4w ago
Thanks Roshan, previously you wrote: „2. On the client, call kindeAuthClient.getToken(request as SessionManager). If the user has a valid session, the SDK will refresh the token silently and return updated claims.“ So we mixed up something there? I don’t need the token on the client. I just wanted to try your recommendation.
Roshan
Roshan•4w ago
Sorry Paul, That was a mistake on my part. The wording should have been clearer. What I meant was:
“2. Call kindeAuthClient.getToken(request as SessionManager).”
This is intended for a server-side context, not the client.
Paul E
Paul E•4w ago
No worries! So calling getToken on the server refreshes the token and updates the claims of the user if he has a valid session?
Roshan
Roshan•3w ago
Hi Paul, Apologies for the delay — I was testing this out and also checked in with our senior engineers. getToken won’t instantly give you a new token with updated claims. Apologies for the misunderstanding on my end.

What you’ve done with your helper around /api/auth/login?prompt=none is currently the most reliable way to force a refresh and get the latest claims. If you need real-time updates in sensitive flows (e.g. checking permissions during a payments process), you could also call the Permissions API at that moment. This ensures you’re working with the most up-to-date state, even before the normal refresh cycle kicks in. I’ve also passed along your request for a dedicated helper to our internal team — it’s definitely on our radar.
Paul E
Paul E•3w ago
Thank you for your clarification, Roshan! 🙂
Roshan
Roshan•3w ago
Happy to help, Paul! Don’t hesitate to reach out if you need anything else.

Did you find this page helpful?