Nextjs 中间件无法与 Amplify 上的 Next Auth V5 配合使用:“服务器配置存在问题”和“主机必须可信”

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

环境 环境 系统: 操作系统:macOS 14.3.1 CPU:(10)arm64苹果M1 Pro 内存:174.97 MB / 16.00 GB 外壳:5.9 - /bin/zsh 二进制文件: 节点:18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node 纱线:1.22.19 - /usr/local/bin/yarn npm:10.2.4 - ~/.nvm/versions/node/v18.17.1/bin/npm 浏览器: 勇敢的浏览器:121.1.62.156 铬:121.0.6167.184 Safari:17.3.1

我正在将 Amplify 与 NextAuth V5 结合使用。目前,我面临一个问题,即我没有指定 NEXTAUTH_URL。这在 Amplify 上似乎有问题,因为它仍然引用回本地主机。然而,主要问题是中间件没有为 auth.req 提供正确的输出。

auth.req 给我“消息”:“服务器配置存在问题。检查服务器日志以获取更多信息。”

有趣的是,我部署的代码在 Vercel 上完美运行,无需指定 NEXTAUTH_URL,并且中间件运行完美。我怀疑中间件在 Amplify 上的解释方式可能存在问题。

详细信息:我在 .env 中使用 NEXTAUTH_SECRET,但没有使用 NEXTAUTH_URL。 NEXTAUTH_SECRET 可以在中间件中读取,因此问题是无法在 amplify 上找到 .env 变量。

我也在使用 Prisma 和 Mongodb 适配器。

预期行为 如果用户已登录,则 auth.req 应返回用户;如果未登录,则应返回 null,而不是消息错误。

不应使用本地主机,而应使用我正在使用的子域(即 app.DOMAIN.com 或 dev.DOMAIN.com)

src/middleware.ts

import NextAuth from 'next-auth';

import authConfig from '@/auth.config';
import {
  DEFAULT_LOGIN_REDIRECT,
  apiAuthPrefix,
  authRoutes,
  publicRoutes,
} from './routes';

const { auth } = NextAuth(authConfig);

/* @ts-ignore */
export default auth((req) => {
  const { nextUrl } = req;

  if (nextUrl.pathname.startsWith('/ingest')) {
    console.log('hit hit');
    return null;
  }

  const isLoggedIn = !!req.auth;

  console.log('isLoggedIn', isLoggedIn);

  const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
  const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
  const isAuthRoute = authRoutes.includes(nextUrl.pathname);

  console.log('isApiAuthRoute', isApiAuthRoute);
  console.log('isPublicRoute', isPublicRoute);
  console.log('isAuthRoute', isAuthRoute);

  if (isApiAuthRoute) {
    return null;
  }

  if (isAuthRoute) {
    if (isLoggedIn) {
      return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
    }
    return null;
  }
  if (!isLoggedIn && !isPublicRoute) {
    let callbackUrl = nextUrl.pathname;
    if (nextUrl.search) {
      callbackUrl += nextUrl.search;
    }

    const encodedCallbackUrl = encodeURIComponent(callbackUrl);

    return Response.redirect(
      new URL(`/?callbackUrl=${encodedCallbackUrl}`, nextUrl),
    );
  }

  return null;

  // req.auth
});

