请参阅最后我的确切错误屏幕截图。
背景:
我使用 Clerk Auth 开发了一个 NextJs Web 应用程序,它运行得很好! 后来我决定使用 Next Multitenancy Template 添加多租户,该模板使用中间件来查找域名更改,该模板也使用 Next Auth。因此,我将之前的 Web App 与它合并了。我为多租户管理系统留下了下一个身份验证,并希望为租户使用职员身份验证,到目前为止,那里没有冲突。
现在,我的 clerk auth 中间件和多租户中间件发生了冲突。
以前的应用程序目录
合并后的App目录
我将原始应用程序中的所有应用程序文件复制到多租户模板的 [domain] 目录中,并据我所知解决了所有依赖性问题、组件、挂钩、库。
我的中间件代码:
import { NextRequest, NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";
// // Developer Message 2 : This is for Clerk support. To Further Check Proceed To Link : https://clerk.com/docs/quickstarts/nextjs
// // After this (auth) folder was created in app
// //Below is Developer Message 3
import { authMiddleware } from "@clerk/nextjs";
// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your middleware
export default authMiddleware({
// Developer Message 3
//Public Routes Enable Unauthorised users to visit below mentioned routes
publicRoutes: ["/","/api/webhook"]
});
export const config = {
matcher: [
/*
* Match all paths except for:
* 1. /api routes
* 2. /_next (Next.js internals)
* 3. /_static (inside /public)
* 4. all root files inside /public (e.g. /favicon.ico)
*/
'/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)', // from clerk auth
"/((?!api/|_next/|_static/|_vercel|[\\w-]+\\.\\w+).*)", //from multitenancy template
],
};
export async function middleware(req: NextRequest) {
const url = req.nextUrl;
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
const hostname = req.headers
.get("host")!
.replace(".localhost:3000", `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`);
const searchParams = req.nextUrl.searchParams.toString();
// Get the pathname of the request (e.g. /, /about, /blog/first-post)
const path = `${url.pathname}${
searchParams.length > 0 ? `?${searchParams}` : ""
}`;
// rewrites for app pages
if (hostname == `app.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`) {
const session = await getToken({ req });
if (!session && path !== "/login") {
return NextResponse.redirect(new URL("/login", req.url));
} else if (session && path == "/login") {
return NextResponse.redirect(new URL("/", req.url));
}
return NextResponse.rewrite(
new URL(`/app${path === "/" ? "" : path}`, req.url),
);
}
// special case for `vercel.pub` domain
if (hostname === "vercel.pub") {
return NextResponse.redirect(
"https://vercel.com/blog/platforms-starter-kit",
);
}
// rewrite root application to `/home` folder
if (
hostname === "localhost:3000" ||
hostname === process.env.NEXT_PUBLIC_ROOT_DOMAIN
) {
return NextResponse.rewrite(
new URL(`/home${path === "/" ? "" : path}`, req.url),
);
}
// rewrite everything else to `/[domain]/[slug] dynamic route
return NextResponse.rewrite(new URL(`/${hostname}${path}`, req.url));
}
我已将两个中间件代码放在同一个中,但两个默认值不能同时存在,因此我尝试导出不带默认关键字的多租户中间件(),并且它似乎有效。我还结合了这两个配置。
我添加了包含 html 标签的标签,以便身份验证在整个应用程序上工作。我还尝试在 [domain] 目录应用程序布局中放置标签,以使其仅适用于租户,但错误并没有消失。
每当我通过职员身份验证登录并且我应该登陆仪表板时,就会出现以下错误
我认为我的中间件导致了这个问题,我已经没有主意了。
我做了类似的事情,并且有效
import { authMiddleware, redirectToSignIn } from "@clerk/nextjs";
import { NextResponse } from "next/server";
// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
export default authMiddleware({
publicRoutes: ["/"],
afterAuth: (auth, req) => {
const url = req.nextUrl;
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3123)
// biome-ignore lint/style/noNonNullAssertion: <explanation>
let hostname = req.headers.get("host")!.replace(".localhost:3123", `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`);
// special case for Vercel preview deployment URLs
if (hostname.includes("---") && hostname.endsWith(`.${process.env.NEXT_PUBLIC_VERCEL_DEPLOYMENT_SUFFIX}`)) {
hostname = `${hostname.split("---")[0]}.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`;
}
const searchParams = req.nextUrl.searchParams.toString();
// Get the pathname of the request (e.g. /, /about, /blog/first-post)
const path = `${url.pathname}${searchParams.length > 0 ? `?${searchParams}` : ""}`;
// rewrites for app pages
if (hostname === `app.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`) {
if (!auth.userId && !auth.isPublicRoute) {
const prefix = process.env.NODE_ENV === "development" ? "http://" : "https://";
return redirectToSignIn({ returnBackUrl: `${prefix}${hostname}/` });
}
return NextResponse.rewrite(new URL(`/app${path === "/" ? "" : path}`, req.url));
}
// special case for `vercel.pub` domain
// if (hostname === 'vercel.pub') {
// return NextResponse.redirect(
// 'https://vercel.com/blog/platforms-starter-kit',
// );
// }
// rewrite root application to `/home` folder
if (hostname === "localhost:3123" || hostname === process.env.NEXT_PUBLIC_ROOT_DOMAIN) {
return NextResponse.rewrite(new URL(`/home${path === "/" ? "" : path}`, req.url));
}
// console.log("here");
// rewrite everything else to `/[domain]/[slug] dynamic route
return NextResponse.rewrite(new URL(`/${hostname}${path}`, req.url));
},
});
export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};