1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 05:13:29 +00:00

[PM-7604] Require target UserID for KdfConfigService (#14380)

* Require userId for KdfConfigService

* Update auth team callers

* Update tools team callers
This commit is contained in:
Thomas Avery
2025-04-29 17:25:27 -05:00
committed by GitHub
parent f39e37002b
commit d43e4757df
14 changed files with 171 additions and 142 deletions

View File

@@ -5,7 +5,7 @@ import * as http from "http";
import { OptionValues } from "commander";
import * as inquirer from "inquirer";
import Separator from "inquirer/lib/objects/separator";
import { firstValueFrom, map, switchMap } from "rxjs";
import { firstValueFrom, map } from "rxjs";
import {
LoginStrategyServiceAbstraction,
@@ -29,7 +29,6 @@ import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/ide
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
import { UpdateTempPasswordRequest } from "@bitwarden/common/auth/models/request/update-temp-password.request";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { ClientType } from "@bitwarden/common/enums";
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
@@ -40,6 +39,7 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { UserId } from "@bitwarden/common/types/guid";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
import { KdfConfigService, KeyService } from "@bitwarden/key-management";
@@ -367,9 +367,9 @@ export class LoginCommand {
clientSecret == null
) {
if (response.forcePasswordReset === ForceSetPasswordReason.AdminForcePasswordReset) {
return await this.updateTempPassword();
return await this.updateTempPassword(response.userId);
} else if (response.forcePasswordReset === ForceSetPasswordReason.WeakMasterPassword) {
return await this.updateWeakPassword(password);
return await this.updateWeakPassword(response.userId, password);
}
}
@@ -431,7 +431,7 @@ export class LoginCommand {
return Response.success(res);
}
private async updateWeakPassword(currentPassword: string) {
private async updateWeakPassword(userId: UserId, currentPassword: string) {
// If no interaction available, alert user to use web vault
if (!this.canInteract) {
await this.logoutCallback();
@@ -448,6 +448,7 @@ export class LoginCommand {
try {
const { newPasswordHash, newUserKey, hint } = await this.collectNewMasterPasswordDetails(
userId,
"Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now.",
);
@@ -469,7 +470,7 @@ export class LoginCommand {
}
}
private async updateTempPassword() {
private async updateTempPassword(userId: UserId) {
// If no interaction available, alert user to use web vault
if (!this.canInteract) {
await this.logoutCallback();
@@ -486,6 +487,7 @@ export class LoginCommand {
try {
const { newPasswordHash, newUserKey, hint } = await this.collectNewMasterPasswordDetails(
userId,
"An organization administrator recently changed your master password. In order to access the vault, you must update your master password now.",
);
@@ -510,10 +512,12 @@ export class LoginCommand {
* Collect new master password and hint from the CLI. The collected password
* is validated against any applicable master password policies, a new master
* key is generated, and we use it to re-encrypt the user key
* @param userId - User ID of the account
* @param prompt - Message that is displayed during the initial prompt
* @param error
*/
private async collectNewMasterPasswordDetails(
userId: UserId,
prompt: string,
error?: string,
): Promise<{
@@ -539,11 +543,12 @@ export class LoginCommand {
// Master Password Validation
if (masterPassword == null || masterPassword === "") {
return this.collectNewMasterPasswordDetails(prompt, "Master password is required.\n");
return this.collectNewMasterPasswordDetails(userId, prompt, "Master password is required.\n");
}
if (masterPassword.length < Utils.minimumPasswordLength) {
return this.collectNewMasterPasswordDetails(
userId,
prompt,
`Master password must be at least ${Utils.minimumPasswordLength} characters long.\n`,
);
@@ -556,10 +561,7 @@ export class LoginCommand {
);
const enforcedPolicyOptions = await firstValueFrom(
this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)),
),
this.policyService.masterPasswordPolicyOptions$(userId),
);
// Verify master password meets policy requirements
@@ -572,6 +574,7 @@ export class LoginCommand {
)
) {
return this.collectNewMasterPasswordDetails(
userId,
prompt,
"Your new master password does not meet the policy requirements.\n",
);
@@ -589,6 +592,7 @@ export class LoginCommand {
// Re-type Validation
if (masterPassword !== masterPasswordRetype) {
return this.collectNewMasterPasswordDetails(
userId,
prompt,
"Master password confirmation does not match.\n",
);
@@ -601,7 +605,7 @@ export class LoginCommand {
message: "Master Password Hint (optional):",
});
const masterPasswordHint = hint.input;
const kdfConfig = await this.kdfConfigService.getKdfConfig();
const kdfConfig = await this.kdfConfigService.getKdfConfig(userId);
// Create new key and hash new password
const newMasterKey = await this.keyService.makeMasterKey(

View File

@@ -310,13 +310,16 @@ export class ChangePasswordComponent
newMasterKey: MasterKey,
newUserKey: [UserKey, EncString],
) {
const masterKey = await this.keyService.makeMasterKey(
this.currentMasterPassword,
await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.email))),
await this.kdfConfigService.getKdfConfig(),
const [userId, email] = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => [a?.id, a?.email])),
);
const masterKey = await this.keyService.makeMasterKey(
this.currentMasterPassword,
email,
await this.kdfConfigService.getKdfConfig(userId),
);
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
const newLocalKeyHash = await this.keyService.hashMasterKey(
this.masterPassword,
newMasterKey,

View File

@@ -2,8 +2,10 @@
// @ts-strict-ignore
import { Component, OnDestroy, OnInit } from "@angular/core";
import { FormBuilder, FormControl, ValidatorFn, Validators } from "@angular/forms";
import { Subject, takeUntil } from "rxjs";
import { Subject, firstValueFrom, takeUntil } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { DialogService } from "@bitwarden/components";
import {
KdfConfigService,
@@ -43,6 +45,7 @@ export class ChangeKdfComponent implements OnInit, OnDestroy {
constructor(
private dialogService: DialogService,
private kdfConfigService: KdfConfigService,
private accountService: AccountService,
private formBuilder: FormBuilder,
) {
this.kdfOptions = [
@@ -52,7 +55,8 @@ export class ChangeKdfComponent implements OnInit, OnDestroy {
}
async ngOnInit() {
this.kdfConfig = await this.kdfConfigService.getKdfConfig();
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
this.kdfConfig = await this.kdfConfigService.getKdfConfig(userId);
this.formGroup.get("kdf").setValue(this.kdfConfig.kdfType);
this.setFormControlValues(this.kdfConfig);