-
Notifications
You must be signed in to change notification settings - Fork 1
/
auth.config.ts
100 lines (83 loc) · 3.19 KB
/
auth.config.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
import type { NextAuthConfig } from "next-auth";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import bcrypt from "bcrypt";
import { CustomJWT, CustomSession } from '@/auth-types';
import { SignInSchema } from "@/schemas";
import getUserByEmail from "@/utils/getUserByEmail";
import getUserById from "@/utils/getUserById";
// Notice this is only an object, not a full Auth.js instance
export default {
providers: [
GitHub,
Credentials({
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
// e.g. domain, username, password, 2FA token, etc.
credentials: {
email: { label: "Email", type: "email", placeholder: "Enter your email address" },
password: { label: "Password", type: "password", placeholder: "**************" },
},
authorize: async (credentials) => {
// Validate the credentials using the SignInSchema
const parsedValues = SignInSchema.safeParse(credentials);
if (parsedValues.success) {
const { email, password } = parsedValues.data;
// Retrieve the user by email from the database
const user = await getUserByEmail(email);
// Check if the user exists and has a password (not an OAuth user)
if (!user || !user.password) {
// If no user or user password (user may have signed-in with OAuth Google or GitHub)
// Credentials provider will not work without the user's hashed password
return null;
}
const passwordsMatch = await bcrypt.compare(
password, // The password credential input
user.password, // The password hash from our database
);
if (passwordsMatch) {
// Return user object with their profile data
return user;
}
}
// Return null if validation or authentication fails
return null;
},
}),
],
callbacks: {
async jwt({ token, user }) {
const customToken = token as CustomJWT;
// Initial sign in
if (user) {
if (user.id && user.email) {
customToken.id = user.id;
customToken.email = user.email;
}
}
if (!token.sub) { return token; }
const existingUser = await getUserById(token.sub);
if (!existingUser) { return token; }
token.role = existingUser.role;
return customToken;
},
async session({ session, token }) {
const customSession = session as CustomSession;
const customToken = token as CustomJWT;
// Add token properties to the session
if (customToken) {
customSession.user.id = customToken.id;
customSession.user.email = customToken.email;
customSession.user.role = customToken.role;
}
// Assign the session.sub field (which is the ID) to the session.id
if (token.sub && session.user) {
session.user.id = token.sub;
}
// Add token role property to the session
if (token.role && session.user) {
session.user.role = token.role;
}
return customSession;
},
},
} satisfies NextAuthConfig;