Skip to content

ConvexProviderWithClerk on Expo can stay unauthenticated after Clerk session replacement #156

@eliotgevers

Description

@eliotgevers

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:

  1. Sign in with an email/password Clerk user.
  2. Confirm the app shows:
    • SESSION AUD is convex
    • CONVEX AUTHENTICATED is true
  3. Sign out.
  4. 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:

  1. User signs in and uses the app successfully.
  2. User signs out.
  3. User signs back in with the same account, or another account.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions