From d5251d71b94a8a6432584f740a98a2e70121595f Mon Sep 17 00:00:00 2001 From: "cto-new[bot]" <140088366+cto-new[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 06:28:11 +0000 Subject: [PATCH] feat(convex-auth): enable Clerk-based authentication for Convex queries and improve error handling Enable Clerk-based authentication flow for Convex by removing the 'expectAuth: false' flag and wiring Clerk auth through the Convex client/provider. Add robust error handling for authentication identity retrieval and unauthorized access, with improved logs. - Enable Convex client to use Clerk authentication (remove expectAuth: false) - Harden getCurrentUserId and requireAuth with logging and guards - Add fallback/defaults and warnings for Clerk JWT issuer domain - Clarify behavior when unauthenticated users access protected Convex endpoints No breaking changes; ensure environment vars (NEXT_PUBLIC_CONVEX_URL, CLERK_JWT_ISSUER_DOMAIN) are set for best experience. --- convex/auth.config.ts | 8 +++++++- convex/helpers.ts | 22 ++++++++++++++++++++-- src/components/convex-provider.tsx | 3 +-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/convex/auth.config.ts b/convex/auth.config.ts index 552efd9b..cf844f3b 100644 --- a/convex/auth.config.ts +++ b/convex/auth.config.ts @@ -1,7 +1,13 @@ +const jwtIssuerDomain = process.env.CLERK_JWT_ISSUER_DOMAIN; + +if (!jwtIssuerDomain) { + console.warn("CLERK_JWT_ISSUER_DOMAIN environment variable is not set"); +} + export default { providers: [ { - domain: process.env.CLERK_JWT_ISSUER_DOMAIN!, + domain: jwtIssuerDomain || "placeholder.convex.cloud", applicationID: "convex", }, ], diff --git a/convex/helpers.ts b/convex/helpers.ts index 1d92f10c..bf1e8b30 100644 --- a/convex/helpers.ts +++ b/convex/helpers.ts @@ -3,8 +3,21 @@ import { QueryCtx, MutationCtx } from "./_generated/server"; export async function getCurrentUserId( ctx: QueryCtx | MutationCtx ): Promise { - const identity = await ctx.auth.getUserIdentity(); - return identity?.subject || null; + try { + const identity = await ctx.auth.getUserIdentity(); + if (!identity) { + console.warn("No user identity found in context"); + return null; + } + if (!identity.subject) { + console.warn("User identity found but no subject field"); + return null; + } + return identity.subject; + } catch (error) { + console.error("Error getting user identity:", error); + return null; + } } export async function requireAuth( @@ -12,6 +25,11 @@ export async function requireAuth( ): Promise { const userId = await getCurrentUserId(ctx); if (!userId) { + console.error("Authentication failed: No user ID found"); + console.error("Context auth details:", { + hasAuth: !!ctx.auth, + hasGetUserIdentity: typeof ctx.auth?.getUserIdentity === 'function' + }); throw new Error("Unauthorized"); } return userId; diff --git a/src/components/convex-provider.tsx b/src/components/convex-provider.tsx index 5f0a32f4..6bee2b92 100644 --- a/src/components/convex-provider.tsx +++ b/src/components/convex-provider.tsx @@ -8,8 +8,7 @@ import type { ReactNode } from "react"; const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL; const convexClient = new ConvexReactClient( - convexUrl || "https://placeholder.convex.cloud", - { expectAuth: false } + convexUrl || "https://placeholder.convex.cloud" ); export function ConvexClientProvider({ children }: { children: ReactNode }) {