Skip to content

feat(auth): add opt-in TOTP two-factor authentication (Phase 1)#247

Merged
parth0025 merged 2 commits into
stagingfrom
feat/2fa-totp-phase1
Jun 17, 2026
Merged

feat(auth): add opt-in TOTP two-factor authentication (Phase 1)#247
parth0025 merged 2 commits into
stagingfrom
feat/2fa-totp-phase1

Conversation

@parth0025

Copy link
Copy Markdown
Collaborator

Phase 1 of S1-03: opt-in authenticator-app 2FA for password login. Strictly additive and non-breaking — with 2FA disabled (the default for every existing user) the login flow is unchanged. OAuth logins, sessions, and the JWT mechanism are untouched.

Backend

  • Deps: otplib (TOTP) + qrcode (enrollment QR).
  • New twoFactor field on the userAuth schema (Mixed object): TOTP secret AES-256-GCM encrypted at rest; recovery codes bcrypt-hashed and single-use.
  • Modules/Auth/helpers/twoFactorRules.js — pure, self-contained helpers (TOTP, recovery codes, AES, tempToken). 10 unit tests in tests/twofactor-rules.test.js.
  • Modules/Auth/controller/twoFactor.js — status / setup / verify / disable / validate.
  • loginSession.js — extracts finalizeSession (the existing session-issuance code, unchanged) and adds the 2FA gate. When twoFactorEnabled, login returns a short-lived tempToken (signed with a SEPARATE secret + twoFactorPending claim) instead of a session; the normal access-token middleware verifies against JWT_SECRET, so it can never accept the tempToken. /2fa/validate exchanges tempToken + code for a real session via the same finalizeSession.
  • Routes + middleware allow-list: setup/verify/disable require auth (JWT + companyId); validate is public and rate-limited like login (manageAttempt).
  • .env.example: optional TWO_FACTOR_ENC_KEY / TWO_FACTOR_TEMP_SECRET / TWO_FACTOR_ISSUER (derived from JWT_SECRET if unset).

Frontend

  • Login.vue — second-step code form (TOTP or recovery code) shown when the API returns twoFactorRequired, reusing the shared proceedAfterAuth post-login flow.
  • Settings → Two-Factor Authentication (new view + route + menu): enable (QR + manual key + confirm, then one-time recovery codes with copy/download) and disable.
  • Endpoint constants + i18n strings.

Out of scope (Phase 2)

Company-wide enforcement and extending the gate to OAuth logins.

Verification

  • 10/10 unit tests pass.
  • All touched .vue files compile via @vue/compiler-sfc; JS configs parse; backend module loads with all handlers.
  • Manually tested: enroll, login second-step, recovery-code single-use, disable, rate-limit.

🤖 Generated with Claude Code

Phase 1 of S1-03: opt-in authenticator-app 2FA for password login. Strictly additive and non-breaking - with 2FA disabled (the default for every existing user) the login flow is unchanged; OAuth, sessions and JWT are untouched.

Backend: otplib + qrcode; a twoFactor field on userAuth (TOTP secret AES-256-GCM encrypted at rest, bcrypt single-use recovery codes); pure helpers twoFactorRules.js with 10 unit tests; controller status/setup/verify/disable/validate; loginSession.js extracts finalizeSession and adds the 2FA gate (tempToken signed with a separate secret, validated only at /2fa/validate); routes + middleware allow-list; optional env vars in .env.example.

Frontend: Login.vue second-step (TOTP or recovery code) reusing the shared post-login flow; new Settings > Two-Factor Authentication view + route + menu for enroll/disable; endpoint constants + i18n.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1631c3e3-99b9-49f7-a379-f6023f118826

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/2fa-totp-phase1

Comment @coderabbitai help to get the list of available commands and usage tips.

33 user-facing cases: enrollment, recovery codes, login second-step, recovery-code single-use, disable, rate-limit/session, regression (non-2FA + OAuth + reset unchanged), and UI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@parth0025 parth0025 self-assigned this Jun 16, 2026
@parth0025 parth0025 merged commit 43761e7 into staging Jun 17, 2026
4 checks passed
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.

1 participant