1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

feature(set-change-password): [Auth/PM-17648] Create MasterPasswordApiService (#13552)

Creates a MasterPasswordApiService to house our API calls related to setting and changing a master password.
This commit is contained in:
rr-bw
2025-03-12 11:33:44 -07:00
committed by GitHub
parent 0356f4c1af
commit e268055dc1
18 changed files with 295 additions and 51 deletions

View File

@@ -21,6 +21,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
@@ -58,6 +59,7 @@ export class LoginCommand {
protected loginStrategyService: LoginStrategyServiceAbstraction,
protected authService: AuthService,
protected apiService: ApiService,
protected masterPasswordApiService: MasterPasswordApiService,
protected cryptoFunctionService: CryptoFunctionService,
protected environmentService: EnvironmentService,
protected passwordGenerationService: PasswordGenerationServiceAbstraction,
@@ -454,7 +456,7 @@ export class LoginCommand {
request.newMasterPasswordHash = newPasswordHash;
request.key = newUserKey[1].encryptedString;
await this.apiService.postPassword(request);
await this.masterPasswordApiService.postPassword(request);
return await this.handleUpdatePasswordSuccessResponse();
} catch (e) {
@@ -491,7 +493,7 @@ export class LoginCommand {
request.newMasterPasswordHash = newPasswordHash;
request.masterPasswordHint = hint;
await this.apiService.putUpdateTempPassword(request);
await this.masterPasswordApiService.putUpdateTempPassword(request);
return await this.handleUpdatePasswordSuccessResponse();
} catch (e) {

View File

@@ -155,6 +155,7 @@ export class Program extends BaseProgram {
this.serviceContainer.loginStrategyService,
this.serviceContainer.authService,
this.serviceContainer.apiService,
this.serviceContainer.masterPasswordApiService,
this.serviceContainer.cryptoFunctionService,
this.serviceContainer.environmentService,
this.serviceContainer.passwordGenerationService,

View File

@@ -36,6 +36,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { MasterPasswordApiService as MasterPasswordApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import {
AccountServiceImplementation,
@@ -46,6 +47,7 @@ import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/services/master-password/master-password-api.service.implementation";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { TokenService } from "@bitwarden/common/auth/services/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
@@ -280,6 +282,7 @@ export class ServiceContainer {
sdkLoadService: SdkLoadService;
cipherAuthorizationService: CipherAuthorizationService;
ssoUrlService: SsoUrlService;
masterPasswordApiService: MasterPasswordApiServiceAbstraction;
constructor() {
let p = null;
@@ -843,6 +846,8 @@ export class ServiceContainer {
this.organizationService,
this.accountService,
);
this.masterPasswordApiService = new MasterPasswordApiService(this.apiService, this.logService);
}
async logout() {

View File

@@ -46,6 +46,7 @@ import {
AuthService,
AuthService as AuthServiceAbstraction,
} from "@bitwarden/common/auth/abstractions/auth.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
@@ -367,6 +368,7 @@ const safeProviders: SafeProvider[] = [
useClass: DesktopSetPasswordJitService,
deps: [
ApiService,
MasterPasswordApiService,
KeyService,
EncryptService,
I18nServiceAbstraction,

View File

@@ -9,6 +9,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
@@ -40,6 +41,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
policyApiService: PolicyApiServiceAbstraction,
policyService: PolicyService,
router: Router,
masterPasswordApiService: MasterPasswordApiService,
syncService: SyncService,
route: ActivatedRoute,
private broadcasterService: BroadcasterService,
@@ -63,6 +65,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
policyApiService,
policyService,
router,
masterPasswordApiService,
apiService,
syncService,
route,

View File

@@ -5,10 +5,10 @@ import { Router } from "@angular/router";
import { firstValueFrom, map } from "rxjs";
import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
@@ -50,7 +50,7 @@ export class ChangePasswordComponent
private auditService: AuditService,
private cipherService: CipherService,
private syncService: SyncService,
private apiService: ApiService,
private masterPasswordApiService: MasterPasswordApiService,
private router: Router,
dialogService: DialogService,
private userVerificationService: UserVerificationService,
@@ -213,14 +213,14 @@ export class ChangePasswordComponent
try {
if (this.rotateUserKey) {
this.formPromise = this.apiService.postPassword(request).then(async () => {
this.formPromise = this.masterPasswordApiService.postPassword(request).then(async () => {
// we need to save this for local masterkey verification during rotation
await this.masterPasswordService.setMasterKeyHash(newLocalKeyHash, userId as UserId);
await this.masterPasswordService.setMasterKey(newMasterKey, userId as UserId);
return this.updateKey();
});
} else {
this.formPromise = this.apiService.postPassword(request);
this.formPromise = this.masterPasswordApiService.postPassword(request);
}
await this.formPromise;

View File

@@ -50,6 +50,7 @@ import {
import { AccountApiService as AccountApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/account-api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ClientType } from "@bitwarden/common/enums";
@@ -279,6 +280,7 @@ const safeProviders: SafeProvider[] = [
useClass: WebSetPasswordJitService,
deps: [
ApiService,
MasterPasswordApiService,
KeyServiceAbstraction,
EncryptService,
I18nServiceAbstraction,

View File

@@ -17,6 +17,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { OrganizationAutoEnrollStatusResponse } from "@bitwarden/common/admin-console/models/response/organization-auto-enroll-status.response";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
@@ -62,6 +63,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements
private policyApiService: PolicyApiServiceAbstraction,
policyService: PolicyService,
protected router: Router,
private masterPasswordApiService: MasterPasswordApiService,
private apiService: ApiService,
private syncService: SyncService,
private route: ActivatedRoute,
@@ -195,7 +197,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements
);
try {
if (this.resetPasswordAutoEnroll) {
this.formPromise = this.apiService
this.formPromise = this.masterPasswordApiService
.setPassword(request)
.then(async () => {
await this.onSetPasswordSuccess(masterKey, userKey, newKeyPair);
@@ -222,7 +224,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements
);
});
} else {
this.formPromise = this.apiService.setPassword(request).then(async () => {
this.formPromise = this.masterPasswordApiService.setPassword(request).then(async () => {
await this.onSetPasswordSuccess(masterKey, userKey, newKeyPair);
});
}

View File

@@ -3,10 +3,10 @@
import { Directive } from "@angular/core";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
@@ -40,7 +40,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
policyService: PolicyService,
keyService: KeyService,
messagingService: MessagingService,
private apiService: ApiService,
private masterPasswordApiService: MasterPasswordApiService,
private userVerificationService: UserVerificationService,
private logService: LogService,
dialogService: DialogService,
@@ -117,9 +117,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
request.key = newUserKey[1].encryptedString;
// Update user's password
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.apiService.postPassword(request);
await this.masterPasswordApiService.postPassword(request);
this.toastService.showToast({
variant: "success",

View File

@@ -4,10 +4,10 @@ import { Directive, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { firstValueFrom, map } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
@@ -52,7 +52,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent imp
policyService: PolicyService,
keyService: KeyService,
messagingService: MessagingService,
private apiService: ApiService,
private masterPasswordApiService: MasterPasswordApiService,
private syncService: SyncService,
private logService: LogService,
private userVerificationService: UserVerificationService,
@@ -202,7 +202,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent imp
request.newMasterPasswordHash = masterPasswordHash;
request.masterPasswordHint = this.hint;
return this.apiService.putUpdateTempPassword(request);
return this.masterPasswordApiService.putUpdateTempPassword(request);
}
private async updatePassword(newMasterPasswordHash: string, userKey: [UserKey, EncString]) {
@@ -214,7 +214,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent imp
request.newMasterPasswordHash = newMasterPasswordHash;
request.key = userKey[1].encryptedString;
return this.apiService.postPassword(request);
return this.masterPasswordApiService.postPassword(request);
}
private async updateTdeOffboardingPassword(
@@ -226,6 +226,6 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent imp
request.newMasterPasswordHash = masterPasswordHash;
request.masterPasswordHint = this.hint;
return this.apiService.putUpdateTdeOffboardingPassword(request);
return this.masterPasswordApiService.putUpdateTdeOffboardingPassword(request);
}
}

View File

@@ -91,6 +91,7 @@ import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractio
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { MasterPasswordApiService as MasterPasswordApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import {
InternalMasterPasswordServiceAbstraction,
MasterPasswordServiceAbstraction,
@@ -113,6 +114,7 @@ import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/services/master-password/master-password-api.service.implementation";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { PasswordResetEnrollmentServiceImplementation } from "@bitwarden/common/auth/services/password-reset-enrollment.service.implementation";
import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service";
@@ -1350,6 +1352,7 @@ const safeProviders: SafeProvider[] = [
useClass: DefaultSetPasswordJitService,
deps: [
ApiServiceAbstraction,
MasterPasswordApiService,
KeyService,
EncryptService,
I18nServiceAbstraction,
@@ -1482,6 +1485,11 @@ const safeProviders: SafeProvider[] = [
ToastService,
],
}),
safeProvider({
provide: MasterPasswordApiServiceAbstraction,
useClass: MasterPasswordApiService,
deps: [ApiServiceAbstraction, LogService],
}),
];
@NgModule({

View File

@@ -9,6 +9,7 @@ import {
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationKeysResponse } from "@bitwarden/common/admin-console/models/response/organization-keys.response";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SetPasswordRequest } from "@bitwarden/common/auth/models/request/set-password.request";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
@@ -31,6 +32,7 @@ describe("DefaultSetPasswordJitService", () => {
let sut: DefaultSetPasswordJitService;
let apiService: MockProxy<ApiService>;
let masterPasswordApiService: MockProxy<MasterPasswordApiService>;
let keyService: MockProxy<KeyService>;
let encryptService: MockProxy<EncryptService>;
let i18nService: MockProxy<I18nService>;
@@ -42,6 +44,7 @@ describe("DefaultSetPasswordJitService", () => {
beforeEach(() => {
apiService = mock<ApiService>();
masterPasswordApiService = mock<MasterPasswordApiService>();
keyService = mock<KeyService>();
encryptService = mock<EncryptService>();
i18nService = mock<I18nService>();
@@ -53,6 +56,7 @@ describe("DefaultSetPasswordJitService", () => {
sut = new DefaultSetPasswordJitService(
apiService,
masterPasswordApiService,
keyService,
encryptService,
i18nService,
@@ -148,7 +152,7 @@ describe("DefaultSetPasswordJitService", () => {
keyService.makeKeyPair.mockResolvedValue(keyPair);
apiService.setPassword.mockResolvedValue(undefined);
masterPasswordApiService.setPassword.mockResolvedValue(undefined);
masterPasswordService.setForceSetPasswordReason.mockResolvedValue(undefined);
userDecryptionOptionsSubject.next(new UserDecryptionOptions({ hasMasterPassword: true }));
@@ -185,7 +189,7 @@ describe("DefaultSetPasswordJitService", () => {
await sut.setPassword(credentials);
// Assert
expect(apiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
});
it("should set password successfully (given no user key)", async () => {
@@ -196,7 +200,7 @@ describe("DefaultSetPasswordJitService", () => {
await sut.setPassword(credentials);
// Assert
expect(apiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
});
it("should handle reset password auto enroll", async () => {
@@ -210,7 +214,7 @@ describe("DefaultSetPasswordJitService", () => {
await sut.setPassword(credentials);
// Assert
expect(apiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
expect(organizationApiService.getKeys).toHaveBeenCalledWith(orgId);
expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(userKey.key, orgPublicKey);
expect(

View File

@@ -9,6 +9,7 @@ import {
import { InternalUserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { SetPasswordRequest } from "@bitwarden/common/auth/models/request/set-password.request";
@@ -29,6 +30,7 @@ import {
export class DefaultSetPasswordJitService implements SetPasswordJitService {
constructor(
protected apiService: ApiService,
protected masterPasswordApiService: MasterPasswordApiService,
protected keyService: KeyService,
protected encryptService: EncryptService,
protected i18nService: I18nService,
@@ -77,7 +79,7 @@ export class DefaultSetPasswordJitService implements SetPasswordJitService {
kdfConfig.iterations,
);
await this.apiService.setPassword(request);
await this.masterPasswordApiService.setPassword(request);
// Clear force set password reason to allow navigation back to vault.
await this.masterPasswordService.setForceSetPasswordReason(ForceSetPasswordReason.None, userId);

View File

@@ -49,17 +49,13 @@ import { UserApiTokenRequest } from "../auth/models/request/identity-token/user-
import { WebAuthnLoginTokenRequest } from "../auth/models/request/identity-token/webauthn-login-token.request";
import { KeyConnectorUserKeyRequest } from "../auth/models/request/key-connector-user-key.request";
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
import { PasswordRequest } from "../auth/models/request/password.request";
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
import { SetKeyConnectorKeyRequest } from "../auth/models/request/set-key-connector-key.request";
import { SetPasswordRequest } from "../auth/models/request/set-password.request";
import { TwoFactorEmailRequest } from "../auth/models/request/two-factor-email.request";
import { TwoFactorProviderRequest } from "../auth/models/request/two-factor-provider.request";
import { TwoFactorRecoveryRequest } from "../auth/models/request/two-factor-recovery.request";
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
import { UpdateTdeOffboardingPasswordRequest } from "../auth/models/request/update-tde-offboarding-password.request";
import { UpdateTempPasswordRequest } from "../auth/models/request/update-temp-password.request";
import { UpdateTwoFactorAuthenticatorRequest } from "../auth/models/request/update-two-factor-authenticator.request";
import { UpdateTwoFactorDuoRequest } from "../auth/models/request/update-two-factor-duo.request";
import { UpdateTwoFactorEmailRequest } from "../auth/models/request/update-two-factor-email.request";
@@ -169,8 +165,6 @@ export abstract class ApiService {
postPrelogin: (request: PreloginRequest) => Promise<PreloginResponse>;
postEmailToken: (request: EmailTokenRequest) => Promise<any>;
postEmail: (request: EmailRequest) => Promise<any>;
postPassword: (request: PasswordRequest) => Promise<any>;
setPassword: (request: SetPasswordRequest) => Promise<any>;
postSetKeyConnectorKey: (request: SetKeyConnectorKeyRequest) => Promise<any>;
postSecurityStamp: (request: SecretVerificationRequest) => Promise<any>;
getAccountRevisionDate: () => Promise<number>;
@@ -189,8 +183,6 @@ export abstract class ApiService {
postAccountKdf: (request: KdfRequest) => Promise<any>;
postUserApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
postUserRotateApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise<any>;
putUpdateTdeOffboardingPassword: (request: UpdateTdeOffboardingPasswordRequest) => Promise<any>;
postConvertToKeyConnector: () => Promise<void>;
//passwordless
postAuthRequest: (request: AuthRequest) => Promise<AuthRequestResponse>;

View File

@@ -0,0 +1,28 @@
import { PasswordRequest } from "../models/request/password.request";
import { SetPasswordRequest } from "../models/request/set-password.request";
import { UpdateTdeOffboardingPasswordRequest } from "../models/request/update-tde-offboarding-password.request";
import { UpdateTempPasswordRequest } from "../models/request/update-temp-password.request";
export abstract class MasterPasswordApiService {
/**
* POSTs a SetPasswordRequest to "/accounts/set-password"
*/
abstract setPassword: (request: SetPasswordRequest) => Promise<any>;
/**
* POSTs a PasswordRequest to "/accounts/password"
*/
abstract postPassword: (request: PasswordRequest) => Promise<any>;
/**
* PUTs an UpdateTempPasswordRequest to "/accounts/update-temp-password"
*/
abstract putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise<any>;
/**
* PUTs an UpdateTdeOffboardingPasswordRequest to "/accounts/update-tde-offboarding-password"
*/
abstract putUpdateTdeOffboardingPassword: (
request: UpdateTdeOffboardingPasswordRequest,
) => Promise<any>;
}

View File

@@ -0,0 +1,85 @@
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MasterPasswordApiService as MasterPasswordApiServiceAbstraction } from "../../abstractions/master-password-api.service.abstraction";
import { PasswordRequest } from "../../models/request/password.request";
import { SetPasswordRequest } from "../../models/request/set-password.request";
import { UpdateTdeOffboardingPasswordRequest } from "../../models/request/update-tde-offboarding-password.request";
import { UpdateTempPasswordRequest } from "../../models/request/update-temp-password.request";
export class MasterPasswordApiService implements MasterPasswordApiServiceAbstraction {
constructor(
private apiService: ApiService,
private logService: LogService,
) {}
async setPassword(request: SetPasswordRequest): Promise<any> {
try {
const response = await this.apiService.send(
"POST",
"/accounts/set-password",
request,
true,
false,
);
return response;
} catch (e: unknown) {
this.logService.error(e);
throw e;
}
}
async postPassword(request: PasswordRequest): Promise<any> {
try {
const response = await this.apiService.send(
"POST",
"/accounts/password",
request,
true,
false,
);
return response;
} catch (e: unknown) {
this.logService.error(e);
throw e;
}
}
async putUpdateTempPassword(request: UpdateTempPasswordRequest): Promise<any> {
try {
const response = await this.apiService.send(
"PUT",
"/accounts/update-temp-password",
request,
true,
false,
);
return response;
} catch (e: unknown) {
this.logService.error(e);
throw e;
}
}
async putUpdateTdeOffboardingPassword(
request: UpdateTdeOffboardingPasswordRequest,
): Promise<any> {
try {
const response = await this.apiService.send(
"PUT",
"/accounts/update-tde-offboarding-password",
request,
true,
false,
);
return response;
} catch (e: unknown) {
this.logService.error(e);
throw e;
}
}
}

View File

@@ -0,0 +1,130 @@
import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { KdfType } from "@bitwarden/key-management";
import { PasswordRequest } from "../../models/request/password.request";
import { SetPasswordRequest } from "../../models/request/set-password.request";
import { UpdateTdeOffboardingPasswordRequest } from "../../models/request/update-tde-offboarding-password.request";
import { UpdateTempPasswordRequest } from "../../models/request/update-temp-password.request";
import { MasterPasswordApiService } from "./master-password-api.service.implementation";
describe("MasterPasswordApiService", () => {
let apiService: MockProxy<ApiService>;
let logService: MockProxy<LogService>;
let sut: MasterPasswordApiService;
beforeEach(() => {
apiService = mock<ApiService>();
logService = mock<LogService>();
sut = new MasterPasswordApiService(apiService, logService);
});
it("should instantiate", () => {
expect(sut).not.toBeFalsy();
});
describe("setPassword", () => {
it("should call apiService.send with the correct parameters", async () => {
// Arrange
const request = new SetPasswordRequest(
"masterPasswordHash",
"key",
"masterPasswordHint",
"orgIdentifier",
{
publicKey: "publicKey",
encryptedPrivateKey: "encryptedPrivateKey",
},
KdfType.PBKDF2_SHA256,
600_000,
);
// Act
await sut.setPassword(request);
// Assert
expect(apiService.send).toHaveBeenCalledWith(
"POST",
"/accounts/set-password",
request,
true,
false,
);
});
});
describe("postPassword", () => {
it("should call apiService.send with the correct parameters", async () => {
// Arrange
const request = {
newMasterPasswordHash: "newMasterPasswordHash",
masterPasswordHint: "masterPasswordHint",
key: "key",
masterPasswordHash: "masterPasswordHash",
} as PasswordRequest;
// Act
await sut.postPassword(request);
// Assert
expect(apiService.send).toHaveBeenCalledWith(
"POST",
"/accounts/password",
request,
true,
false,
);
});
});
describe("putUpdateTempPassword", () => {
it("should call apiService.send with the correct parameters", async () => {
// Arrange
const request = {
masterPasswordHint: "masterPasswordHint",
newMasterPasswordHash: "newMasterPasswordHash",
key: "key",
} as UpdateTempPasswordRequest;
// Act
await sut.putUpdateTempPassword(request);
// Assert
expect(apiService.send).toHaveBeenCalledWith(
"PUT",
"/accounts/update-temp-password",
request,
true,
false,
);
});
});
describe("putUpdateTdeOffboardingPassword", () => {
it("should call apiService.send with the correct parameters", async () => {
// Arrange
const request = {
masterPasswordHint: "masterPasswordHint",
newMasterPasswordHash: "newMasterPasswordHash",
key: "key",
} as UpdateTdeOffboardingPasswordRequest;
// Act
await sut.putUpdateTdeOffboardingPassword(request);
// Assert
expect(apiService.send).toHaveBeenCalledWith(
"PUT",
"/accounts/update-tde-offboarding-password",
request,
true,
false,
);
});
});
});

View File

@@ -56,17 +56,13 @@ import { UserApiTokenRequest } from "../auth/models/request/identity-token/user-
import { WebAuthnLoginTokenRequest } from "../auth/models/request/identity-token/webauthn-login-token.request";
import { KeyConnectorUserKeyRequest } from "../auth/models/request/key-connector-user-key.request";
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
import { PasswordRequest } from "../auth/models/request/password.request";
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
import { SetKeyConnectorKeyRequest } from "../auth/models/request/set-key-connector-key.request";
import { SetPasswordRequest } from "../auth/models/request/set-password.request";
import { TwoFactorEmailRequest } from "../auth/models/request/two-factor-email.request";
import { TwoFactorProviderRequest } from "../auth/models/request/two-factor-provider.request";
import { TwoFactorRecoveryRequest } from "../auth/models/request/two-factor-recovery.request";
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
import { UpdateTdeOffboardingPasswordRequest } from "../auth/models/request/update-tde-offboarding-password.request";
import { UpdateTempPasswordRequest } from "../auth/models/request/update-temp-password.request";
import { UpdateTwoFactorAuthenticatorRequest } from "../auth/models/request/update-two-factor-authenticator.request";
import { UpdateTwoFactorDuoRequest } from "../auth/models/request/update-two-factor-duo.request";
import { UpdateTwoFactorEmailRequest } from "../auth/models/request/update-two-factor-email.request";
@@ -374,14 +370,6 @@ export class ApiService implements ApiServiceAbstraction {
return this.send("POST", "/accounts/email", request, true, false);
}
postPassword(request: PasswordRequest): Promise<any> {
return this.send("POST", "/accounts/password", request, true, false);
}
setPassword(request: SetPasswordRequest): Promise<any> {
return this.send("POST", "/accounts/set-password", request, true, false);
}
postSetKeyConnectorKey(request: SetKeyConnectorKeyRequest): Promise<any> {
return this.send("POST", "/accounts/set-key-connector-key", request, true, false);
}
@@ -479,14 +467,6 @@ export class ApiService implements ApiServiceAbstraction {
return new ApiKeyResponse(r);
}
putUpdateTempPassword(request: UpdateTempPasswordRequest): Promise<any> {
return this.send("PUT", "/accounts/update-temp-password", request, true, false);
}
putUpdateTdeOffboardingPassword(request: UpdateTdeOffboardingPasswordRequest): Promise<void> {
return this.send("PUT", "/accounts/update-tde-offboarding-password", request, true, false);
}
postConvertToKeyConnector(): Promise<void> {
return this.send("POST", "/accounts/convert-to-key-connector", null, true, false);
}