#isAuthenticated false

33 messages · Page 1 of 1 (latest)

lime shard
#

useConvexAuth isAuthenticated still false even after successfully login.
jwt received, issuer is correct, iss and aud too
the auClient.useSession have data but not useConvexAuth

elfin axleBOT
#

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

#

I'm sorry, but there is no information in the provided knowledge sources regarding a provider called auClient.useSession. However, based on similar issues with other authentication providers (like WorkOS, Better Auth, or Clerk), if isAuthenticated from useConvexAuth() remains false despite a successful login and a valid JWT, here are the potential causes and steps to resolve it:

1. Missing Backend Configuration Sync

The most common cause is that the backend configuration has not been synchronized. Your auth.config.ts file must be synced to the Convex cloud.

2. JWT Audience (aud) or Issuer (iss) Mismatches

Even if you believe they are correct, Convex requires an exact match between the JWT payload and your auth.config.ts.

  • Audience: Ensure the applicationID in your auth.config.ts matches the aud claim in your JWT exactly. Some providers like WorkOS may require you to manually enable the aud claim in their dashboard to include your Client ID [Debugging Authentication].
  • Issuer: The issuer in auth.config.ts must match the iss claim in the JWT.
#

3. Missing ConvexProviderWithAuth

If the React client isn't configured to fetch and pass the JWT to Convex, isAuthenticated will remain false.

  • Solution: Ensure you are using ConvexProviderWithAuth (or a provider-specific one like ConvexProviderWithClerk) and that the useAuth prop is correctly passing the token. The useAuth hook must return a fetchAccessToken function that Convex calls to get the JWT [Provide the JWT to the Convex React client; Functions].

4. Race Conditions and WebSockets

After receiving a token, the client must send an Authenticate message over the WebSocket to the Convex deployment.

#

5. Domain/Environment Variables

Check if your auth.config.ts relies on environment variables (like CONVEX_SITE_URL) that might be undefined in your local or production environment. If the domain is undefined, JWT validation will fail [getAuthUserId() Returns Null Despite Successful OAuth Sign-In].

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

#

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

lime shard
#

@elfin axle I m using ConvexBetterAuthProvider

elfin axleBOT
#

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

#

If you are using ConvexBetterAuthProvider and isAuthenticated remains false despite a successful session in Better Auth, it usually indicates that the Convex client has not yet successfully validated the session token with the Convex backend.

Based on the knowledge sources, here are the troubleshooting steps specifically for the Better Auth + Convex integration:

1. Verification of auth.config.ts

Convex must be configured to trust the tokens issued by Better Auth. Ensure your convex/auth.config.ts matches your Better Auth deployment.

  • Issuer and Audience: The issuer and applicationID in your config must match the iss and aud claims in the JWT provided by Better Auth.
  • JWKS Endpoint: If you are not using a standard provider, you may need to expose the JWKS endpoint via a Convex HTTP action so the backend can verify the signatures [Better Auth with MongoDB and Convex for client data].

2. Client-Side Plugin Initialization

Ensure your Better Auth client is initialized with the convexClient() plugin. This plugin is responsible for making the session token available to the ConvexBetterAuthProvider. Without this, useConvexAuth will not receive the token to pass to the Convex backend [Better Auth + Convex: isLoading never resolves and authenticated queries never run].

#

3. Check for expectAuth: true

If you configured your ConvexReactClient with { expectAuth: true }, all queries will be paused until authentication is complete. If there is a configuration mismatch, the client may get stuck in an isLoading state indefinitely.

4. Better Auth Session vs. Convex Auth

It is important to note that Better Auth will reflect an authenticated user (via authClient.useSession()) before Convex does. The Convex client must take that session, exchange/validate the token with the Convex backend, and only then will useConvexAuth().isAuthenticated become true [Authorization].

Always use useConvexAuth() or the <Authenticated> helper component to gate your logic, as calling Convex functions before the Convex-specific validation completes can lead to errors [Authorization].

#

5. Debugging the Token

If the issue persists, verify the JWT:

  1. Check the browser's Network tab for the sync WebSocket connection.
  2. Look for an Authenticate message.
  3. Copy the token and paste it into jwt.io to ensure the iss and aud fields match exactly what you have in auth.config.ts [Check whether authentication works on the frontend].

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

#

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

lime shard
#

