Summary
In an Expo app using Clerk Expo and ConvexProviderWithClerk, signing out and then signing back in can leave Convex unauthenticated even though Clerk has a valid new session and the session claims include aud: "convex".
Reloading the app fixes the state. Remounting ConvexProviderWithClerk by Clerk sessionId also fixes it.
Minimal reproduction
https://github.com/eliotgevers/clerk-convex-expo-auth-repro
Environment
- Expo Go
- Expo SDK:
54.0.33
- React Native:
0.81.5
- React:
19.1.0
@clerk/expo: 3.2.2
convex: 1.34.1
- Clerk email/password sign-in
- Clerk Convex integration enabled
- Convex auth configured with
applicationID: "convex"
Reproduction steps
Start the repro in plain provider mode:
EXPO_PUBLIC_KEY_CONVEX_BY_SESSION=false
Then:
- Sign in with an email/password Clerk user.
- Confirm the app shows:
SESSION AUD is convex
CONVEX AUTHENTICATED is true
- Sign out.
- Sign in again with the same Clerk user.
Observed behavior
After the second sign-in:
- Clerk is signed in.
- Clerk has a new
sessionId.
sessionClaims.aud is still convex.
useConvexAuth().isLoading is false.
useConvexAuth().isAuthenticated is false.
Reloading the app makes Convex authenticated again for the same Clerk session.
Expected behavior
Convex should authenticate for the new Clerk session without requiring an app reload or a manual provider remount.
A common real-world flow is:
- User signs in and uses the app successfully.
- User signs out.
- User signs back in with the same account, or another account.
- The app should be usable immediately.
Instead, the app can land in a state where Clerk is authenticated but Convex is not, so authenticated Convex queries/mutations cannot run until the app is relaunched.
Workaround
The repro includes a toggle:
EXPO_PUBLIC_KEY_CONVEX_BY_SESSION=true
In this mode, the app does:
const { sessionId } = useAuth();
const providerKey = sessionId ?? "signed-out";
return (
<ConvexProviderWithClerk key={providerKey} client={convex} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
);
With this workaround, the same sign-out/sign-in flow works: Convex becomes authenticated after the second sign-in.
Why this seems related to ConvexProviderWithClerk
It does not look like the Clerk session itself is invalid:
- Clerk reports signed in.
- A new Clerk
sessionId is present.
sessionClaims.aud is convex.
- Reloading the app fixes Convex auth without changing the Clerk session.
- Remounting
ConvexProviderWithClerk by sessionId fixes the issue.
From looking at ConvexProviderWithClerk, the token fetch callback is rebuilt for orgId / orgRole changes, but not for sessionId changes. I understand getToken is intentionally omitted because Clerk Expo's useAuth hook is not memoized, but same-user session replacement appears to be another auth-context transition that needs to retrigger Convex auth setup.
Summary
In an Expo app using Clerk Expo and
ConvexProviderWithClerk, signing out and then signing back in can leave Convex unauthenticated even though Clerk has a valid new session and the session claims includeaud: "convex".Reloading the app fixes the state. Remounting
ConvexProviderWithClerkby ClerksessionIdalso fixes it.Minimal reproduction
https://github.com/eliotgevers/clerk-convex-expo-auth-repro
Environment
54.0.330.81.519.1.0@clerk/expo:3.2.2convex:1.34.1applicationID: "convex"Reproduction steps
Start the repro in plain provider mode:
Then:
SESSION AUDisconvexCONVEX AUTHENTICATEDistrueObserved behavior
After the second sign-in:
sessionId.sessionClaims.audis stillconvex.useConvexAuth().isLoadingisfalse.useConvexAuth().isAuthenticatedisfalse.Reloading the app makes Convex authenticated again for the same Clerk session.
Expected behavior
Convex should authenticate for the new Clerk session without requiring an app reload or a manual provider remount.
A common real-world flow is:
Instead, the app can land in a state where Clerk is authenticated but Convex is not, so authenticated Convex queries/mutations cannot run until the app is relaunched.
Workaround
The repro includes a toggle:
In this mode, the app does:
With this workaround, the same sign-out/sign-in flow works: Convex becomes authenticated after the second sign-in.
Why this seems related to
ConvexProviderWithClerkIt does not look like the Clerk session itself is invalid:
sessionIdis present.sessionClaims.audisconvex.ConvexProviderWithClerkbysessionIdfixes the issue.From looking at
ConvexProviderWithClerk, the token fetch callback is rebuilt fororgId/orgRolechanges, but not forsessionIdchanges. I understandgetTokenis intentionally omitted because Clerk Expo'suseAuthhook is not memoized, but same-user session replacement appears to be another auth-context transition that needs to retrigger Convex auth setup.