fix(security): prevent TOTP replay attacks and fix user enumeration in verifyTotp

Adds lastTotpAt timestamp to User model. After a successful TOTP validation,
the timestamp is recorded. Any reuse of the same code within the 30-second
window is rejected as a replay attack.

verifyTotp now returns a single generic UNAUTHORIZED error regardless of
whether the user ID is invalid or TOTP is not enabled, preventing enumeration
of user IDs and MFA status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 21:41:09 +02:00
parent 1833182e90
commit afabaa0b7a
4 changed files with 64 additions and 13 deletions
+1
View File
@@ -187,6 +187,7 @@ model User {
lastActiveAt DateTime?
totpSecret String? // Base32 TOTP secret
totpEnabled Boolean @default(false)
lastTotpAt DateTime? // tracks last successful TOTP use to prevent replay
isActive Boolean @default(true)
deletedAt DateTime?