-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
199 lines (184 loc) · 6.36 KB
/
auth.ts
File metadata and controls
199 lines (184 loc) · 6.36 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";
// getServerSession будет импортирован в lib/auth.ts
// Валидация переменных окружения
function validateEnvVars() {
const missing: string[] = [];
if (!process.env.GOOGLE_CLIENT_ID) {
missing.push("GOOGLE_CLIENT_ID");
}
if (!process.env.GOOGLE_CLIENT_SECRET) {
missing.push("GOOGLE_CLIENT_SECRET");
}
if (!process.env.NEXTAUTH_SECRET) {
missing.push("NEXTAUTH_SECRET");
}
if (missing.length > 0) {
const errorMessage = `Отсутствуют переменные окружения: ${missing.join(
", "
)}. Проверьте настройки Vercel: Settings → Environment Variables → Production`;
console.error("[NextAuth] " + errorMessage);
throw new Error(errorMessage);
}
}
// В NextAuth v4 используется NEXTAUTH_URL
const nextAuthUrl = process.env.NEXTAUTH_URL;
// Логируем информацию о URL для диагностики
console.log("[NextAuth] URL конфигурация:", {
NEXTAUTH_URL: nextAuthUrl || "не установлен",
VERCEL_URL: process.env.VERCEL_URL || "не установлен",
NODE_ENV: process.env.NODE_ENV,
VERCEL: process.env.VERCEL || "не установлен",
});
if (
!nextAuthUrl &&
(process.env.NODE_ENV === "production" || process.env.VERCEL)
) {
console.warn(
"[NextAuth] ВНИМАНИЕ: NEXTAUTH_URL не установлен в production! Это может вызвать ошибку Configuration."
);
}
// Конфигурация NextAuth
export const authOptions: any = {
adapter: PrismaAdapter(prisma) as any,
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
// Явно указываем authorization URL для избежания проблем с локализованными доменами
authorization: {
url: "https://accounts.google.com/o/oauth2/v2/auth",
params: {
prompt: "consent",
access_type: "offline",
response_type: "code",
// Принудительно используем английский язык и основной домен .com
hl: "en",
// Принудительно используем английский (США) для избежания локализованных доменов
gl: "us",
},
},
}),
],
callbacks: {
async signIn({
user,
account,
profile,
}: {
user: any;
account: any;
profile?: any;
}) {
try {
console.log("[NextAuth] signIn callback:", {
user: user?.email,
provider: account?.provider,
hasAccount: !!account,
hasProfile: !!profile,
accountType: account?.type,
accountId: account?.id,
});
// В production всегда логируем для диагностики
if (process.env.VERCEL || process.env.NODE_ENV === "production") {
console.log("[NextAuth] signIn callback (production):", {
userEmail: user?.email,
provider: account?.provider,
hasAccount: !!account,
hasProfile: !!profile,
});
}
if (account?.provider === "google") {
return true;
}
return true;
} catch (error) {
console.error("[NextAuth] Ошибка в signIn callback:", error);
if (error instanceof Error) {
console.error("[NextAuth] Сообщение об ошибке:", error.message);
}
throw error;
}
},
async redirect({ url, baseUrl }: { url: string; baseUrl: string }) {
console.log("[NextAuth] redirect callback:", { url, baseUrl }); // Always log for diagnosis
if (url.startsWith("/")) {
const redirectUrl = `${baseUrl}${url}`;
if (url === "/login") {
return `${baseUrl}/dashboard`;
}
return redirectUrl;
}
try {
const urlObj = new URL(url);
if (urlObj.origin === baseUrl) {
if (urlObj.pathname === "/login") {
return `${baseUrl}/dashboard`;
}
return url;
}
} catch (e) {
console.error("[NextAuth] Ошибка парсинга URL в redirect callback:", e); // Log parsing errors
// Fallback to dashboard if URL parsing fails
}
return `${baseUrl}/dashboard`;
},
async session({
session,
token,
user,
}: {
session: any;
token: any;
user?: any;
}) {
if (session?.user) {
if (user) {
session.user.id = user.id;
} else if (token?.sub) {
session.user.id = token.sub;
}
}
return session;
},
async jwt({ token, user }: { token: any; user?: any }) {
if (user) {
token.id = user.id;
}
return token;
},
},
pages: {
signIn: "/login",
error: "/api/auth/error",
},
secret: process.env.NEXTAUTH_SECRET,
debug: true, // Включаем debug для диагностики на Vercel
// Явно указываем URL для правильной работы callback на Vercel
...(nextAuthUrl ? { url: nextAuthUrl } : {}),
};
// Инициализируем NextAuth
let nextAuthHandler: ReturnType<typeof NextAuth> | null = null;
function getNextAuthHandler() {
if (nextAuthHandler) {
return nextAuthHandler;
}
try {
validateEnvVars();
console.log("[NextAuth] Инициализация NextAuth v4...");
nextAuthHandler = NextAuth(authOptions);
console.log("[NextAuth] NextAuth v4 успешно инициализирован");
return nextAuthHandler;
} catch (error) {
console.error("[NextAuth] Ошибка при инициализации NextAuth:", error);
if (error instanceof Error) {
console.error("[NextAuth] Сообщение об ошибке:", error.message);
}
throw error;
}
}
// Экспортируем authOptions для использования в route.ts
// Обработчики GET и POST создаются в route.ts
// Экспортируем authOptions для использования в lib/auth.ts