728x90
1. 문제가 있던 코드 ( /api/auth/[...nextauth].js )
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import NextAuth, { AuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import DiscordProvider from "next-auth/providers/discord";
import CredentialsProvider from "next-auth/providers/credentials";
import { connectDB } from "@/util/database";
import { compare } from "bcryptjs";
export const authOptions: AuthOptions = {
providers: [
// GitHub 로그인
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
}),
// Google 로그인
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
}),
// Discord 로그인
DiscordProvider({
clientId: process.env.DISCORD_CLIENT_ID || "",
clientSecret: process.env.DISCORD_CLIENT_SECRET || "",
}),
// Credentials 로그인
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "text" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
if (!credentials) {
throw new Error("Missing credentials");
}
const db = (await connectDB).db("StellarLink");
const user = await db.collection("user_cred").findOne({ email: credentials.email });
if (!user) {
console.log("해당 이메일은 없음");
return null;
}
const isValidPassword = await compare(credentials.password, user.password);
console.log(isValidPassword: , isValidPassword);
if (!isValidPassword) {
console.log("비밀번호 틀림");
return null;
}
// 로그인 성공
console.log("로그인 성공", user);
return {
id: user._id.toString(),
name: user.name,
email: user.email,
profileImage: user.profileImage || "/default-profile.png", // 기본 프로필 이미지 설정
};
},
}),
],
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, // 30일
},
callbacks: {
jwt: async ({ token, user, account }) => {
if (user && account) {
token.user = {
name: user.name,
email: user.email,
profileImage: user.profileImage,
provider: account.provider, // provider 정보 추가
};
}
return token;
},
session: async ({ session, token }) => {
if (token.user) {
session.user = token.user as {
name: string;
email: string;
profileImage: string;
provider: string; // provider 정보 추가
};
}
return session;
},
},
secret: process.env.NEXTAUTH_SECRET, //CSRF 공격 방지
adapter: MongoDBAdapter(connectDB),
};
export default NextAuth(authOptions);
2. authOptions 코드에서 세션이 즉시 업데이트되지 않는 이유
callbacks.session이 클라이언트에서 호출될 때 token.user에 저장된 데이터를 사용하기 때문입니다.
그러나 데이터베이스에서 변경된 값을 가져오지 않으면 갱신된 정보를 반영할 수 없습니다.
세션 정보를 즉시 갱신하려면 callbacks.session 또는 callbacks.jwt 에서 데이터베이스와 동기화하도록 설정해야 합니다.
3. 수정된 코드
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import NextAuth, { AuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import DiscordProvider from "next-auth/providers/discord";
import CredentialsProvider from "next-auth/providers/credentials";
import { connectDB } from "@/util/database";
import { compare } from "bcryptjs";
interface UserToken {
name: string;
email: string;
profileImage: string;
provider: string;
}
export const authOptions: AuthOptions = {
providers: [
// GitHub 로그인
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
}),
// Google 로그인
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
}),
// Discord 로그인
DiscordProvider({
clientId: process.env.DISCORD_CLIENT_ID || "",
clientSecret: process.env.DISCORD_CLIENT_SECRET || "",
}),
// Credentials 로그인
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "text" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
if (!credentials) {
throw new Error("Missing credentials");
}
const db = (await connectDB).db("StellarLink");
const user = await db.collection("user_cred").findOne({ email: credentials.email });
if (!user) {
console.log("해당 이메일은 없음");
return null;
}
const isValidPassword = await compare(credentials.password, user.password);
console.log(`isValidPassword: `, isValidPassword);
if (!isValidPassword) {
console.log("비밀번호 틀림");
return null;
}
// 로그인 성공
console.log("로그인 성공", user);
return {
id: user._id.toString(),
name: user.name,
email: user.email,
profileImage: user.profileImage || "/default-profile.png", // 기본 프로필 이미지 설정
};
},
}),
],
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, // 30일
},
callbacks: {
jwt: async ({ token, user, account }) => {
if (user && account) {
token.user = {
name: user.name,
email: user.email,
profileImage: user.profileImage,
provider: account.provider,
} as UserToken; // 타입 캐스팅
}
return token;
},
session: async ({ session, token }) => {
if (token.user) {
const db = (await connectDB).db("StellarLink");
const user = await db.collection("user_cred").findOne({ email: (token.user as UserToken).email });
if (user) {
session.user = {
name: user.name,
email: user.email,
profileImage: user.profileImage || "/default-profile.png", // 기본 프로필 이미지 설정
provider: (token.user as UserToken).provider, // 기존 provider 유지
};
}
}
return session;
},
},
secret: process.env.NEXTAUTH_SECRET, // CSRF 공격 방지
adapter: MongoDBAdapter(connectDB),
};
export default NextAuth(authOptions);
실질적으로 수정된 코드
callbacks: {
jwt: async ({ token, user, account }) => {
if (user && account) {
token.user = {
name: user.name,
email: user.email,
profileImage: user.profileImage,
provider: account.provider,
} as UserToken; // 타입 캐스팅
}
return token;
},
session: async ({ session, token }) => {
if (token.user) {
const db = (await connectDB).db("StellarLink");
const user = await db.collection("user_cred").findOne({ email: (token.user as UserToken).email });
if (user) {
session.user = {
name: user.name,
email: user.email,
profileImage: user.profileImage || "/default-profile.png", // 기본 프로필 이미지 설정
provider: (token.user as UserToken).provider, // 기존 provider 유지
};
}
}
return session;
},
},
- 세션 콜백에 데이터베이스에서 값을 받아오는 코드를 새로 작성
728x90