NextJs 多租户中间件与 Clerk Auth 中间件

问题描述 投票:0回答:1

请参阅最后我的确切错误屏幕截图。

背景:

我使用 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] 目录应用程序布局中放置标签,以使其仅适用于租户,但错误并没有消失。

每当我通过职员身份验证登录并且我应该登陆仪表板时,就会出现以下错误

我认为我的中间件导致了这个问题,我已经没有主意了。

authentication next.js middleware multi-tenant clerk
1个回答
0
投票

我做了类似的事情,并且有效

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)(.*)"],
};

© www.soinside.com 2019 - 2024. All rights reserved.