-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
173 lines (153 loc) · 4.83 KB
/
auth.ts
File metadata and controls
173 lines (153 loc) · 4.83 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
import bcrypt from "bcryptjs";
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
import GitHub from "next-auth/providers/github";
import Google from "next-auth/providers/google";
import { IAccountDoc } from "./database/account.model";
import { IUserDoc } from "./database/user.model";
import { api } from "./lib/api";
import { SignInSchema } from "./lib/validations";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
GitHub,
Google,
Credentials({
async authorize(credentials) {
try {
const validatedFields = SignInSchema.safeParse(credentials);
if (!validatedFields.success) {
console.error(
"[Credentials Authorize] Validation failed:",
validatedFields.error.flatten()
);
return null;
}
const { email, password } = validatedFields.data;
const normalizedEmail = email.trim().toLowerCase();
const { data: existingAccount } = (await api.accounts.getByProvider(
normalizedEmail
)) as ActionResponse<IAccountDoc>;
if (
!existingAccount ||
existingAccount.provider !== "credentials" ||
!existingAccount.password
) {
console.error(
"[Credentials Authorize] No credentials account found for email:",
normalizedEmail
);
return null;
}
const { data: existingUser } = (await api.users.getById(
existingAccount.userId.toString()
)) as ActionResponse<IUserDoc>;
if (!existingUser) {
console.error(
"[Credentials Authorize] No user found for account userId:",
existingAccount.userId
);
return null;
}
const isValidPassword = await bcrypt.compare(
password,
existingAccount.password!
);
if (!isValidPassword) {
console.error(
"[Credentials Authorize] Invalid password for email:",
normalizedEmail
);
return null;
}
return {
id: existingUser.id,
name: existingUser.name,
email: existingUser.email,
image: existingUser.image,
};
} catch (error) {
console.error("[Credentials Authorize] Unexpected error:", error);
return null;
}
},
}),
],
callbacks: {
async session({ session, token }) {
try {
session.user.id = token.sub as string;
return session;
} catch (error) {
console.error(
"[Session Callback] Error setting session user ID:",
error
);
return session;
}
},
async jwt({ token, account }) {
try {
if (account) {
const { data: existingAccount, success } =
(await api.accounts.getByProvider(
account.type === "credentials"
? token.email!
: account.providerAccountId
)) as ActionResponse<IAccountDoc>;
if (!success || !existingAccount) {
console.error(
"[JWT Callback] No account found for:",
token.email || account.providerAccountId
);
return token;
}
const userId = existingAccount.userId;
if (userId) token.sub = userId.toString();
}
return token;
} catch (error) {
console.error("[JWT Callback] Unexpected error:", error);
return token;
}
},
async signIn({ user, profile, account }) {
try {
if (account?.type === "credentials") return true;
if (!account || !user) {
console.error(
"[SignIn Callback] Missing account or user information"
);
return false;
}
const userInfo = {
name: user.name!,
email: user.email!,
image: user.image!,
username:
account.provider === "github"
? (profile?.login as string)
: (user.name?.toLowerCase() as string),
};
const { success } = (await api.auth.oAuthSignIn({
user: userInfo,
provider: account.provider as "github" | "google",
providerAccountId: account.providerAccountId,
})) as ActionResponse;
if (!success) {
console.error(
"[SignIn Callback] OAuth signup failed for provider:",
account.provider
);
return false;
}
return true;
} catch (error) {
console.error(
"[SignIn Callback] Unexpected error during OAuth signup:",
error
);
return false;
}
},
},
});