cornpopguy
cornpopguy9mo ago

How can I use Convex in the Next.js middleware?

I am trying to use Convex in my middleware like so, but ctx.auth.getUserIdentity() in my action keeps returning null, I believe that this is due it running on the server so it is not wrapped with <ConvexProviderWithClerk />:
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
import { fetchAction } from 'convex/nextjs';
import { NextResponse } from 'next/server';

import { api } from '@/convex/_generated/api';
import { env } from '@/env';

const isPrivateRoute = createRouteMatcher([`${env.NEXT_PUBLIC_AFTER_AUTH_REDIRECT_URL}(.*)`]);
const isAuthRoute = createRouteMatcher([
`${env.NEXT_PUBLIC_CLERK_SIGN_IN_URL}(.*)`,
`${env.NEXT_PUBLIC_CLERK_SIGN_UP_URL}(.*)`,
]);

export default clerkMiddleware(async (auth, req) => {
const { url } = req;
const user = await fetchAction(api.clerk.user.getUserInfo);
console.log(user.user.stripeUserId);

if (isAuthRoute(req)) {
return NextResponse.redirect(new URL(env.NEXT_PUBLIC_AFTER_AUTH_REDIRECT_URL, url));
} else if (isPrivateRoute(req)) {
auth().protect();
return auth().redirectToSignIn();
}

return NextResponse.next();
});

export const config = {
matcher: [
'/((?!.*\\..*|_next).*)', // Don't run middleware on static files
'/', // Run middleware on index page
'/(api|trpc)(.*)', // Run middleware on API routes
],
};
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
import { fetchAction } from 'convex/nextjs';
import { NextResponse } from 'next/server';

import { api } from '@/convex/_generated/api';
import { env } from '@/env';

const isPrivateRoute = createRouteMatcher([`${env.NEXT_PUBLIC_AFTER_AUTH_REDIRECT_URL}(.*)`]);
const isAuthRoute = createRouteMatcher([
`${env.NEXT_PUBLIC_CLERK_SIGN_IN_URL}(.*)`,
`${env.NEXT_PUBLIC_CLERK_SIGN_UP_URL}(.*)`,
]);

export default clerkMiddleware(async (auth, req) => {
const { url } = req;
const user = await fetchAction(api.clerk.user.getUserInfo);
console.log(user.user.stripeUserId);

if (isAuthRoute(req)) {
return NextResponse.redirect(new URL(env.NEXT_PUBLIC_AFTER_AUTH_REDIRECT_URL, url));
} else if (isPrivateRoute(req)) {
auth().protect();
return auth().redirectToSignIn();
}

return NextResponse.next();
});

export const config = {
matcher: [
'/((?!.*\\..*|_next).*)', // Don't run middleware on static files
'/', // Run middleware on index page
'/(api|trpc)(.*)', // Run middleware on API routes
],
};
4 Replies
Michal Srb
Michal Srb9mo ago
You need to pass a valid token to fetchAction: https://docs.convex.dev/client/react/nextjs/server-rendering#server-side-authentication (it should say "preloadQuery, fetchQuery, fetchMutation and fetchAction")
Next.js Server Rendering | Convex Developer Hub
Next.js automatically renders both Client and Server Components on the server
cornpopguy
cornpopguyOP9mo ago
Hmm, I think it might be possible to query the user from the db and pass in the auth().userId right? Would this be more feasible option?
Michal Srb
Michal Srb9mo ago
You'll want to use a token to make sure the request is securely authenticated fetchQuery(api.clerk.user.get, {}, {token: await auth().getToken({ template: "convex" }))})
cornpopguy
cornpopguyOP9mo ago
Okay, thanks, will do that.

Did you find this page helpful?