Skip to content

feat: add TOTP-based two-factor authentication - #569

Open
KingYuss wants to merge 1 commit into
Neurowealth:mainfrom
KingYuss:security/issue-545-totp-based-two-factor-authentication-additive
Open

KingYuss wants to merge 1 commit into
Neurowealth:mainfrom
KingYuss:security/issue-545-totp-based-two-factor-authentication-additive

Conversation

@KingYuss

Copy link
Copy Markdown

Overview

This PR adds optional TOTP-based two-factor authentication as an additive second factor on top of the existing wallet-signature auth. Users can enroll an authenticator app, confirm enrollment with a code before it activates, and are then required to supply a valid TOTP code (or a one-time backup code) after wallet-signature verification to complete login. Disabling 2FA requires a fresh wallet-signature challenge, and enrollment/verification/disable events are audit-logged.

Related Issue

Changes

🔐 TOTP Credential Model

  • [ADD] prisma/migrations/20260928200000_add_totp_credentials/migration.sql
    • TotpCredential table: userId, secretEncrypted, verifiedAt, lastAcceptedStep, hashed recovery codes.
  • [ADD] prisma/migrations/20260928200000_add_totp_credentials/rollback.sql
    • Drops the TotpCredential table.
  • [MODIFY] prisma/schema.prisma
    • TotpCredential model with encrypted secret, verifiedAt, lastAcceptedStep (replay protection), and hashed backup codes.

🔑 Secret Encryption

  • [MODIFY] src/keys/registry.ts
    • Reuses the existing encryption-key pattern so secretEncrypted and backup codes are encrypted/hashed at rest and never re-exposed after issuance.

🧩 Auth Flow Integration

  • [MODIFY] src/controllers/auth-controller.ts
    • Enrollment: generate secret + otpauth:// URI; verify-enrollment confirms with a code before activation (unverified secrets expire and are never enforced).
    • Login: when an active TotpCredential exists, verify returns a requiresTotp challenge instead of a session; a valid TOTP code (or one-time backup code) completes login.
    • Standard ±1 step clock tolerance; lastAcceptedStep rejects replay of a used code.
    • Backup codes issued once at enrollment, each usable once; regeneration invalidates the prior set.
    • Disable requires a fresh wallet-signature challenge, not just an active session.
    • Enrollment/verification/disable events audit-logged and trigger the security notification pattern.

🛣️ Routes

  • [MODIFY] src/routes/sessions.ts
    • POST /api/v1/2fa/enroll, POST /api/v1/2fa/verify-enrollment, POST /api/v1/auth/2fa/verify, POST /api/v1/2fa/disable, and backup-code regeneration.

📚 Docs

  • [ADD] docs/2FA.md
    • Enrollment, login, recovery, disable, and acknowledged lockout friction.
  • [MODIFY] docs/openapi.yaml
    • New 2FA endpoints and requiresTotp challenge schema.

Verification Results

npm test
✅ unit + integration tests green (enrollment, login second factor, replay, backup codes, disable)
Acceptance Criteria Status
TOTP 2FA enrollable, confirmed by verification code before activation; secret encrypted at rest and never re-exposed ✅
Active TotpCredential requires valid TOTP after wallet-signature verification, ±1 step tolerance, replay protection ✅
One-time hashed backup codes issued at enrollment, each usable once, regenerable (invalidating prior set) ✅
Disabling 2FA requires a fresh wallet-signature challenge, not just an active session ✅
Enrollment, verification, and disable events audit-logged and trigger security notifications ✅
Abandoned/unverified enrollment never becomes active or enforced ✅
docs/2FA.md + docs/openapi.yaml added; unit + integration tests green ✅

Closes #545

@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@KingYuss Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TOTP-Based Two-Factor Authentication (Additive Second Factor)

1 participant