chore: update src/pages/api/user/settings/2fa.ts

swadhinbiswas committed 8 months ago
54451ac
1 parent 861ca9f
commit 54451ac
1 file changed
+20 -13
Showing 1 changed file+20-13
▼src/pages/api/user/settings/2fa.ts
+20-13
32
32
// Generate QR Code
33
33
const qrCodeUrl = await QRCode.toDataURL(uri);
34
34
35
- // We don't save the secret yet, the client must verify it first
36
- // But we need to verify it in the POST request.
37
- // Stateless approach: Send secret to client, client sends it back with code?
38
- // Security risk? Kind of.
39
- // Better: Store in DB temporarily? Or just return it and let client send it back signed?
40
- // Simple approach for now: Return secret to client, client sends it back in POST to "enable".
41
- // The secret is sensitive but it's being sent to the authenticated user.
35
+ await (db as NodePgDatabase<typeof schema>)
36
+ .update(users)
37
+ .set({
38
+ twoFactorEnabled: false,
39
+ twoFactorSecret: secret,
40
+ })
41
+ .where(eq(users.id, user.userId));
42
42
43
43
return success({
44
44
enabled: false,
63
63
const db = getDatabase() as NodePgDatabase<typeof schema>;
64
64
65
65
if (action === "enable") {
66
- if (!token || !secret) return badRequest("Token and secret are required");
66
+ if (!token) return badRequest("Authentication code is required");
67
67
68
- // Verify the token against the provided secret
69
- const isValid = verify2FAToken(token, secret);
68
+ const currentUser = await db.query.users.findFirst({
69
+ where: eq(users.id, user.userId)
70
+ });
71
+ if (!currentUser) return unauthorized();
72
+
73
+ const effectiveSecret = currentUser.twoFactorSecret || secret;
74
+ if (!effectiveSecret) return badRequest("No pending 2FA setup found");
75
+
76
+ // Verify the token against server-side pending secret.
77
+ // `secret` from request is accepted only as a compatibility fallback.
78
+ const isValid = verify2FAToken(token, effectiveSecret);
70
79
if (!isValid) return badRequest("Invalid authentication code");
71
80
72
81
// Enable 2FA
73
82
await db.update(users)
74
83
.set({
75
84
twoFactorEnabled: true,
76
- twoFactorSecret: secret
85
+ twoFactorSecret: effectiveSecret
77
86
})
78
87
.where(eq(users.id, user.userId));
79
88
82
91
}
83
92
84
93
if (action === "disable") {
85
- // To disable, we should require a valid token (or password) for security
86
- // For now, requiring the current 2FA token
87
94
if (!token) return badRequest("Authentication code required to disable 2FA");
88
95
89
96
const currentUser = await db.query.users.findFirst({
90
97