502 Bad Gateway в производстве с Nextjs next-auth с URL-адресом '/api/auth/callback/cognito'

Я пытаюсь опубликовать приложение nextjs, которое использует next-auth с aws Cognito.

Когда я запускаю его локально, используя next dev ИЛИ next start, он работает совершенно нормально.

Когда я запускаю его на производственном сервере (ubuntu, с nginx), этого не происходит.

Точная ошибка: После доступа к встроенной странице входа Cognito URL-адрес перенаправления https://...../api/auth/callback/cognito?code=......&state=..... отображает страницу ошибки 502 по умолчанию nginx.

Что я проверил:

  • Все возможные результаты Google, проблема с github и вопрос о stackoverflow по этой теме
  • В логах ошибок производственного соседнего сервера, а также сервера nginx ничего нет.
  • Журналы консоли браузера, там ничего нет

И ДА, параметр Callback URL(s) для приложения в самом AWS Cognito установлен на правильный URL-адрес (https:// ....... /api/auth/callback/cognito).

Подробности:

КОД:

middleware.ts

export { default } from "next-auth/middleware";

export const config = { matcher: ["/dashboard/:path*"] };

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  compiler: {
    styledComponents: true,
   
  },
};

module.exports = nextConfig;

pages/api/auth/[...nextauth].ts

import CognitoProvider from "next-auth/providers/cognito";
import NextAuth, { NextAuthOptions, Session } from "next-auth";
import {
  AuthFlowType,
  CognitoIdentityProviderClient,
  InitiateAuthCommand,
} from "@aws-sdk/client-cognito-identity-provider";
import { JWT } from "next-auth/jwt";

const COGNITO_AWS_REGION = process.env.COGNITO_AWS_REGION;
const COGNITO_POOL_ID = process.env.COGNITO_POOL_ID;
const COGNITO_CLIENT_ID = process.env.COGNITO_CLIENT_ID;
const COGNITO_CLIENT_SECRET = process.env.COGNITO_CLIENT_SECRET;
const NEXTAUTH_SECRET = process.env.NEXTAUTH_SECRET;
const NEXTAUTH_URL = process.env.NEXTAUTH_URL;
if (!COGNITO_AWS_REGION) throw new Error("REGION is not set");
if (!COGNITO_CLIENT_ID) throw new Error("COGNITO_CLIENT_ID is not set");
if (!COGNITO_POOL_ID) throw new Error("COGNITO_USER_POOL_ID is not set");
if (!COGNITO_CLIENT_SECRET) throw new Error("COGNITO_CLIENT_SECRET is not set");
if (!NEXTAUTH_SECRET) throw new Error("NEXTAUTH_SECRET is not set");
if (!NEXTAUTH_URL) throw new Error("NEXTAUTH_URL is not set");

const refreshCognitoAccessToken = async (token: JWT) => {
  const client = new CognitoIdentityProviderClient({
    region: COGNITO_AWS_REGION,
  });
  const command = new InitiateAuthCommand({
    AuthFlow: AuthFlowType.REFRESH_TOKEN_AUTH,
    ClientId: COGNITO_CLIENT_ID,
    AuthParameters: {
      REFRESH_TOKEN: token.refreshToken as string,
    },
  });
  const response = await client.send(command);
  return response.AuthenticationResult;
};

export const authOptions: NextAuthOptions = {
  secret: NEXTAUTH_SECRET,
  // @ts-expect-error -- this property is not documented properly
  site: NEXTAUTH_URL,
  providers: [
    CognitoProvider({
      clientId: COGNITO_CLIENT_ID!,
      issuer: `https://cognito-idp.${COGNITO_AWS_REGION}.amazonaws.com/${COGNITO_POOL_ID!}`,
      clientSecret: process.env.COGNITO_CLIENT_SECRET!,
      
    }),
  ],
  callbacks: {
    jwt: async ({ token, account, user }) => {
      // Initial sign in
      if (account && user) {
        return {
          // save token to session for authenticating to AWS
          // https://next-auth.js.org/configuration/callbacks#jwt-callback
          accessToken: account.access_token,
          accessTokenExpires: account.expires_at
            ? account.expires_at * 1000
            : 0,
          refreshToken: account.refresh_token,
          user,
        };
      }

      // Return previous token if the access token has not expired yet
      if (Date.now() < (token as unknown as Session).accessTokenExpires) {
        return token;
      }

      // Access token has expired, try to update it
      const refreshedTokens = await refreshCognitoAccessToken(token);
      return {
        ...token,
        accessToken: refreshedTokens?.AccessToken,
        accessTokenExpires: refreshedTokens?.ExpiresIn
          ? Date.now() + refreshedTokens?.ExpiresIn * 1000
          : 0,
        refreshToken: refreshedTokens?.RefreshToken ?? token.refreshToken, // Fall back to old refresh token
      };
    },

    session: async ({ session, token }) => {
      if (!session?.user || !token?.accessToken) {
        console.error("No accessToken found on token or session");
        return session;
      }
      session.user = token.user as Session["user"];
      session.accessToken = token.accessToken as string;
      session.error = token.error as string | undefined;

      return session;
    },
    redirect: async ({ url, baseUrl }) => {
      // allows any url
      if (url.startsWith("/")) return `${baseUrl}${url}`;
      return url;
    },
  },
};

export default NextAuth(authOptions);
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
3
0
172
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, в конце концов я сам это понял, оказывается, я неправильно читал свои журналы nginx, как только я это сделал, это не было чем-то слишком сложным... вот что я сделал:

Самое важное:

Ошибка 502, скорее всего, соответствует ошибке upstream sent too big header while reading response header from upstream в журналах ошибок nginx для этого запроса. Чтобы решить эту проблему, добавьте это в свою конфигурацию под /etc/nginx/nginx.conf в разделе http {... } ...

proxy_buffers 8 16k;
proxy_buffer_size 32k;

(нашел это решение здесь: https://stackoverflow.com/a/38758325/4205839)

Дополнительные вещи, чтобы попробовать:

Вышеприведенное должно решить ошибку 502, но вы все еще можете получать ошибки с next-auth, вот еще несколько вещей, которые я обнаружил, пытаясь решить эту проблему...

В AWS Cognito попробуйте создать, а затем использовать новый «Клиент приложения» в AWS Cognito БЕЗ секрета клиента.

Если вы запустите его сейчас, вы получите такие ошибки, как signin?error=OAuthCallback и client_secret_basic client authentication method requires a client_secret. Так что вам также нужно будет обновить конфигурацию cognito в pages/api/auth/[...nextauth].ts, чтобы быть ...

CognitoProvider({
clientId: COGNITO_CLIENT_ID,
      issuer: `https://cognito-idp.${COGNITO_AWS_REGION}.amazonaws.com/${COGNITO_POOL_ID!}`,
      clientSecret: "someString",
      client: {
           token_endpoint_auth_method: "none",
      },
})

который я обнаружил из этого обсуждения: https://github.com/nextauthjs/next-auth/issues/2524

Примечание. Если вы получаете что-то вроде ошибки redirect_mismatch от Cognito, это означает, что вы неправильно обновили URL-адреса в настройках своего клиентского приложения AWS Cognito, что часто случается при переключении между локальным и оперативным для отладки.

Другие вопросы по теме