Igor Kotua
Igor Kotua•13mo ago

Issues with getUserIdentity inside queries (auth with Clerk)

Hi there I configured login with Clerk and set up integration with Convex. getUserIdentity works fine inside mutations (returning identity object), but inside queries it's almost always emtpy. I am using Next.js. I am also using Clerk middleware for app router. The weird thing I noticed is when I navigate to a page with a query via Next.js router.push() the query works fine and user identity is not null. But if I refresh this page or try to navigate to it just via URL, the user identity will be empty. What am I doing wrong?
9 Replies
Igor Kotua
Igor KotuaOP•13mo ago
This is my client setup
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithClerk } from "convex/react-clerk";
// import { ClerkProvider } from "@clerk/nextjs";
// import { useAuth } from "@clerk/nextjs";
import { useUser, ClerkProvider, useAuth } from "@clerk/clerk-react";
import { useConvexAuth } from "convex/react";
import { useEffect, useState } from "react";
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Id } from "../../convex/_generated/dataModel";

const convexClient = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export default function ConvexClientProvider({
children,
}: {
children: ReactNode;
}) {
return (
<ClerkProvider
publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}
>
<ConvexProviderWithClerk client={convexClient} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
</ClerkProvider>
);
}
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithClerk } from "convex/react-clerk";
// import { ClerkProvider } from "@clerk/nextjs";
// import { useAuth } from "@clerk/nextjs";
import { useUser, ClerkProvider, useAuth } from "@clerk/clerk-react";
import { useConvexAuth } from "convex/react";
import { useEffect, useState } from "react";
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Id } from "../../convex/_generated/dataModel";

const convexClient = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export default function ConvexClientProvider({
children,
}: {
children: ReactNode;
}) {
return (
<ClerkProvider
publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}
>
<ConvexProviderWithClerk client={convexClient} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
</ClerkProvider>
);
}
Also getConvexAuth on this page returns authenticated: true Let me know if you need more info 🙂
Michal Srb
Michal Srb•13mo ago
Hey @Igor Kotua, the client always needs to authenticate first. Either you need 1. the client to block calls to the queries (for example by wrapping the components with Authenticated, as described in https://docs.convex.dev/auth/clerk#logged-in-and-logged-out-views), or 2. your queries to handle the missing authentication scenario (I recommend returning null as its it's easy to handle along with undefined from useQuery), and use routing to determine whether the user should be shown the logged-in or logged-out state. Here are sequence diagrams for the two solutions:
Convex Clerk | Convex Developer Hub
Clerk is an authentication platform providing login via
No description
No description
Igor Kotua
Igor KotuaOP•13mo ago
@Michal Srb well my client is authenticated, useConvexAuth hooks confirms that. But my convex query still returns null from getUserIdentity
Michal Srb
Michal Srb•13mo ago
Can you share your React code, which includes useConvexAuth / Authenticated and the useQuery calls?
Igor Kotua
Igor KotuaOP•13mo ago
Basically this, nothing special "use client"; import { useQuery } from "convex/react"; import { api } from "../../../convex/_generated/api"; import { useConvexAuth } from "convex/react"; export default function Page({ params }: { params: { id: string } }) { const auth = useConvexAuth(); const data = useQuery(api.videos.getVideo, { videoId: params.id as any }); return ( <div> <h1>Video</h1> {JSON.stringify(data?.description)} {JSON.stringify(auth)} </div> ); }
Michal Srb
Michal Srb•13mo ago
From this code it doesn't seem that you're blocking useQuery from running when useConvexAuth returns {isAuthenticated: false}. You need to wrap the Page in Authenticated, or split it up into two components, the outer one using Authenticated or checking the result of useConvexAuth.
Igor Kotua
Igor KotuaOP•13mo ago
Oh ok, that's a bit confusing. I thought ConvexProviderWithClerk is taking care of this I will try to wrap this in Authenticated or prevent query from running if useConvexAuth returns {isAuthenticated: false}
Mordsith
Mordsith•12mo ago
I'm facing this exact issue but with Next.JS. If Convex needs to authenticate on client first, how about instance where we need to use preloadQuery on the server side and fetch authenticated user?
@Michal Srb The <Authenticated /> wrapper doesn't work on server side
Michal Srb
Michal Srb•12mo ago
@Mordsith 1. pass the token to the options argument in preloadQuery (as per docs) 2. Return null from the query when it is not authenticated 3. On the client use this helper hook: https://github.com/Nutlope/notesGPT/blob/main/lib/hooks.tsx
GitHub
notesGPT/lib/hooks.tsx at main · Nutlope/notesGPT
Record voice notes & transcribe, summarize, and get tasks - Nutlope/notesGPT

Did you find this page helpful?