ej_xd.
ej_xd.3mo ago

User not authenticated" error in Convex mutation when called from Next.js API route

Hello! I'm running into an authentication issue when calling Convex mutations from Next.js API routes. I'm getting "User not authenticated" error when calling ctx.auth.getUserIdentity() inside a Convex mutation that's being called from a Next.js API route. However, other mutations that also use ctx.auth.getUserIdentity() work perfectly when called from client components that are wrapped in Clerk's <Authenticated> component. Next.js API route
export async function GET(req: NextRequest) {
const { userId, orgId } = await auth();

const integrationId = await fetchMutation(
api.features.integrations.public.createIntegration,
{
provider: "linear",
// ... other args
}
);
}
export async function GET(req: NextRequest) {
const { userId, orgId } = await auth();

const integrationId = await fetchMutation(
api.features.integrations.public.createIntegration,
{
provider: "linear",
// ... other args
}
);
}
Convex Mutation
export const createIntegration = mutation({
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity(); // ❌ This fails
if (!identity) {
throw new Error("User not authenticated"); // ❌ This error is thrown
}
// ...
}
});
export const createIntegration = mutation({
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity(); // ❌ This fails
if (!identity) {
throw new Error("User not authenticated"); // ❌ This error is thrown
}
// ...
}
});
Could I get some help on this?
4 Replies
erquhart
erquhart3mo ago
fetchMutation (and fetchQuery/fetchAction/preloadQuery) accept a third args object of Nextjs options, you can pass a token there to authenticate the function call.
ej_xd.
ej_xd.OP3mo ago
Thank you so much @erquhart! It's working now 😊 yay
moxaj
moxaj2mo ago
@erquhart is there some equivalent for executing mutations in a tanstack route's beforeLoad? I'm having the exact same issue.
moxaj
moxaj2mo ago
To anyone stumbling upon this thread - my issue was that I used the session token, not the JWT template. See here: https://docs.convex.dev/client/react/tanstack-start/tanstack-start-with-clerk#:~:text=const%20token%20%3D%20await%20auth.getToken(%7B%20template%3A%20%27convex%27%20%7D). You have to pass template: 'convex'. The strange thing is, requests made from components worked as expected, but the ones initiated from the server (route loader or beforeLoad) failed.
TanStack Start with Clerk | Convex Developer Hub
Learn how to integrate Clerk authentication with Convex in TanStack Start applications using ID tokens and ConvexProviderWithClerk.

Did you find this page helpful?