@elfin axle i get this after login but isAuthenticated still false
isAuthenticated
1/10/2026, 2:54:25 PM [CONVEX H(GET /api/auth/get-session)] [LOG] 'response headers' Headers { 'set-cookie': '__Secure-better-auth.convex_jwt=eyJhb....

1/10/2026, 2:54:25 PM [CONVEX H(GET /api/auth/get-session)] [LOG] '2026-01-10T13:54:25.324Z INFO [Better Auth]: [Convex Adapter]' '#3 \x1B[40m\x1B[33m[3/3]\x1B[0m' '\x1B[1mfindMany\x1B[0m \x1B[2m(Parsed Result)\x1B[0m:' {
model: 'jwks',
data: [
{
publicKey: '{"kty":"RSA","n":"xsdaE55e

1/10/2026, 2:54:25 PM [CONVEX H(GET /api/auth/get-session)] [LOG] '2026-01-10T13:54:25.324Z INFO [Better Auth]: [Convex Adapter]' '#3 \x1B[40m\x1B[33m[2/3]\x1B[0m' '\x1B[1mfindMany\x1B[0m \x1B[2m(DB Result)\x1B[0m:' {
model: 'jwks',
data: [
{
_creationTime: 1767814581243.6265,
_id: 'kd7fcmf4827zk18ph3ntr8x1ed7yr20n',
createdAt: 1767814581242,
privateKey: '"bea4dc192ae9d0

1/10/2026, 2:54:25 PM [CONVEX H(GET /api/auth/get-session)] [LOG] '2026-01-10T13:54:25.320Z INFO [Better Auth]: [Convex Adapter]' '#2 \x1B[40m\x1B[33m[3/3]\x1B[0m' '\x1B[1mfindOne\x1B[0m \x1B[2m(Parsed Result)\x1B[0m:' {
model: 'session',
data: {
expiresAt: 1768635097746,
token: 'IX5wto3NSq38Mlu8GXq5vu2kGZhant7Z',
createdAt: 1768030297746,
updatedAt: 1768030297746,
ipAddress: 'XXXX',
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36',
userId: 'k571qg3n8rhktcgsjw761knh2d7yxz6n',
impersonatedBy: undefined,
id: 'jx711psv34tar1fw6x1zn1wqwx7yzf5c',
user: {
name:

elfin axleBOT
#

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

#

The logs show that Better Auth is successfully creating a session and setting the __Secure-better-auth.convex_jwt cookie. However, isAuthenticated remaining false on the client indicates that the Convex React client has not yet received or successfully validated that token with the Convex backend.

Based on the knowledge sources, here are the likely reasons for this behavior:

1. Verification of auth.config.ts

The most common reason isAuthenticated stays false even when a token exists is that the Convex backend is rejecting the JWT because the configuration doesn't match.

  • Issuer Match: Better Auth typically uses your CONVEX_SITE_URL as the issuer. Ensure your convex/auth.config.ts has the exact same URL (including <https://> and no trailing slash) [No JWT Token when using better-auth with Next.js SSR on login].
  • Application ID: Ensure the applicationID in auth.config.ts is set to "convex", which is the default audience used by the Better Auth Convex plugin.

2. JWT Validation via JWKS

Your logs show Better Auth fetching jwks from the database. For Convex to validate the JWT, it needs to access these public keys.

  • If you are not using the experimental.jwks feature, Convex tries to fetch the keys from your Better Auth deployment at runtime.
  • Experimental Optimization: To speed this up and avoid validation failures, you can provide the JWKS statically to the auth config. You can run npx convex run auth:getLatestJwks | npx convex env set JWKS and update your auth.config.ts to use process.env.JWKS [Experimental].
#

3. Client-Side Race Condition

In frameworks like Next.js, the better-auth.convex_jwt cookie is set during the login request, but the Convex WebSocket might already be connected and waiting.

  • The Convex client needs to "see" that token change. If you are using ConvexBetterAuthProvider, it relies on the Better Auth client's state.
  • There is a known issue where the convex_jwt might not be immediately available to the client-side session without a refresh if using certain plugins or older versions of the adapter [No JWT Token when using better-auth with Next.js SSR on login]. Ensure you are on the latest version of @convex-dev/better-auth.

4. Debugging the Validation Failure

To see exactly why the backend is keeping isAuthenticated false, you can enable verbose logging:

  • Backend: Set the environment variable AUTH_LOG_LEVEL to DEBUG in your Convex dashboard. This will log exactly why a JWT validation failed (e.g., "invalid issuer" or "could not fetch JWKS") [Debugging].
  • Client: Initialize your ConvexReactClient with verbose: true to see if the "Authenticate" message is being sent over the WebSocket [Debugging].
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!, {
  verbose: true,
});
#

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

lime shard
#

@elfin axle better auth while authenticated, useConvexAuth isLoading remain true

elfin axleBOT
#

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

#

If useConvexAuth().isLoading remains stuck at true while using Better Auth, it typically means the Convex client is waiting for authentication to resolve but has not received a definitive success or failure from the backend.

Based on the knowledge sources, here are the primary reasons and solutions for this state:

1. expectAuth: true is enabled

If you initialized your ConvexReactClient with the expectAuth: true option, Convex will pause all query execution and remain in a loading state until the user is successfully authenticated. If there is any misconfiguration in your auth setup, the client will stay in isLoading: true indefinitely because it is waiting for a valid JWT that never clears validation [Better Auth + Convex: isLoading never resolves and authenticated queries never run].

2. JWT Validation Latency (JWKS Fetching)

By default, the Convex backend must perform two blocking HTTP requests to validate a Better Auth token: one for OIDC discovery and one to fetch the JWKS (JSON Web Key Set). This can cause the authentication process to be slow or hang if these external requests fail.

  • Solution: Use Static JWKS to speed up validation. You can fetch your JWKS and store it as a Convex environment variable. This allows the backend to validate tokens locally without external network calls [Experimental].
#

3. Missing Client-Side Plugin

The Better Auth client must be configured with the convexClient() plugin to properly communicate the session state to the ConvexBetterAuthProvider.

4. Debugging the "Hang"

To identify exactly why the loading state isn't resolving, you can:

  • Check WebSocket Traffic: Open the browser Network tab, filter for WS, and look at the sync connection. Look for an Authenticate message. If the message is sent but never receives a confirmation, the backend is struggling to validate it [Check whether authentication works on the frontend].
  • Enable Verbose Logging: Set AUTH_LOG_LEVEL to DEBUG in your Convex dashboard. This will reveal if the backend is silently failing during token validation, which keeps the client in a waiting state [Debugging].

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

#

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

lime shard
elfin axleBOT
#

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

#

I'm sorry, but I do not have access to the specific content of the Discord link you provided (1443243345609621594), as it is not included in the knowledge sources provided to me.

However, based on the relevant knowledge sources regarding Better Auth and Convex authentication staying in a loading state, the most common solution for this specific "infinite loading" behavior is:

  1. Check for expectAuth: true: If you have expectAuth: true in your ConvexReactClient configuration, it will pause all queries and remain in an isLoading state until authentication is fully resolved. If there is a configuration mismatch, it may never resolve. Staff recommend turning this off to troubleshoot if the state then transitions to isAuthenticated: false [Better Auth + Convex: isLoading never resolves and authenticated queries never run; INFINITE loading state].
  2. Verify the convexClient() plugin: Ensure your Better Auth client is initialized with the convexClient() plugin, which is required for the ConvexBetterAuthProvider to receive the token [Better Auth + Convex: isLoading never resolves and authenticated queries never run].
  3. Backend Config Sync: Ensure you have run npx convex dev after setting up your auth.config.ts. If the backend doesn't have the provider info, the validation request will never complete successfully [Debugging Authentication].
#

If you can share the specific error or code snippet from that thread, I may be able to provide more targeted help based on the documents I have.

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

#

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

lime shard
elfin axleBOT
#

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

#

I'm sorry, but the provided knowledge sources do not contain information regarding the GitHub issue get-convex/convex-js/issues/108 or the specific details of that discussion.

However, if you have removed expectAuth, confirmed your convexClient() plugin is correct, and deployed your auth.config.ts, but isLoading still remains true or isAuthenticated remains false, the knowledge sources point to a few remaining potential causes:

  • Cookie Accessibility: In Next.js and other frameworks, the convex_jwt is often stored in a cookie. If the cookie is not being sent with the Convex WebSocket connection (for example, due to CORS issues or the cookie being marked as __Host- but the client running on a different subdomain), the Convex client will never receive the token to start the authentication process [Debugging].
  • Static JWKS Mismatch: If you are using the static JWKS optimization, ensure that the keys in your JWKS environment variable exactly match the keys being used by your Better Auth instance to sign the tokens. If they do not match, validation will fail silently on the backend, potentially leaving the client waiting [Experimental].
  • Issuer URL Precision: The domain in auth.config.ts must be a character-for-character match with the iss claim in your JWT. This includes the protocol (<https://>) and the absence of a trailing slash. If your BETTER_AUTH_URL differs even slightly from what is in auth.config.ts, authentication will fail [No JWT Token when using better-auth with Next.js SSR on login].
#

To get more diagnostic information, I recommend setting the environment variable AUTH_LOG_LEVEL to DEBUG in your Convex dashboard. This will log the specific reason why the authentication flow is hanging or failing in the Logs section of your dashboard [Debugging].

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