Skip to content

[PM-35393] MasterPasswordService auth integration#7575

Open
enmande wants to merge 16 commits intomainfrom
auth/pm-35393/master-password-service-auth-integration
Open

[PM-35393] MasterPasswordService auth integration#7575
enmande wants to merge 16 commits intomainfrom
auth/pm-35393/master-password-service-auth-integration

Conversation

@enmande
Copy link
Copy Markdown
Contributor

@enmande enmande commented May 1, 2026

🎟️ Tracking

PM-35393

📔 Objective

Integrate Auth-domain callers with MasterPasswordService.
Wires five password-mutation flows to the service added in #7530 :

  • Self-service password change
  • TDE offboarding
  • Emergency Access Takeover
  • Temporary password replacement
  • SSO JIT provisioning.

All relevant request models now accept both payload variants ("new": AuthenticationData + UnlockData, or "legacy": NewMasterPasswordHash + Key) for backward compatibility.
KDF validation is enforced at the request model layer whenever new payloads are present.
Legacy entry points on IUserService are marked [Obsolete] with specific replacement guidance. Legacy fields are tracked for removal in PM-33141.

📸 Screenshots

Master Password Self-Service

User enmande updates their Master Password using self-service.

  • Current Master Password is required and passes validation.
  • New Master Password is hashed and set.
  • User is logged out on success (behavioral parity with main).
  • User can log in with the new Master Password.
pm-35393__mp-self-service.mov

TDE Offboarding

  • User zed belongs to an SSO-required Trusted Device Encryption organization.
  • Organization Owner enmande converts the organization to Master Password Encryption. This is generally described as "TDE Offboarding."
  • User zed is required to set a new Master Password at next login; password is successfully set and allows zed to log in and view their vault.

NOTE: This organization retains SSO requirement throughout; zed remains authenticated to SSO for the duration of this test, so SSO challenge is not represented in this video.

pm-35393__tde-offboarding.mov

Emergency Access Takeover

  • User zed, who is enrolled in Emergency Access Takeover by organizational policy, has their account taken over ("Recovered") by organization Owner enmande.
  • enmande sets zed's new temporary Master Password.
  • New temporary Master Password is accepted at next login for zed's account.
  • Upon login, zed's account requires the setting of a new Master Password.
  • User is logged out on change of the Master Password.
  • New Master Password hash is set, and enabled subsequent login and access to the vault.
pm-35393__account-recovery.mov

@enmande enmande changed the title Auth/pm 35393/master password service auth integration [PM-35393] MasterPasswordService auth integration May 1, 2026
@enmande enmande added the ai-review Request a Claude code review label May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Bitwarden Claude Code Review

Overall Assessment: APPROVE

This PR integrates Auth-domain callers (self-service password change, admin temp-password replacement, emergency access takeover, TDE offboarding, SSO JIT, TDE set-password) with the MasterPasswordService introduced in foundation PR #7530. The 3-verb (Prepare / Save / Build) shape is consistently applied across new commands, legacy entry points are marked [Obsolete] with a clear PM-33141 sunset, and request models uniformly route via RequestHasNewDataTypes() + MasterPasswordPayloadVariantValidator. Critical safety invariants previously enforced inline in the commands (salt unchanged, user.HasMasterPassword == false, user.Key == null, !user.UsesKeyConnector) are preserved — they have moved into SetInitialPasswordData.ValidateDataForUser, which is invoked from MasterPasswordService.PrepareSetInitialMasterPasswordAsync. KDF settings/salt parity for the change-KDF flow is enforced by KdfSettingsValidator.ValidateAuthenticationAndUnlockData.

Code Review Details

No new blocking, important, or debt-level findings. Substantive concerns raised in the five existing review threads (test coverage for FinishRecoveryTakeoverAsync, validator placement under the Auth namespace, and removal of now-duplicative salt tests) already have author responses and corresponding fixes in this branch.

Minor observations (informational, not posted as inline comments to keep signal high):

  • MasterPasswordPayloadVariantValidator.ValidateExclusivity actually validates "at least one variant present," not exclusivity — both shapes may legitimately co-exist during the transition. The XML doc comment makes the intent clear, so this is a naming nuance only and will sunset with PM-33141.
  • AccountsController.PostKdf only dispatches the new payload shape, while ChangeKdfRequestModel still accepts either shape via the shared validator. This transitional gap is intentional and documented in the PR description.
  • SelfServicePasswordChangeCommand no longer emits the LogWarning on a bad current-password attempt that the legacy UserService.ChangePasswordAsync did. If telemetry on failed self-service password changes is still desired, consider adding it back; otherwise this is a non-issue since CheckPasswordAsync already handles failure tracking.

