-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
115 lines (110 loc) · 3.28 KB
/
auth.ts
File metadata and controls
115 lines (110 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import NextAuth from 'next-auth'
import GitHub from 'next-auth/providers/github'
import Google from 'next-auth/providers/google'
import Kakao from 'next-auth/providers/kakao'
import { PrismaAdapter } from '@auth/prisma-adapter'
import { prisma } from '@/lib/core/prisma'
// 카카오 API 응답 타입 (공식 문서 기준)
interface KakaoProfile {
id: number
kakao_account?: {
profile?: {
nickname?: string
profile_image_url?: string
thumbnail_image_url?: string
}
}
}
export const { auth, handlers, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
debug: process.env.NODE_ENV === 'development',
session: {
strategy: 'jwt',
maxAge: 30 * 24 * 60 * 60, // 30일 기본 세션 만료
updateAge: 24 * 60 * 60, // 24시간마다 세션 업데이트
},
pages: {
signIn: '/auth/signin',
},
cookies: {
pkceCodeVerifier: {
name: 'authjs.pkce.code_verifier',
options: {
httpOnly: true,
sameSite: 'lax',
path: '/',
secure: process.env.NODE_ENV === 'production',
},
},
},
callbacks: {
async jwt({ token, user, trigger }) {
if (user) {
// 첫 로그인 시 DB에서 사용자 정보 가져오기
const dbUser = await prisma.user.findUnique({
where: { id: user.id },
select: { globalRole: true },
})
token.role = dbUser?.globalRole || 'USER'
}
// 세션 업데이트 시 DB에서 최신 역할 정보 가져오기
if (trigger === 'update' && token.sub) {
const dbUser = await prisma.user.findUnique({
where: { id: token.sub },
select: { globalRole: true },
})
token.role = dbUser?.globalRole || 'USER'
}
// 기존 세션에도 role이 없다면 다시 조회
if (!token.role && token.sub) {
const dbUser = await prisma.user.findUnique({
where: { id: token.sub },
select: { globalRole: true },
})
token.role = dbUser?.globalRole || 'USER'
}
return token
},
session({ session, token }) {
if (token && token.sub) {
session.user.id = token.sub
session.user.role = token.role as 'USER' | 'MANAGER' | 'ADMIN'
}
return session
},
async signIn() {
return true
},
},
providers: [
GitHub({
clientId: process.env.AUTH_GITHUB_ID!,
clientSecret: process.env.AUTH_GITHUB_SECRET!,
}),
Google({
clientId: process.env.AUTH_GOOGLE_ID!,
clientSecret: process.env.AUTH_GOOGLE_SECRET!,
authorization: {
params: {
prompt: 'consent',
access_type: 'offline',
response_type: 'code',
},
},
}),
Kakao({
clientId: process.env.AUTH_KAKAO_ID!,
clientSecret: process.env.AUTH_KAKAO_SECRET!,
// 카카오 API는 kakao_account.profile 구조로 사용자 정보 반환
// NextAuth가 이를 자동으로 파싱하지 못하므로 수동 매핑 필요
profile(profile: KakaoProfile) {
return {
id: String(profile.id),
name: profile.kakao_account?.profile?.nickname || null,
email: null, // 카카오는 이메일 미제공
image: profile.kakao_account?.profile?.profile_image_url || null,
}
},
}),
],
})