Reputation: 21
I have already seen Next.js Clerk vs. NextIntl. Middleware clash
I have tested the integration between next-intl and clerk v5 and the usage of the /api folder is blocked as it raises 404. Looks like there is a clash when enabling the /api path and also protecting it.
Here is my config in the middleware:
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
import createMiddleware from "next-intl/middleware";
import { NextResponse } from "next/server";
import { defaultLocale, locales } from "./messages/config";
const intlMiddleware = createMiddleware({
locales: locales,
defaultLocale: defaultLocale,
alternateLinks: false,
localePrefix: "as-needed",
});
const isProtectedRoute = createRouteMatcher(["/:locale/(.*)", "/", "/api/:path*"]);
export default clerkMiddleware((auth, req) => {
const { pathname } = req.nextUrl;
if (pathname.includes("/:locale/")) {
const locale = pathname.split("/")[1];
const replacedPathname = pathname.replace("/:locale/", "");
return NextResponse.redirect(
new URL(`/${(locales.includes(locale) ?? locale) || defaultLocale}/${replacedPathname}`, req.url),
);
}
if (isProtectedRoute(req)) {
auth().protect();
}
return intlMiddleware(req);
});
export const config = {
matcher: ["/((?!api/config/:path*).*)", "/((?!_next|_vercel|.*\\..*).*)"],
};
This is my folder structure:
And this is (part) of my .env.local file:
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/:locale/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/:locale/sign-up
Any help on configuring the matcher and protecting some or all of the /api routes would be great.
I followed the guide, and expected that the /api folder would be protected, but raises a 404.
Upvotes: 1
Views: 1279
Reputation: 11
Here is what I did. I wanted Clerk to protect certain localized routes and certain api routes. I did not want Next-Intl to localize my api routes.
My file structure is like yours except my sign-up route is \sign-up[[...sign-up]]\page.tsx
I used the default environment configuration and it works fine
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
I protect the localized routes by listing them like this in the middleware.
const isProtectedRoute = createRouteMatcher([
"/:locale/dashboard(.*)",
"/:locale/my-account(.*)",
]);
Also In the middleware I make sure that both Clerk and Next-Intl run everywhere except on the static pages. My middleware matcher looks like this:
export const config = {
matcher: "/((?!static|.*\\..*|_next).*)",
};
Inside the ClerkMiddleware is where I make the check that Next-Intl does not run on the api routes. Here is my code:
export default clerkMiddleware((auth, req) => {
// Restrict admin routes to users with specific permissions
if (isProtectedRoute(req)) {
auth().protect({});
}
// do not localize api routes
const path = req.nextUrl.pathname;
if (path.includes("/api")) {
return;
}
return intlMiddleware(req);
});
Finally in each api route I add the Clerk authentication like this.
import { auth } from "@clerk/nextjs/server";
export async function POST(request) {
// check if admin
const { has } = auth();
if (!has({ role: "org:admin" })) {
return new Response("You do not have rights", {
status: 401,
});
}
// Here is your route logic
}
Upvotes: 1