@enmande enmande marked this pull request as ready for review May 4, 2026 15:44
@enmande enmande requested a review from a team as a code owner May 4, 2026 15:44
@enmande enmande requested a review from ike-kottlowski May 4, 2026 15:44
@codecov
Copy link
Copy Markdown

codecov Bot commented May 4, 2026

Codecov Report

❌ Patch coverage is 64.77273% with 124 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.62%. Comparing base (5ae8570) to head (b2c9a70).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
src/Api/Auth/Controllers/AccountsController.cs 17.02% 38 Missing and 1 partial ⚠️
...fboardingPassword/TdeOffboardingPasswordCommand.cs 15.90% 35 Missing and 2 partials ⚠️
...Features/EmergencyAccess/EmergencyAccessService.cs 5.88% 32 Missing ⚠️
.../Api/Auth/Controllers/EmergencyAccessController.cs 0.00% 15 Missing ⚠️
...assword/ReplaceAdminSetTemporaryPasswordCommand.cs 96.29% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #7575    +/-   ##
========================================
  Coverage   59.62%   59.62%            
========================================
  Files        2097     2101     +4     
  Lines       92611    92914   +303     
  Branches     8249     8295    +46     
========================================
+ Hits        55215    55397   +182     
- Misses      35443    35562   +119     
- Partials     1953     1955     +2     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 73.12139% with 93 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.79%. Comparing base (f835212) to head (123bab3).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/Api/Auth/Controllers/AccountsController.cs 17.02% 38 Missing and 1 partial ⚠️
...fboardingPassword/TdeOffboardingPasswordCommand.cs 15.90% 35 Missing and 2 partials ⚠️
.../Api/Auth/Controllers/EmergencyAccessController.cs 0.00% 15 Missing ⚠️
...th/Models/Request/Accounts/PasswordRequestModel.cs 92.30% 0 Missing and 1 partial ⚠️
...assword/ReplaceAdminSetTemporaryPasswordCommand.cs 96.29% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7575      +/-   ##
==========================================
+ Coverage   59.73%   59.79%   +0.05%     
==========================================
  Files        2102     2107       +5     
  Lines       92691    93031     +340     
  Branches     8257     8304      +47     
==========================================
+ Hits        55371    55627     +256     
- Misses      35366    35442      +76     
- Partials     1954     1962       +8     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@ike-kottlowski ike-kottlowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some concerns around the removal of salt tests.

By removing them I think we are lessening our testing coverage for ensuring the salt remains unchanged. I know there maybe concerns about business logic locations and checking the salt in a JIT User Provision unit test suite may not be the correct palace for it but having it in the wrong place is better than not having it at all.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎨 : there are no CODEOWNERS for this directory. I think it's probably best if we move this to an Auth owned space.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 8ee4c6d. Good call.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ : Why were the salt related test removed? they should still pass with your changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent question 🔎
I think it just comes down to visibility within this PR.
We added a number of tests with the foundation PR that would support these cases when wired up, but move them to the new authorities. Most of those authorities now are the data models, for validation at the boundary. For example, this test and the one(s) above it should be covering this now where ValidateDataForUser is called -- synchronously in the set initial master password delegate.
We had both in play until this wire-up came in to preserve continuity; the connection here allows us to deprecate these tests (otherwise I believe they all are strictly duplicative).


[Theory]
[BitAutoData]
public async Task ChangePasswordAsync_PassesCorrectDataToMasterPasswordService(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎨 : this feels duplicative of the first success test. Can we just add the data assertion from this one to the success one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, refactored in 123bab3. One indexed on the service invocation, and the other on the side effects. Realistically, this should be a single collection of assertions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎨 : The salt tests are removed here as well. Can you speak to that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent question 🔎
I think it just comes down to visibility within this PR.
We added a number of tests with the foundation PR that would support these cases when wired up, but move them to the new authorities. Most of those authorities now are the data models, for validation at the boundary. For example, this test and the one(s) above it should be covering this now where ValidateDataForUser is called -- synchronously in the set initial master password delegate.
We had both in play until this wire-up came in to preserve continuity; the connection here allows us to deprecate these tests (otherwise I believe they all are strictly duplicative).

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

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.

2 participants