#Auth Issues

1 messages · Page 1 of 1 (latest)

buoyant oak
#

We’re using a React/Vite web app with WorkOS AuthKit for auth and Convex for backend/authenticated data. In production, we’re seeing long-lived browser sessions where WorkOS still appears to have a user, but Convex auth becomes unauthenticated after background/hidden-tab activity and websocket reconnects. The key preceding failures are WorkOS getAccessToken({ forceRefresh: true }) throwing a browser TypeError during token refresh, and in another case AuthKit reporting Missing refresh token after about an hour on the page.

sage steppeBOT
#

Hi @buoyant oak. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Based on the knowledge sources, this is a known and actively investigated issue with the WorkOS + Convex integration. Here's what's relevant to your situation:

Known Issue: Auth Loss After Background/Token Refresh

Your symptoms — Convex becoming unauthenticated after background tab activity and WebSocket reconnects — match issues discussed extensively in the WorkOS + Convex integration thread. [WorkOS Auth Thread]

What's happening under the hood

When a Convex query or mutation encounters an expired auth token, the server closes the WebSocket connection as a signal to the client to fetch a fresh token. The client then reconnects. This causes a brief unauthenticated state. [WorkOS Auth Thread]

There's also a known issue where returning to a suspended/backgrounded tab can trigger a failed-to-fetch error that logs the user out. This is a documented open issue. [WorkOS Auth Thread]

Recommended Fix: Use getAccessToken instead of accessToken

One community member resolved stale/missing token issues by switching from the accessToken ref pattern to getAccessToken(), which guarantees a fresh token:

function useAuthFromAuthKit() {
  const { user, loading: isUserLoading } = useAuth();
  const {
    getAccessToken,
    loading: isTokenLoading,
    error: tokenError,
  } = useAccessToken();

  const isLoading = (isUserLoading ?? false) || (isTokenLoading ?? false);
  const isAuthenticated = !!user;

  const fetchAccessToken = React.useCallback(async () => {
    if (tokenError) return null;
    const token = await getAccessToken();
    return token ?? null;
  }, [getAccessToken, tokenError]);
#

return {
isLoading,
isAuthenticated,
fetchAccessToken,
};
}


The key insight is that `accessToken` from `useAccessToken` is flagged as "might be stale", while `getAccessToken()` is described as "Get a guaranteed fresh access token. Automatically refreshes if needed." [[WorkOS Auth Thread](<https://discord.com/channels/1019350475847499849/1202520608672317471>)]

### For the `Missing refresh token` error

This is likely related to the known issue where coming back to a page after a long idle period causes a `failed-to-fetch` or missing refresh token error. The Convex team has acknowledged this and is working on retry logic — catching the error and retrying a few times before considering the session lost. [[WorkOS Auth Thread](<https://discord.com/channels/1019350475847499849/1202520608672317471>)]

### Additional mitigations

- Make sure `ConvexClientProvider` is the **outermost** provider in your layout — placing other providers (like `ThemeProvider`) outside it has been shown to cause race conditions. [[WorkOS Auth Thread](<https://discord.com/channels/1019350475847499849/1202520608672317471>)]
- Use the official testbed repo as a reference: [workos-convex-nextjs-testbed](<https://github.com/get-convex/workos-convex-nextjs-testbed>)
- Check the official templates for the latest fixes: [Vite template](<https://github.com/workos/template-convex-react-vite-authkit>) [[WorkOS Auth Thread](<https://discord.com/channels/1019350475847499849/1202520608672317471>)]
#

Note: The knowledge sources don't contain a complete fix for the getAccessToken({ forceRefresh: true }) TypeError specifically. I'd recommend opening an issue on the WorkOS Convex template repo with a reproduction, as the Convex team has been actively responsive there.


Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: