#useConvexAuth vs <Authenticated />

1 messages · Page 1 of 1 (latest)

severe birch
#

Hello, I have Convex auth setup but when I use useConvexAuth's isAuthenticated variable its false, and when I use the <Authenticated> component it renders, because I am authenticated, how is this possible?

royal elbowBOT
#

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

#

This scenario shouldn't normally be possible, since <Authenticated> is powered by useConvexAuth() under the hood — they use the same auth state. [Convex Auth0 docs]

However, there is one known situation that can cause confusing behavior like this: timing/race conditions between the auth provider's state and Convex's validated auth state.

As documented for Better Auth (but the principle applies broadly):

"Better Auth will reflect an authenticated user before Convex does, as the Convex client must subsequently validate the token provided by Better Auth." [Better Auth authorization]

The full authentication flow is:

  1. Your auth provider (Clerk, Auth0, WorkOS, etc.) authenticates the user.
  2. ConvexProviderWithX fetches a token from the provider.
  3. The ConvexReactClient passes the token to your Convex backend to validate.
  4. Only after backend validation does useConvexAuth() return isAuthenticated: true. [Clerk under the hood]

So if you're seeing a discrepancy, a likely cause is that you're reading isAuthenticated from useConvexAuth() at a moment when Convex hasn't yet validated the token, while the <Authenticated> component (also using useConvexAuth) renders correctly because it re-renders reactively once validation completes.

#

Things to check:

  • Make sure you're not reading isAuthenticated before isLoading is false. Always check isLoading first:
    const { isLoading, isAuthenticated } = useConvexAuth();
    if (isLoading) return <div>Loading...</div>;
    if (!isAuthenticated) return <div>Not authenticated</div>;
    
  • Ensure you are not using your auth provider's own auth hook (e.g., useAuth from WorkOS, useAuth0, etc.) to check authentication state for Convex-related logic. Always use useConvexAuth() or the <Authenticated> component for this purpose. [Clerk React docs]

If the issue persists, it may also be a backend configuration problem (e.g., missing environment variables or unsynced config). See the Debugging Authentication guide for more thorough steps.

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

#

@severe birch Kapa.ai is still learning and improving, please let me know how I did by reacting below.

severe birch
#

"use client";
import { useAuthActions } from "@convex-dev/auth/react";
import { Authenticated, useConvexAuth } from "convex/react";
import { TriangleAlertIcon } from "lucide-react";

export function Footer() {
const { signOut } = useAuthActions();
const { isAuthenticated } = useConvexAuth();

if (isAuthenticated) {
<footer className="inline-flex h-10 w-full items-center justify-center gap-4 border-t">
<TriangleAlertIcon className="size-5" />
<p className="">TEST!</p>
</footer>;
}

return (
<footer className="inline-flex h-10 w-full items-center justify-center gap-4 border-t bg-yellow-600">
<TriangleAlertIcon className="size-5" />
<p>Hello</p>
<Authenticated>
<p>I am logged in</p>
</Authenticated>
</footer>
);
}

It renders hello I am logged in @royal elbow

royal elbowBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

The issue is a simple JavaScript bug — you're missing a return statement in your if (isAuthenticated) block!

if (isAuthenticated) {
  // ❌ This JSX is never returned — it's just an expression statement
  <footer>...</footer>;
}

Because there's no return, the function falls through to the final return statement, which always renders the yellow footer. The <Authenticated> component inside it then correctly shows "I am logged in" because you are authenticated.

Fix it by adding return:

if (isAuthenticated) {
  return (
    <footer className="inline-flex h-10 w-full items-center justify-center gap-4 border-t">
      <TriangleAlertIcon className="size-5" />
      <p className="">TEST!</p>
    </footer>
  );
}

This is why isAuthenticated from useConvexAuth() and <Authenticated> are actually consistent — they use the same auth state. [Convex Auth0 docs] The discrepancy you were seeing was purely a missing return, not an auth issue.

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

#

@severe birch Kapa.ai is still learning and improving, please let me know how I did by reacting below.