// Optionally, don't invoke Middleware on some paths
export const config = {
  // matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
src/auth.ts

import NextAuth from 'next-auth';
import { UserRole } from '@prisma/client';
import { PrismaAdapter } from '@auth/prisma-adapter';

import { db } from '@/lib/db';
import authConfig from '@/auth.config';
import { getUserById } from '@/data/user';
import { getTwoFactorConfirmationByUserId } from '@/data/two-factor-confirmation';
import { getAccountByUserId } from './data/account';

export const {
  auth,
  signIn,
  signOut,
  unstable_update,
  handlers: { GET, POST },
} = NextAuth({
  trustHost: true,
  logger: {
    debug: console.log,
    error: console.error,
    warn: console.warn,
  },
  debug: true,
  pages: {
    signIn: '/',
    error: '/auth/error',
  },

  events: {
    async linkAccount({ user }) {
      await db.user.update({
        where: { id: user.id },
        data: { emailVerified: new Date() },
      });
    },
  },
  callbacks: {
    async signIn({ user, account }) {
      // Allow OAuth without email verification
      if (account?.provider !== 'credentials') return true;

      const existingUser = await getUserById(user.id as string);

      // Prevent sign in without email verification
      if (!existingUser?.emailVerified) return false;

      if (existingUser.isTwoFactorEnabled) {
        const twoFactorConfirmation = await getTwoFactorConfirmationByUserId(
          existingUser.id,
        );

        if (!twoFactorConfirmation) return false;

        // Delete two factor confirmation for next sign in
        await db.twoFactorConfirmation.delete({
          where: { id: twoFactorConfirmation.id },
        });
      }

      return true;
    },
    async session({ token, session }) {
      if (token.sub && session.user) {
        session.user.id = token.sub;
      }

      if (token.role && session.user) {
        session.user.role = token.role as UserRole;
      }

      if (session.user) {
        session.user.isTwoFactorEnabled = token.isTwoFactorEnabled as boolean;
      }

      if (session.user) {
        session.user.family_name = token.family_name as string;
        session.user.given_name = token.given_name as string;
        session.user.email = token.email as string;
        session.user.isOAuth = token.isOAuth as boolean;
        session.user.completedOnboarding = token.completedOnboarding as boolean;
        session.user.betaAccess = token.betaAccess as boolean;
        session.user.dailyMessageCooldownCounter =
          token.dailyMessageCooldownCounter as Date;
        session.user.dailyMessageCount = token.dailyMessageCount as number;
        session.user.stripe_customer_id = token.stripe_customer_id as string;
      }

      return session;
    },
    async jwt({ token }) {
      if (!token.sub) return token;

      const existingUser = await getUserById(token.sub);

      if (!existingUser) return token;

      const existingAccount = await getAccountByUserId(existingUser.id);

      token.isOAuth = !!existingAccount;
      token.family_name = existingUser.family_name;
      token.given_name = existingUser.given_name;
      token.email = existingUser.email;
      token.role = existingUser.role;
      token.isTwoFactorEnabled = existingUser.isTwoFactorEnabled;
      token.completedOnboarding = existingUser.completedOnboarding;
      token.betaAccess = existingUser.betaAccess;
      token.dailyMessageCooldownCounter =
        existingUser.dailyMessageCooldownCounter;
      token.dailyMessageCount = existingUser.dailyMessageCount;
      token.stripe_customer_id = existingUser.stripe_customer_id;

      return token;
    },
  },
  adapter: PrismaAdapter(db),
  session: { strategy: 'jwt' },
  ...authConfig,
});

Localhost error is still showing on Amplify

Amplify can't read auth.req in middleware

我遇到的两个错误:

�[31m[auth][error]�[0m UntrustedHost: Host must be trusted. URL was: https://dev.xyz.com/api/auth/session .Read more at https://errors.authjs.dev#untrustedhost
req {
"sourcePage": "/src/middleware",
"message": "There was a problem with the server configuration. Check the server logs for more information."
}

同样,部署到 Vercel 时一切正常,但部署到 Amplify 时则不然。任何帮助将不胜感激!

我尝试了我能想到的一切。每当我放置 NEXTAUTH_URL 时,它都无法解决 amplify 上的 /src/middlware 问题。

然后我在没有 NEXTAUTH_URL 的情况下部署到 vercel,它工作得很好。我认为问题出在 Amplify 上的某些配置上。

next.js aws-amplify next-auth
1个回答
0
投票

您需要在环境变量中更新或添加这些内容,如下所示:

.env.production
env.local
文件中

NEXTAUTH_URL=http://YOUR_LOCAL_OR_DEPLOYED_HOST_URL:HOST_PORT
AUTH_TRUST_HOST=http://YOUR_LOCAL_OR_DEPLOYED_HOST_URL:HOST_PORT

结果如下:

NEXTAUTH_URL=http://192.152.1.1:3000
AUTH_TRUST_HOST=ttp://192.152.1.1:3000
© www.soinside.com 2019 - 2024. All rights reserved.