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.
#Auth Issues
1 messages · Page 1 of 1 (latest)
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 }) TypeErrorspecifically. I'd recommend opening an issue on the WorkOS Convex template repo with a reproduction, as the Convex team has been actively responsive there.