whoami
whoami2y ago

Refresh clerk auth token when I switch orgs

I am encountering an issue when attempting to implement row level security with your recommended approach. I've taken the step of feeding the org_id to the gender field in the JWT provided by the clerk. However, I am finding that the token is not refreshing immediately after switching organizations. In my code, I switch the organization, which prompts the clerk hook to reflect the change:
const { organization: org } = useOrganization({})
const { organization: org } = useOrganization({})
As expected, org?.id is passed to the query reactively when I switch organizations. However, I've noticed that the JWT's gender field, where I've assigned the org_id, doesn't appear to refresh to the new organization's ID in sync. This discrepancy is causing my chat list to return as empty. Here's my query code
const data = useQuery('chats:list', {
org: org?.id || '',
})
const data = useQuery('chats:list', {
org: org?.id || '',
})
Here is my RLS code
export const { withQueryRLS, withMutationRLS } = RowLevelSecurity<
{ auth: Auth; db: DatabaseReader },
DataModel
>({
chats: {
read: async ({ auth }, chat) => {
const identity = await auth.getUserIdentity()
if (!identity) {
throw new Error('Unauthenticated call to mutation')
}
const { gender: org } = identity
return chat.org === org
},
...
export const { withQueryRLS, withMutationRLS } = RowLevelSecurity<
{ auth: Auth; db: DatabaseReader },
DataModel
>({
chats: {
read: async ({ auth }, chat) => {
const identity = await auth.getUserIdentity()
if (!identity) {
throw new Error('Unauthenticated call to mutation')
}
const { gender: org } = identity
return chat.org === org
},
...
I need the JWT to refresh immediately after an organization switch to ensure the correct data is being accessed.
5 Replies
Michal Srb
Michal Srb2y ago
Hey @whoami , would it work better to pass the org id directly in a mutation? That way you can control exactly when it gets updated, and don’t need the gender field trick?
Michal Srb
Michal Srb2y ago
You could use a useEffect for example, similarly to the useEffect shown in this doc: https://docs.convex.dev/auth/database-auth
Storing Users in the Convex Database | Convex Developer Hub
You might want to have a centralized place that stores information about the
Chad Maycumber
@whoami Did you ever find a good approach here or go with what @Michal Srb suggested I'm running into the same thing and want to try to avoid passing in the orgId to most of my mutations if possible. I ended up adding a key to the convex provider, it causes a re-render but I don't need to update the entire app. I think this will work for my use case
Michal Srb
Michal Srb2y ago
Ah, using key is a neat way to force a refresh of the token. We talked about this problem a little internally and the approach of passing in the orgId is not ideal since you'd still want to verify that orgId is the right one based on state stored in Clerk. Hence you might consider the Webhooks or API approach for syncing Clerk data with Convex: https://clerk.com/docs/users/sync-data-to-your-backend
Sync data to your backend | Clerk
Learn how to sync Clerk data to your application's database
Michal Srb
Michal Srb5mo ago
Custom claims are now supported with convex@1.14.0

Did you find this page helpful?