Skip to content

Auth/PM-3813 - 2FA Management Endpoints - User Verification Refactor#21385

Draft
JaredSnider-Bitwarden wants to merge 3 commits into
mainfrom
auth/pm-38137/2fa-verification-refactor
Draft

Auth/PM-3813 - 2FA Management Endpoints - User Verification Refactor#21385
JaredSnider-Bitwarden wants to merge 3 commits into
mainfrom
auth/pm-38137/2fa-verification-refactor

Conversation

@JaredSnider-Bitwarden

Copy link
Copy Markdown
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-38137

📔 Objective

TODO

📸 Screenshots

TODO

Mirror the server-side per-provider model rewrite on the client:

- Existing PUT/DELETE setup request models drop SecretVerificationRequest
  inheritance and become standalone with explicit userVerificationToken
  fields. two-factor-email.request keeps its inheritance because it also
  serves the login flow.
- New per-provider delete request models (YubiKey, Duo, Email,
  OrganizationDuo, WebAuthn delete-all) — token-only shape mirroring
  the server.
- Authenticator delete request file/class renamed from
  disable-two-factor-authenticator to delete-two-factor-authenticator
  to match server naming.
- New TwoFactorWebAuthnChallengeResponse wrapper around the FIDO2
  options + minted token (replaces the bare ChallengeResponse payload
  from get-webauthn-challenge).
- Response models for Duo, Email, WebAuthn, and YubiKey gain
  userVerificationToken.
- Obsolete two-factor-provider.request deleted (no remaining consumers
  after the disable-model rewrite).
Both TwoFactorApiService and TwoFactorService (abstractions and
implementations) pick up:

- New methods deleteTwoFactorYubiKey, deleteTwoFactorDuo,
  deleteTwoFactorEmail, deleteTwoFactorOrganizationDuo, and
  deleteTwoFactorWebAuthnAll routing to the corresponding per-provider
  DELETE endpoints.
- Removal of legacy putTwoFactorDisable and
  putTwoFactorOrganizationDisable (server endpoints are gone).
- Updated return type on getTwoFactorWebAuthnChallenge to the new
  TwoFactorWebAuthnChallengeResponse wrapper.

DefaultTwoFactorApiService spec: legacy put*Disable tests removed,
five new deleteTwoFactor* tests added, WebAuthn challenge test asserts
the new wrapper.
Per-provider setup components (Authenticator, YubiKey, Duo, Email,
WebAuthn) instantiate request models directly, cache the user
verification token from the GET response, and thread it through every
PUT / DELETE / setup-POST call. Each component implements its own
disableMethod against the appropriate per-provider DELETE endpoint:

- Authenticator, YubiKey, Email each call their corresponding
  deleteTwoFactor* method.
- Duo branches on organizationId between deleteTwoFactorDuo and
  deleteTwoFactorOrganizationDuo (the component is shared between
  personal Duo and OrgDuo setup).
- WebAuthn's "Disable All Keys" button calls
  deleteTwoFactorWebAuthnAll (single round-trip; server-side handles
  the wipe atomically). Per-credential remove continues to use
  deleteTwoFactorWebAuthn.
- WebAuthn challenge consumer reads options + userVerificationToken
  from the new wrapper response.

Base setup component disableMethod becomes protected abstract — every
subclass provides its own override. Parent settings page stops
rendering the lapsed-premium-only secondary "Disable" button; the
standard "Manage" button is now enabled for lapsed-premium users on
already-enrolled premium providers, so the same GET → DELETE flow
handles them.
@JaredSnider-Bitwarden JaredSnider-Bitwarden added the ai-review Request a Claude code review label Jun 19, 2026
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the 2FA management refactor that replaces the generic PUT /two-factor/disable endpoint with per-provider DELETE endpoints (authenticator, email, Duo, org Duo, YubiKey, WebAuthn-all) and threads a server-minted user-verification token through the setup/enable/disable flows. Verified that the removed TwoFactorProviderRequest, DisableTwoFactorAuthenticatorRequest, putTwoFactorDisable, and disablePremium2faTypeForNonPremiumUser have no remaining references, the abstract disableMethod() is implemented by every concrete provider component, and the new request/response models and API service tests are consistent with the routed verbs and paths. No security, correctness, or breaking-change issues met the confidence bar.

Code Review Details

No blocking findings.

One item worth confirming during QA (not posted inline — depends on the companion server change in PM-38137): this PR removes disablePremium2faTypeForNonPremiumUser, the workaround added in PM-21204 so a lapsed-premium user could still disable a previously-enabled Duo/YubiKey provider. Disabling now routes through manage()TwoFactorVerifyComponent, which calls the premium-gated getTwoFactorDuo / getTwoFactorYubiKey GETs. The updated API docs in this PR drop the premium requirement from those GETs, which implies the server no longer gates them — worth verifying a non-premium user can still reach the disable button for an enabled Duo/YubiKey provider.

@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 30.35714% with 78 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.19%. Comparing base (36805f6) to head (1c0100e).
⚠️ Report is 44 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../two-factor/two-factor-setup-webauthn.component.ts 0.00% 22 Missing ⚠️
...tings/two-factor/two-factor-setup-duo.component.ts 0.00% 18 Missing ⚠️
...ngs/two-factor/two-factor-setup-email.component.ts 0.00% 16 Missing ⚠️
...s/two-factor/two-factor-setup-yubikey.component.ts 0.00% 13 Missing ⚠️
.../two-factor/services/default-two-factor.service.ts 0.00% 5 Missing ⚠️
...factor/two-factor-setup-authenticator.component.ts 0.00% 3 Missing ⚠️
...esponse/two-factor-web-authn-challenge.response.ts 85.71% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21385      +/-   ##
==========================================
- Coverage   49.27%   49.19%   -0.08%     
==========================================
  Files        4056     4079      +23     
  Lines      127010   127859     +849     
  Branches    19371    19568     +197     
==========================================
+ Hits        62583    62905     +322     
- Misses      59803    60300     +497     
- Partials     4624     4654      +30     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant