// app/api/auth/[...nextauth]/route.js
import NextAuth, { AuthOptions } from "next-auth";
import KakaoProvider from "next-auth/providers/kakao";
// import { NextApiHandler } from "next";
// import { NextRequest, NextResponse } from "next/server";
// 다른 프로바이더들도 추가할 수 있습니다 (예: GitHub, Facebook 등)
export const authOptions: AuthOptions = {
providers: [
KakaoProvider({
clientId: process.env.NEXT_AUTH_KAKAO_ID || "",
clientSecret: process.env.NEXT_AUTH_KAKAO_CLIENT_SECRET || "",
}),
],
secret: process.env.NEXTAUTH_SECRET || "", // 보안을 위해 secret 설정 필요
session: {
strategy: "jwt",
},
pages: {
signIn: "/auth/signin", // 커스텀 로그인 페이지
},
callbacks: {
async session({ session, token }: any) {
session.user.id = token.sub;
return session;
},
},
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
//src/app/context/AuthContext.tsx
//클라이언트단에서 적용되므로 따로 빼줘야함
"use client";
import { SessionProvider } from "next-auth/react";
type Props = {
children?: React.ReactNode;
};
export const NextAuthProvider = ({ children }: Props) => {
return <SessionProvider>{children}</SessionProvider>;
};
//src/app/layout.tsx
import type { Metadata } from "next";
import { NextAuthProvider } from "@/app/context/AuthContext";
import { Inter } from "next/font/google";
import "./globals.css";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter";
import { ThemeProvider } from "@mui/material/styles";
import theme from "../theme";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<AppRouterCacheProvider>
<NextAuthProvider>
<ThemeProvider theme={theme}>{children} </ThemeProvider>
</NextAuthProvider>
</AppRouterCacheProvider>
</body>
</html>
);
}
카카오 로그인 Redirect Url설정
내 애플리케이션>제품 설정>카카오 로그인에서 설정해준다.
로그인 화면 작성
//임시로 만든 테스트 화면
"use client";
import { useEffect, useState } from "react";
import { Box, Typography, Button } from "@mui/material";
import { getProviders, signIn } from "next-auth/react";
const SignInPage = () => {
const callbackUrl = process.env.NEXT_PUBLIC_HOMEPAGE_URL as string;
const [providers, setProviders] = useState<any>({});
//제공하는 sso 로그인 리스트들 가져오기
useEffect(() => {
async function loadProviders() {
const res = await getProviders();
setProviders(res);
}
loadProviders();
}, []);
return (
<Box>
<Typography>로그인 page</Typography>
{Object.values(providers).map((provider: any) => (
<div key={provider.name}>
<Button
variant="contained"
onClick={() => signIn(provider.id, { callbackUrl })}
>
{provider.name} 로그인
</Button>
</div>
))}
</Box>
);
};
export default SignInPage;