-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
127 lines (111 loc) · 5.05 KB
/
auth.ts
File metadata and controls
127 lines (111 loc) · 5.05 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
import { getTwoFactorConfirmationByUserId } from "@/data/two-factor-confirmation";
import { db } from "@/lib/db";
import { PrismaAdapter } from "@auth/prisma-adapter";
import NextAuth from "next-auth";
import authConfig from "./auth.config";
import { getAccountByUserId } from "./data/account";
import { getUserById } from "./data/user";
// NOTE IMPORTANTE:
// 1. Prisma poate fi folosită pe edge cu NextAuth prin PrismaAdapter
// 2. NextAuth creează automat un utilizator în baza de date când cineva se autentifică cu OAuth, dar doar dacă folosești un adapter, cum ar fi PrismaAdapter.
// 3. Callback-urile 'jwt' și 'session' sunt executate la fiecare request pentru a menține sesiunea actualizată și validă.
// 4. Când se execută jwt?
// 4.1 La login – când user-ul se autentifică pentru prima dată.
// 4.2 La fiecare request către server – pentru a verifica dacă token-ul este încă valid.
// 4.3 La fiecare refresh token (dacă există refresh logic implementat).
// 5. Session nu este stocată permanent pe server (pentru strategy: "jwt"
// 6. Session se execută, astfel de fiecare data cand tokenul JWT se schimba, deci la fiecare request pentru a reconstrui sesiunea din token.
// 7. Callback-urile jwt și session se execută înainte ca răspunsul să plece către client.
export const {
auth,
signIn,
signOut,
handlers: { GET, POST },
} = NextAuth({
// Configurarea paginilor pentru autentificare
pages: {
signIn: "/auth/login", // Pagină de login
error: "/auth/error", // Pagină de eroare
},
// Evenimentele din NextAuth
events: {
async linkAccount({ user }) {
// Evenimentul care se execută după asocierea unui cont OAuth cu utilizatorul în baza de date
await db.user.update({
where: { id: user.id }, // Actualizăm utilizatorul cu data de verificare a email-ului
data: { emailVerified: new Date() }, // Setăm emailVerified la data curentă
});
},
},
// Callback-urile NextAuth
callbacks: {
// Callback pentru procesul de autentificare
// Se execută după autentificarea de la provider, înainte ca utilizatorul să fie stocat în sesiune.
async signIn({ user, account }) {
console.log(user, account);
// 1. Permitem autentificarea OAuth fără verificarea email-ului
if (account?.provider !== "credentials") return true;
// 2. Blocăm autentificarea cu credențiale fără verificarea email-ului
const existingUser = await getUserById(user.id);
if (!existingUser || !existingUser.emailVerified) {
return false; // Dacă email-ul nu este verificat, blocăm autentificarea
}
// 3. Verificare 2FA
if (existingUser.isTwoFactorEnabled) {
const twoFactorConfirmation = await getTwoFactorConfirmationByUserId(
existingUser.id
);
if (!twoFactorConfirmation) return false; // Dacă nu există confirmare 2FA, blocăm autentificarea
await db.twoFactorConfirmation.delete({
where: { id: twoFactorConfirmation.id }, // Ștergem confirmarea 2FA pentru următoarea autentificare
});
}
return true; // Permitem autentificarea
},
// Callback pentru sesiune
// Se execută după jwt, când sesiunea este generată și trimisă către client.
async session({ token, session }) {
// Atribuim valorile din token la sesiunea curentă
if (token.sub && session.user) {
session.user.id = token.sub;
}
if (token.role && session.user) {
session.user.role = token.role as "ADMIN" | "USER";
}
if (session.user) {
session.user.isTwoFactorEnabled = token.isTwoFactorEnabled as boolean;
session.user.isOAuth = token.isOAuth as boolean;
}
// Actualizăm sesiunea cu informațiile utilizatorului (update())
if (session.user) {
session.user.name = token.name as string;
session.user.email = token.email as string;
}
console.log({ session: session });
return session; // Returnăm sesiunea finală
},
// Callback pentru generarea JWT
// Se execută după signIn, dar înainte ca token-ul JWT să fie generat.
async jwt({ token }) {
// Verificăm și adăugăm informațiile necesare în token
if (!token.sub) return token;
const existingUser = await getUserById(token.sub);
if (!existingUser) return token;
// Verificăm dacă utilizatorul s-a logat prin OAuth
const existingAccount = await getAccountByUserId(existingUser.id);
token.role = existingUser.role;
token.isTwoFactorEnabled = existingUser.isTwoFactorEnabled;
token.isOAuth = !!existingAccount; // Setăm isOAuth dacă există un cont asociat OAuth
// Actualizăm token-ul cu informațiile utilizatorului
token.name = existingUser.name;
token.email = existingUser.email;
return token; // Permitem crearea token-ului JWT
},
},
// Configurarea PrismaAdapter
adapter: PrismaAdapter(db),
// Folosim strategia JWT pentru sesiune
session: { strategy: "jwt" },
// Configurația suplimentară NextAuth
...authConfig,
});