-
Notifications
You must be signed in to change notification settings - Fork 2
/
auth.ts
127 lines (101 loc) · 3.42 KB
/
auth.ts
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
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"
import Google from "next-auth/providers/google";
import { SanityAdapter } from "./adapters/sanity-adapter"
import sanityClient from "./lib/sanityClient"
import Credentials from "next-auth/providers/credentials"
import { LoginSchema } from "./form-schemas"
import bcrypt from "bcryptjs";
import { getUserById } from "./data/user"
import { getTwoFactorConfirmationByUserId } from "./data/two-factor-confirmation";
import { getAccountByUserId } from "./data/account";
export const {
handlers: { GET, POST },
auth,
signIn,
signOut,
//unstable update in Beta version
unstable_update
} = NextAuth({
pages: {
signIn: "/auth/login",
error: "/auth/error"
},
providers: [
GitHub({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
}),
Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET
}),
Credentials({
async authorize(credentials) {
//if not using zod resolvers validated fields arent necessary
const validatedFields = LoginSchema.safeParse(credentials);
if(!validatedFields.success) return null;
const user_qry = `*[_type == "user" && email== "${credentials?.email}"][0]`;
const user = await sanityClient.fetch(user_qry);
if (!user || !user.password) return null;
const passwordsMatch = await bcrypt.compare(credentials?.password as string, user.password);
if (passwordsMatch) {
return {
id: user._id,
role: user.role,
...user
};
}
return null;
}
})
],
session: { strategy: "jwt"},
adapter: SanityAdapter(sanityClient),
callbacks: {
async signIn({user, account}) {
if (account?.provider !== "credentials") return true;
const existingUser = await getUserById(user.id!)
// prevent signIn without email verification
if(!existingUser?.emailVerified) return false;
// 2FA CHECK
if(existingUser.isTwoFactorEnabled) {
const twoFactorConfirmation = await getTwoFactorConfirmationByUserId(existingUser._id);
if(!twoFactorConfirmation) return false;
//Delete 2FA for next signin
await sanityClient.delete(twoFactorConfirmation._id);
}
return true
},
//@ts-ignore
async session({ session, token }){
if(token.sub && session.user) {
session.user.id = token.sub;
}
if(token.role && session.user) {
session.user.role = token.role;
}
if(session.user) {
session.user.isTwoFactorEnabled = token.isTwoFactorEnabled as boolean;
}
if(session.user) {
session.user.name = token.name;
session.user.email = token.email;
session.user.isOAuth = token.isOAuth as boolean;
}
return session
},
async jwt({ token }){
if(!token.sub) return token;
const existingUser = await getUserById(token.sub);
if (!existingUser) return token;
const existingAccount = await getAccountByUserId(existingUser._id);
token.isOAuth = !!existingAccount;
token.name = existingUser.name;
token.email = existingUser.email;
token.role = existingUser.role;
token.isTwoFactorEnabled = existingUser.isTwoFactorEnabled
return token;
},
},
})