본문 바로가기
Application/Javascript 패밀리 (React, next.js ..)

[Next.js] next-auth 구글, aws 코그니토 연동 관련

by 노반장 2023. 10. 14.

next-auth를 활용하여 간편가입을 연동하고, 코그니토와 연동관련 코드

import NextAuth, { Account, User, Profile } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import AWS from "aws-sdk";
import Config from "../../../../../config/config.export";

AWS.config.update({ region: "ap-northeast-2" });
const cognito = new AWS.CognitoIdentityServiceProvider();

// JWT만료 확인. BE에서 검증으로 주석처리
// const isTokenExpired = (token: JWT) => {
//   const decodedToken = jwtDecode(token);
//   const currentTime = Date.now() / 1000; // 현재 시간을 초 단위로 변환
//   return decodedToken.exp < currentTime;
// };
// CognitoToken 받아오는 함수
const getCognitoToken = async (email: string, name: string) => {
  try {
    const response = await cognito
      .adminInitiateAuth({
        AuthFlow: "ADMIN_NO_SRP_AUTH",
        ClientId: process.env.COGNITO_CLIENT_ID!,
        UserPoolId: process.env.COGNITO_USER_POOL_ID!,
        AuthParameters: {
          USERNAME: email,
          PASSWORD: "Abc1234!",
        },
      })
      .promise();

    return response.AuthenticationResult?.IdToken;
  } catch (error) {
    console.error("Failed to get Cognito token:", error);
    return null;
  }
};

const handler = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID || "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
    }),

    // ...
  ],
  callbacks: {
    signIn: async ({ user, account }) => {
      if (account?.provider === "google" && user?.email && user?.name) {
        const email = user.email;
        const name = user.name;
        const password = "Abc1234!";
        try {
          // Cognito User Pool에서 사용자 조회
          const listUsersResponse = await cognito
            .listUsers({
              UserPoolId: process.env.COGNITO_USER_POOL_ID!,
              Filter: `email = "${email}"`,
            })
            .promise();

          // 사용자가 존재하지 않으면 새 사용자 생성
          if (listUsersResponse?.Users?.length === 0) {
            console.log("email : ", user.email);
            console.log("name : ", user.name);
            await cognito
              .adminCreateUser({
                UserPoolId: process.env.COGNITO_USER_POOL_ID!,
                Username: email,
                TemporaryPassword: "Abc1992!",
                // 필요한 경우 추가 사용자 속성 설정
                UserAttributes: [
                  {
                    Name: "email",
                    Value: email,
                  },
                ],
              })
              .promise();
            await cognito
              .adminSetUserPassword({
                UserPoolId: process.env.COGNITO_USER_POOL_ID!,
                Username: email,
                Password: password,
                Permanent: true,
              })
              .promise();
          }
          // 백엔드 API 호출을 위한 fetch 요청
          const response = await fetch(Config().baseUrl + "/wotd/saveUser", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              email: email,
              name: name,
            }),
          });

          if (!response.ok) {
            throw new Error("Failed to save user to DB via API");
          }
          return true;
        } catch (error) {
          console.error(error);
          return false;
        }
      }
      return true;
    },
    jwt: async ({ token, user, account }) => {
      if (account?.provider === "google") {
        token.id = user.id;
        token.email = user.email;
        token.name = user.name;

        // Cognito에서 JWT 토큰 받아오기
        if (typeof user.email === "string" && typeof user.name === "string") {
          const cognitoToken = await getCognitoToken(user.email, user.name);
          if (cognitoToken) {
            token.cognitoToken = cognitoToken;
          }
        }
      }
      console.log("JWT Token:", token);

      return token;
    },
    session: async ({ session, token }) => {
      //   if (isTokenExpired(token)) {
      //     return null; // 세션 종료
      //   }
      if (typeof token.cognitoToken === "string") {
        session.cognitoToken = token.cognitoToken;
      }
      return session;
    },
  },
});

export { handler as GET, handler as POST };
function jwtDecode(token: JWT) {
  throw new Error("Function not implemented.");
}

댓글