mirror of
https://github.com/bitwarden/browser
synced 2026-01-31 08:43:54 +00:00
[PM-27086] Changing direction: remove new methods
This commit is contained in:
@@ -2,9 +2,7 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { DefaultSetInitialPasswordService } from "@bitwarden/angular/auth/password-management/set-initial-password/default-set-initial-password.service.implementation";
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordUserType,
|
||||
@@ -21,7 +19,6 @@ import { AccountCryptographicStateService } from "@bitwarden/common/key-manageme
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { MasterPasswordSalt } from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
@@ -185,57 +182,4 @@ describe("DesktopSetInitialPasswordService", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setInitialPassword()", () => {
|
||||
let credentials: SetInitialPasswordCredentials;
|
||||
let userType: SetInitialPasswordUserType;
|
||||
let userId: UserId;
|
||||
|
||||
beforeEach(() => {
|
||||
credentials = {
|
||||
newPassword: "newPassword",
|
||||
newPasswordHint: "newPasswordHint",
|
||||
kdfConfig: DEFAULT_KDF_CONFIG,
|
||||
salt: "salt" as MasterPasswordSalt,
|
||||
orgSsoIdentifier: "orgSsoIdentifier",
|
||||
orgId: "orgId",
|
||||
resetPasswordAutoEnroll: false,
|
||||
};
|
||||
userId = "userId" as UserId;
|
||||
userType = SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER;
|
||||
});
|
||||
|
||||
describe("given the initial password was successfully set", () => {
|
||||
it("should send a 'redrawMenu' message", async () => {
|
||||
// Arrange
|
||||
jest
|
||||
.spyOn(DefaultSetInitialPasswordService.prototype, "setInitialPassword")
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(messagingService.send).toHaveBeenCalledTimes(1);
|
||||
expect(messagingService.send).toHaveBeenCalledWith("redrawMenu");
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the initial password was NOT successfully set (due to parent method failure)", () => {
|
||||
it("should NOT send a 'redrawMenu' message", async () => {
|
||||
// Arrange
|
||||
const parentError = new Error("Parent setInitialPassword failed");
|
||||
jest
|
||||
.spyOn(DefaultSetInitialPasswordService.prototype, "setInitialPassword")
|
||||
.mockRejectedValue(parentError);
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(parentError);
|
||||
expect(messagingService.send).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { DefaultSetInitialPasswordService } from "@bitwarden/angular/auth/password-management/set-initial-password/default-set-initial-password.service.implementation";
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordUserType,
|
||||
@@ -63,14 +62,4 @@ export class DesktopSetInitialPasswordService
|
||||
|
||||
this.messagingService.send("redrawMenu");
|
||||
}
|
||||
|
||||
override async setInitialPassword(
|
||||
credentials: SetInitialPasswordCredentials,
|
||||
userType: SetInitialPasswordUserType,
|
||||
userId: UserId,
|
||||
) {
|
||||
await super.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
this.messagingService.send("redrawMenu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { DefaultSetInitialPasswordService } from "@bitwarden/angular/auth/password-management/set-initial-password/default-set-initial-password.service.implementation";
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordUserType,
|
||||
@@ -22,7 +20,6 @@ import { AccountCryptographicStateService } from "@bitwarden/common/key-manageme
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { MasterPasswordSalt } from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
@@ -214,58 +211,4 @@ describe("WebSetInitialPasswordService", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setInitialPassword()", () => {
|
||||
let credentials: SetInitialPasswordCredentials;
|
||||
let userType: SetInitialPasswordUserType;
|
||||
let userId: UserId;
|
||||
|
||||
beforeEach(() => {
|
||||
credentials = {
|
||||
newPassword: "newPassword",
|
||||
newPasswordHint: "newPasswordHint",
|
||||
kdfConfig: DEFAULT_KDF_CONFIG,
|
||||
salt: "salt" as MasterPasswordSalt,
|
||||
orgSsoIdentifier: "orgSsoIdentifier",
|
||||
orgId: "orgId",
|
||||
resetPasswordAutoEnroll: false,
|
||||
};
|
||||
userId = "userId" as UserId;
|
||||
userType = SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER;
|
||||
});
|
||||
|
||||
describe("given the initial password was successfully set", () => {
|
||||
it("should call additional state clearing methods", async () => {
|
||||
// Arrange
|
||||
jest
|
||||
.spyOn(DefaultSetInitialPasswordService.prototype, "setInitialPassword")
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(routerService.getAndClearLoginRedirectUrl).toHaveBeenCalledTimes(1);
|
||||
expect(organizationInviteService.clearOrganizationInvitation).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the initial password was NOT successfully set (due to parent method failure)", () => {
|
||||
it("should NOT call any further methods", async () => {
|
||||
// Arrange
|
||||
const parentError = new Error("Parent setInitialPassword failed");
|
||||
jest
|
||||
.spyOn(DefaultSetInitialPasswordService.prototype, "setInitialPassword")
|
||||
.mockRejectedValue(parentError);
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(parentError);
|
||||
expect(routerService.getAndClearLoginRedirectUrl).not.toHaveBeenCalled();
|
||||
expect(organizationInviteService.clearOrganizationInvitation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { DefaultSetInitialPasswordService } from "@bitwarden/angular/auth/password-management/set-initial-password/default-set-initial-password.service.implementation";
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordUserType,
|
||||
@@ -87,36 +86,4 @@ export class WebSetInitialPasswordService
|
||||
await this.routerService.getAndClearLoginRedirectUrl();
|
||||
await this.organizationInviteService.clearOrganizationInvitation();
|
||||
}
|
||||
|
||||
override async setInitialPassword(
|
||||
credentials: SetInitialPasswordCredentials,
|
||||
userType: SetInitialPasswordUserType,
|
||||
userId: UserId,
|
||||
) {
|
||||
await super.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
/**
|
||||
* TODO: Investigate refactoring the following logic in https://bitwarden.atlassian.net/browse/PM-22615
|
||||
* ---
|
||||
* When a user has been invited to an org, they can be accepted into the org in two different ways:
|
||||
*
|
||||
* 1) By clicking the email invite link, which triggers the normal AcceptOrganizationComponent flow
|
||||
* a. This flow sets an org invite in state
|
||||
* b. However, if the user does not already have an account AND the org has SSO enabled AND the require
|
||||
* SSO policy enabled, the AcceptOrganizationComponent will send the user to /sso to accelerate
|
||||
* the user through the SSO JIT provisioning process (see #2 below)
|
||||
*
|
||||
* 2) By logging in via SSO, which triggers the JIT provisioning process
|
||||
* a. This flow does NOT (itself) set an org invite in state
|
||||
* b. The set initial password process on the server accepts the user into the org after successfully
|
||||
* setting the password (see server - SetInitialMasterPasswordCommand.cs)
|
||||
*
|
||||
* If a user clicks the email link but gets accelerated through the SSO JIT process (see 1b),
|
||||
* the SSO JIT process will accept the user into the org upon setting their initial password (see 2b),
|
||||
* at which point we must remember to clear the deep linked URL used for accepting the org invite, as well
|
||||
* as clear the org invite itself that was originally set in state by the AcceptOrganizationComponent.
|
||||
*/
|
||||
await this.routerService.getAndClearLoginRedirectUrl();
|
||||
await this.organizationInviteService.clearOrganizationInvitation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,27 +19,19 @@ import { AccountCryptographicStateService } from "@bitwarden/common/key-manageme
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import {
|
||||
MasterPasswordSalt,
|
||||
MasterPasswordAuthenticationData,
|
||||
MasterPasswordAuthenticationHash,
|
||||
MasterPasswordUnlockData,
|
||||
} from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { MasterPasswordSalt } from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||
import { KdfConfigService, KeyService, KdfConfig } from "@bitwarden/key-management";
|
||||
import { PureCrypto } from "@bitwarden/sdk-internal";
|
||||
|
||||
import {
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordUserType,
|
||||
SetInitialPasswordTdeOffboardingCredentials,
|
||||
SetInitialPasswordCredentials,
|
||||
} from "./set-initial-password.service.abstraction";
|
||||
|
||||
export class DefaultSetInitialPasswordService implements SetInitialPasswordService {
|
||||
@@ -210,144 +202,6 @@ export class DefaultSetInitialPasswordService implements SetInitialPasswordServi
|
||||
}
|
||||
}
|
||||
|
||||
async setInitialPassword(
|
||||
credentials: SetInitialPasswordCredentials,
|
||||
userType: SetInitialPasswordUserType,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
const {
|
||||
newPassword,
|
||||
newPasswordHint,
|
||||
kdfConfig,
|
||||
salt,
|
||||
orgSsoIdentifier,
|
||||
orgId,
|
||||
resetPasswordAutoEnroll,
|
||||
} = credentials;
|
||||
|
||||
for (const [key, value] of Object.entries(credentials)) {
|
||||
if (value == null) {
|
||||
throw new Error(`${key} not found. Could not set password.`);
|
||||
}
|
||||
}
|
||||
if (userId == null) {
|
||||
throw new Error("userId not found. Could not set password.");
|
||||
}
|
||||
if (userType == null) {
|
||||
throw new Error("userType not found. Could not set password.");
|
||||
}
|
||||
|
||||
let userKey: UserKey = await firstValueFrom(this.keyService.userKey$(userId));
|
||||
|
||||
if (userKey == null) {
|
||||
userKey = new SymmetricCryptoKey(PureCrypto.make_user_key_aes256_cbc_hmac()) as UserKey;
|
||||
}
|
||||
|
||||
const authenticationData: MasterPasswordAuthenticationData =
|
||||
await this.masterPasswordService.makeMasterPasswordAuthenticationData(
|
||||
newPassword,
|
||||
kdfConfig,
|
||||
salt,
|
||||
);
|
||||
|
||||
const unlockData: MasterPasswordUnlockData =
|
||||
await this.masterPasswordService.makeMasterPasswordUnlockData(
|
||||
newPassword,
|
||||
kdfConfig,
|
||||
salt,
|
||||
userKey,
|
||||
);
|
||||
|
||||
let keyPair: [string, EncString] | null = null;
|
||||
let keysRequest: KeysRequest | null = null;
|
||||
|
||||
if (userType === SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER) {
|
||||
/**
|
||||
* A user being JIT provisioned into a MP encryption org does not yet have a user
|
||||
* asymmetric key pair, so we create it for them here.
|
||||
*
|
||||
* Sidenote:
|
||||
* In the case of a TDE user whose permissions require that they have a MP - that user
|
||||
* will already have a user asymmetric key pair by this point, so we skip this if-block
|
||||
* so that we don't create a new key pair for them.
|
||||
*/
|
||||
|
||||
// Extra safety check (see description on https://github.com/bitwarden/clients/pull/10180):
|
||||
// In case we have have a local private key and are not sure whether it has been posted to the server,
|
||||
// we post the local private key instead of generating a new one
|
||||
const existingUserPrivateKey = (await firstValueFrom(
|
||||
this.keyService.userPrivateKey$(userId),
|
||||
)) as Uint8Array;
|
||||
|
||||
const existingUserPublicKey = await firstValueFrom(this.keyService.userPublicKey$(userId));
|
||||
|
||||
if (existingUserPrivateKey != null && existingUserPublicKey != null) {
|
||||
const existingUserPublicKeyB64 = Utils.fromBufferToB64(existingUserPublicKey);
|
||||
|
||||
// Existing key pair
|
||||
keyPair = [
|
||||
existingUserPublicKeyB64,
|
||||
await this.encryptService.wrapDecapsulationKey(existingUserPrivateKey, userKey),
|
||||
];
|
||||
} else {
|
||||
// New key pair
|
||||
keyPair = await this.keyService.makeKeyPair(userKey);
|
||||
}
|
||||
|
||||
if (keyPair == null) {
|
||||
throw new Error("keyPair not found. Could not set password.");
|
||||
}
|
||||
if (!keyPair[1].encryptedString) {
|
||||
throw new Error("encrypted private key not found. Could not set password.");
|
||||
}
|
||||
|
||||
keysRequest = new KeysRequest(keyPair[0], keyPair[1].encryptedString);
|
||||
}
|
||||
|
||||
const request = SetPasswordRequest.newConstructor(
|
||||
authenticationData,
|
||||
unlockData,
|
||||
newPasswordHint,
|
||||
orgSsoIdentifier,
|
||||
keysRequest,
|
||||
);
|
||||
|
||||
await this.masterPasswordApiService.setPassword(request);
|
||||
|
||||
// Clear force set password reason to allow navigation back to vault.
|
||||
await this.masterPasswordService.setForceSetPasswordReason(ForceSetPasswordReason.None, userId);
|
||||
|
||||
// User now has a password so update account decryption options in state
|
||||
await this.updateAccountDecryptionProperties(unlockData, userKey, userId);
|
||||
|
||||
/**
|
||||
* Set the private key only for new JIT provisioned users in MP encryption orgs.
|
||||
* (Existing TDE users will have their private key set on sync or on login.)
|
||||
*/
|
||||
if (keyPair != null && userType === SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER) {
|
||||
if (!keyPair[1].encryptedString) {
|
||||
throw new Error("encrypted private key not found. Could not set private key in state.");
|
||||
}
|
||||
await this.keyService.setPrivateKey(keyPair[1].encryptedString, userId);
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
{
|
||||
V1: {
|
||||
private_key: keyPair[1].encryptedString,
|
||||
},
|
||||
},
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
if (resetPasswordAutoEnroll) {
|
||||
await this.handleResetPasswordAutoEnroll(
|
||||
authenticationData.masterPasswordAuthenticationHash,
|
||||
orgId,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated To be removed in PM-28143
|
||||
*/
|
||||
@@ -399,25 +253,6 @@ export class DefaultSetInitialPasswordService implements SetInitialPasswordServi
|
||||
await this.keyService.setUserKey(masterKeyEncryptedUserKey[0], userId);
|
||||
}
|
||||
|
||||
private async updateAccountDecryptionProperties(
|
||||
unlockData: MasterPasswordUnlockData,
|
||||
userKey: UserKey,
|
||||
userId: UserId,
|
||||
) {
|
||||
const userDecryptionOpts = await firstValueFrom(
|
||||
this.userDecryptionOptionsService.userDecryptionOptionsById$(userId),
|
||||
);
|
||||
userDecryptionOpts.hasMasterPassword = true;
|
||||
|
||||
await this.userDecryptionOptionsService.setUserDecryptionOptionsById(
|
||||
userId,
|
||||
userDecryptionOpts,
|
||||
);
|
||||
await this.masterPasswordService.setMasterPasswordUnlockData(unlockData, userId);
|
||||
await this.kdfConfigService.setKdfConfig(userId, unlockData.kdf);
|
||||
await this.keyService.setUserKey(userKey, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated To be removed in PM-28143
|
||||
*
|
||||
@@ -445,7 +280,7 @@ export class DefaultSetInitialPasswordService implements SetInitialPasswordServi
|
||||
}
|
||||
|
||||
private async handleResetPasswordAutoEnroll(
|
||||
masterKeyHash: MasterPasswordAuthenticationHash | string, // In PM-28143, remove `| string`; should only accept MasterPasswordAuthenticationHash.
|
||||
masterKeyHash: string,
|
||||
orgId: string,
|
||||
userId: UserId,
|
||||
) {
|
||||
|
||||
@@ -27,13 +27,6 @@ import {
|
||||
EncString,
|
||||
} from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import {
|
||||
MasterKeyWrappedUserKey,
|
||||
MasterPasswordAuthenticationData,
|
||||
MasterPasswordAuthenticationHash,
|
||||
MasterPasswordSalt,
|
||||
MasterPasswordUnlockData,
|
||||
} from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -42,11 +35,9 @@ import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { MasterKey, UserKey, UserPrivateKey, UserPublicKey } from "@bitwarden/common/types/key";
|
||||
import { DEFAULT_KDF_CONFIG, KdfConfigService, KeyService } from "@bitwarden/key-management";
|
||||
import { PureCrypto } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { DefaultSetInitialPasswordService } from "./default-set-initial-password.service.implementation";
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordTdeOffboardingCredentials,
|
||||
@@ -737,585 +728,6 @@ describe("DefaultSetInitialPasswordService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("setInitialPassword()", () => {
|
||||
// Mock function parameters
|
||||
let credentials: SetInitialPasswordCredentials;
|
||||
let userType: SetInitialPasswordUserType;
|
||||
|
||||
// Mock other function data
|
||||
let authenticationData: MasterPasswordAuthenticationData;
|
||||
let unlockData: MasterPasswordUnlockData;
|
||||
|
||||
let existingUserPublicKey: UserPublicKey;
|
||||
let existingUserPrivateKey: UserPrivateKey;
|
||||
let userKeyEncryptedPrivateKey: EncString;
|
||||
|
||||
let keyPair: [string, EncString];
|
||||
let keysRequest: KeysRequest;
|
||||
|
||||
let organizationKeys: OrganizationKeysResponse;
|
||||
let orgPublicKeyEncryptedUserKey: EncString;
|
||||
|
||||
let userDecryptionOptions: UserDecryptionOptions;
|
||||
let userDecryptionOptionsSubject: BehaviorSubject<UserDecryptionOptions>;
|
||||
let setPasswordRequest: SetPasswordRequest;
|
||||
|
||||
let enrollmentRequest: OrganizationUserResetPasswordEnrollmentRequest;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Mock function arguments
|
||||
credentials = {
|
||||
newPassword: "newPassword123!",
|
||||
newPasswordHint: "newPasswordHint",
|
||||
kdfConfig: DEFAULT_KDF_CONFIG,
|
||||
salt: "user@example.com" as MasterPasswordSalt,
|
||||
orgSsoIdentifier: "orgSsoIdentifier",
|
||||
orgId: "orgId",
|
||||
resetPasswordAutoEnroll: false,
|
||||
};
|
||||
userType = SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER;
|
||||
|
||||
// Mock other function data
|
||||
authenticationData = {
|
||||
salt: credentials.salt,
|
||||
kdf: credentials.kdfConfig,
|
||||
masterPasswordAuthenticationHash:
|
||||
"masterPasswordAuthenticationHash" as MasterPasswordAuthenticationHash,
|
||||
};
|
||||
|
||||
unlockData = {
|
||||
salt: credentials.salt,
|
||||
kdf: credentials.kdfConfig,
|
||||
masterKeyWrappedUserKey: "masterKeyWrappedUserKey" as MasterKeyWrappedUserKey,
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
salt: this.salt,
|
||||
kdf: this.kdf,
|
||||
masterKeyWrappedUserKey: this.masterKeyWrappedUserKey,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
existingUserPublicKey = Utils.fromB64ToArray("existingUserPublicKey") as UserPublicKey;
|
||||
existingUserPrivateKey = Utils.fromB64ToArray("existingUserPrivateKey") as UserPrivateKey;
|
||||
userKeyEncryptedPrivateKey = new EncString("userKeyEncryptedPrivateKey");
|
||||
|
||||
keyPair = ["publicKey", new EncString("privateKey")];
|
||||
keysRequest = new KeysRequest(keyPair[0], keyPair[1].encryptedString);
|
||||
|
||||
organizationKeys = {
|
||||
privateKey: "orgPrivateKey",
|
||||
publicKey: "orgPublicKey",
|
||||
} as OrganizationKeysResponse;
|
||||
orgPublicKeyEncryptedUserKey = new EncString("orgPublicKeyEncryptedUserKey");
|
||||
|
||||
userDecryptionOptions = new UserDecryptionOptions({ hasMasterPassword: true });
|
||||
userDecryptionOptionsSubject = new BehaviorSubject(userDecryptionOptions);
|
||||
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValue(
|
||||
userDecryptionOptionsSubject,
|
||||
);
|
||||
|
||||
setPasswordRequest = SetPasswordRequest.newConstructor(
|
||||
authenticationData,
|
||||
unlockData,
|
||||
credentials.newPasswordHint,
|
||||
credentials.orgSsoIdentifier,
|
||||
keysRequest,
|
||||
);
|
||||
|
||||
enrollmentRequest = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
enrollmentRequest.masterPasswordHash = authenticationData.masterPasswordAuthenticationHash;
|
||||
enrollmentRequest.resetPasswordKey = orgPublicKeyEncryptedUserKey.encryptedString;
|
||||
});
|
||||
|
||||
interface MockConfig {
|
||||
userType: SetInitialPasswordUserType;
|
||||
userHasUserKey: boolean;
|
||||
userHasLocalKeyPair: boolean;
|
||||
resetPasswordAutoEnroll: boolean;
|
||||
}
|
||||
|
||||
const defaultMockConfig: MockConfig = {
|
||||
userType: SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER,
|
||||
userHasUserKey: true,
|
||||
userHasLocalKeyPair: false,
|
||||
resetPasswordAutoEnroll: false,
|
||||
};
|
||||
|
||||
function setupMocks(config: MockConfig = defaultMockConfig) {
|
||||
if (config.userHasUserKey) {
|
||||
keyService.userKey$.mockReturnValue(of(userKey));
|
||||
} else {
|
||||
keyService.userKey$.mockReturnValue(of(null));
|
||||
jest.spyOn(PureCrypto, "make_user_key_aes256_cbc_hmac").mockReturnValue(new Uint8Array(64));
|
||||
}
|
||||
|
||||
// Mock MasterPasswordAuthenticationData and MasterPasswordUnlockData
|
||||
masterPasswordService.makeMasterPasswordAuthenticationData.mockResolvedValue(
|
||||
authenticationData,
|
||||
);
|
||||
masterPasswordService.makeMasterPasswordUnlockData.mockResolvedValue(unlockData);
|
||||
|
||||
// Mock keyPair values
|
||||
if (config.userType === SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER) {
|
||||
if (config.userHasLocalKeyPair) {
|
||||
keyService.userPrivateKey$.mockReturnValue(of(existingUserPrivateKey));
|
||||
keyService.userPublicKey$.mockReturnValue(of(existingUserPublicKey));
|
||||
encryptService.wrapDecapsulationKey.mockResolvedValue(userKeyEncryptedPrivateKey);
|
||||
} else {
|
||||
keyService.userPrivateKey$.mockReturnValue(of(null));
|
||||
keyService.userPublicKey$.mockReturnValue(of(null));
|
||||
keyService.makeKeyPair.mockResolvedValue(keyPair);
|
||||
}
|
||||
}
|
||||
|
||||
// Mock handleResetPasswordAutoEnroll() values
|
||||
if (config.resetPasswordAutoEnroll) {
|
||||
organizationApiService.getKeys.mockResolvedValue(organizationKeys);
|
||||
encryptService.encapsulateKeyUnsigned.mockResolvedValue(orgPublicKeyEncryptedUserKey);
|
||||
keyService.userKey$.mockReturnValue(of(userKey));
|
||||
}
|
||||
}
|
||||
|
||||
describe("general error handling", () => {
|
||||
[
|
||||
"newPassword",
|
||||
"newPasswordHint",
|
||||
"kdfConfig",
|
||||
"salt",
|
||||
"orgSsoIdentifier",
|
||||
"orgId",
|
||||
"resetPasswordAutoEnroll",
|
||||
].forEach((key) => {
|
||||
it(`should throw if ${key} is not provided on the SetInitialPasswordCredentials object`, async () => {
|
||||
// Arrange
|
||||
const invalidCredentials: SetInitialPasswordCredentials = {
|
||||
...credentials,
|
||||
[key]: null,
|
||||
};
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(invalidCredentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(`${key} not found. Could not set password.`);
|
||||
});
|
||||
});
|
||||
|
||||
["userId", "userType"].forEach((param) => {
|
||||
it(`should throw if ${param} was not passed in`, async () => {
|
||||
// Arrange & Act
|
||||
const promise = sut.setInitialPassword(
|
||||
credentials,
|
||||
param === "userType" ? null : userType,
|
||||
param === "userId" ? null : userId,
|
||||
);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(`${param} not found. Could not set password.`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("given SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER", () => {
|
||||
beforeEach(() => {
|
||||
userType = SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER;
|
||||
});
|
||||
|
||||
it("should create MasterPasswordAuthenticationData", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordService.makeMasterPasswordAuthenticationData).toHaveBeenCalledWith(
|
||||
credentials.newPassword,
|
||||
credentials.kdfConfig,
|
||||
credentials.salt,
|
||||
);
|
||||
});
|
||||
|
||||
it("should create MasterPasswordUnlockData", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordService.makeMasterPasswordUnlockData).toHaveBeenCalledWith(
|
||||
credentials.newPassword,
|
||||
credentials.kdfConfig,
|
||||
credentials.salt,
|
||||
userKey,
|
||||
);
|
||||
});
|
||||
|
||||
describe("given the user has an existing local key pair", () => {
|
||||
it("should NOT create a brand new key pair for the user", async () => {
|
||||
// Arrange
|
||||
setPasswordRequest.keys = {
|
||||
encryptedPrivateKey: userKeyEncryptedPrivateKey.encryptedString,
|
||||
publicKey: Utils.fromBufferToB64(existingUserPublicKey),
|
||||
};
|
||||
|
||||
setupMocks({ ...defaultMockConfig, userHasLocalKeyPair: true });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(keyService.userPrivateKey$).toHaveBeenCalledWith(userId);
|
||||
expect(keyService.userPublicKey$).toHaveBeenCalledWith(userId);
|
||||
expect(encryptService.wrapDecapsulationKey).toHaveBeenCalledWith(
|
||||
existingUserPrivateKey,
|
||||
userKey,
|
||||
);
|
||||
expect(keyService.makeKeyPair).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the user has a userKey", () => {
|
||||
it("should successfully set an initial password", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the user does NOT have a userKey", () => {
|
||||
it("should successfully set an initial password", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userHasUserKey: false });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw if a key pair is not found", async () => {
|
||||
// Arrange
|
||||
keyPair = null;
|
||||
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow("keyPair not found. Could not set password.");
|
||||
expect(masterPasswordApiService.setPassword).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should throw if an encrypted private key is not found", async () => {
|
||||
// Arrange
|
||||
keyPair[1].encryptedString = "" as EncryptedString;
|
||||
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(
|
||||
"encrypted private key not found. Could not set password.",
|
||||
);
|
||||
expect(masterPasswordApiService.setPassword).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("given the initial password has been successfully set", () => {
|
||||
it("should clear the ForceSetPasswordReason by setting it to None", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(masterPasswordService.setForceSetPasswordReason).toHaveBeenCalledWith(
|
||||
ForceSetPasswordReason.None,
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
it("should update account decryption properties", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(userDecryptionOptionsService.setUserDecryptionOptionsById).toHaveBeenCalledWith(
|
||||
userId,
|
||||
userDecryptionOptions,
|
||||
);
|
||||
expect(masterPasswordService.setMasterPasswordUnlockData).toHaveBeenCalledWith(
|
||||
unlockData,
|
||||
userId,
|
||||
);
|
||||
expect(kdfConfigService.setKdfConfig).toHaveBeenCalledWith(userId, unlockData.kdf);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId);
|
||||
});
|
||||
|
||||
it("should set the private key to state", async () => {
|
||||
// Arrange
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(keyPair[1].encryptedString, userId);
|
||||
expect(
|
||||
accountCryptographicStateService.setAccountCryptographicState,
|
||||
).toHaveBeenCalledWith(
|
||||
{
|
||||
V1: {
|
||||
private_key: keyPair[1].encryptedString as EncryptedString,
|
||||
},
|
||||
},
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
describe("given resetPasswordAutoEnroll is true", () => {
|
||||
it(`should handle reset password (account recovery) auto enroll`, async () => {
|
||||
// Arrange
|
||||
credentials.resetPasswordAutoEnroll = true;
|
||||
|
||||
setupMocks({ ...defaultMockConfig, resetPasswordAutoEnroll: true });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).toHaveBeenCalledWith(credentials.orgId, userId, enrollmentRequest);
|
||||
});
|
||||
|
||||
it("should throw if organization keys are not found", async () => {
|
||||
// Arrange
|
||||
credentials.resetPasswordAutoEnroll = true;
|
||||
organizationKeys = null;
|
||||
|
||||
setupMocks({ ...defaultMockConfig, resetPasswordAutoEnroll: true });
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(
|
||||
"Organization keys response is null. Could not handle reset password auto enroll.",
|
||||
);
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
["orgPublicKeyEncryptedUserKey", "orgPublicKeyEncryptedUserKey.encryptedString"].forEach(
|
||||
(property) => {
|
||||
it("should throw if orgPublicKeyEncryptedUserKey is not found", async () => {
|
||||
// Arrange
|
||||
credentials.resetPasswordAutoEnroll = true;
|
||||
|
||||
if (property === "orgPublicKeyEncryptedUserKey") {
|
||||
orgPublicKeyEncryptedUserKey = null;
|
||||
} else {
|
||||
orgPublicKeyEncryptedUserKey.encryptedString = "" as EncryptedString;
|
||||
}
|
||||
|
||||
setupMocks({ ...defaultMockConfig, resetPasswordAutoEnroll: true });
|
||||
|
||||
// Act
|
||||
const promise = sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
await expect(promise).rejects.toThrow(
|
||||
"orgPublicKeyEncryptedUserKey not found. Could not handle reset password auto enroll.",
|
||||
);
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(
|
||||
setPasswordRequest,
|
||||
);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("given resetPasswordAutoEnroll is false", () => {
|
||||
it(`should NOT handle reset password (account recovery) auto enroll`, async () => {
|
||||
// Arrange
|
||||
credentials.resetPasswordAutoEnroll = false;
|
||||
|
||||
setupMocks();
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("given SetInitialPasswordUserType.TDE_ORG_USER_RESET_PASSWORD_PERMISSION_REQUIRES_MP", () => {
|
||||
beforeEach(() => {
|
||||
userType = SetInitialPasswordUserType.TDE_ORG_USER_RESET_PASSWORD_PERMISSION_REQUIRES_MP;
|
||||
setPasswordRequest.keys = null;
|
||||
});
|
||||
|
||||
it("should NOT generate a keyPair", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(keyService.userPrivateKey$).not.toHaveBeenCalled();
|
||||
expect(keyService.userPublicKey$).not.toHaveBeenCalled();
|
||||
expect(encryptService.wrapDecapsulationKey).not.toHaveBeenCalled();
|
||||
expect(keyService.makeKeyPair).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("given the user has a userKey", () => {
|
||||
it("should successfully set an initial password", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the user does NOT have a userKey", () => {
|
||||
it("should successfully set an initial password", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given the initial password has been successfully set", () => {
|
||||
it("should clear the ForceSetPasswordReason by setting it to None", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(masterPasswordService.setForceSetPasswordReason).toHaveBeenCalledWith(
|
||||
ForceSetPasswordReason.None,
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
it("should update account decryption properties", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(userDecryptionOptionsService.setUserDecryptionOptionsById).toHaveBeenCalledWith(
|
||||
userId,
|
||||
userDecryptionOptions,
|
||||
);
|
||||
expect(masterPasswordService.setMasterPasswordUnlockData).toHaveBeenCalledWith(
|
||||
unlockData,
|
||||
userId,
|
||||
);
|
||||
expect(kdfConfigService.setKdfConfig).toHaveBeenCalledWith(userId, credentials.kdfConfig);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(masterKeyEncryptedUserKey[0], userId);
|
||||
});
|
||||
|
||||
it("should NOT set the private key to state", async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("given resetPasswordAutoEnroll is true", () => {
|
||||
it(`should handle reset password (account recovery) auto enroll`, async () => {
|
||||
// Arrange
|
||||
credentials.resetPasswordAutoEnroll = true;
|
||||
|
||||
setupMocks({ ...defaultMockConfig, userType, resetPasswordAutoEnroll: true });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).toHaveBeenCalledWith(credentials.orgId, userId, enrollmentRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given resetPasswordAutoEnroll is false", () => {
|
||||
it(`should NOT handle reset password (account recovery) auto enroll`, async () => {
|
||||
// Arrange
|
||||
setupMocks({ ...defaultMockConfig, userType });
|
||||
|
||||
// Act
|
||||
await sut.setInitialPassword(credentials, userType, userId);
|
||||
|
||||
// Assert
|
||||
expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setInitialPasswordTdeOffboarding(...)", () => {
|
||||
// Mock function parameters
|
||||
let credentials: SetInitialPasswordTdeOffboardingCredentials;
|
||||
|
||||
@@ -39,7 +39,6 @@ import {
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
import {
|
||||
SetInitialPasswordCredentials,
|
||||
SetInitialPasswordCredentialsOld,
|
||||
SetInitialPasswordService,
|
||||
SetInitialPasswordTdeOffboardingCredentials,
|
||||
@@ -196,14 +195,7 @@ export class SetInitialPasswordComponent implements OnInit {
|
||||
switch (this.userType) {
|
||||
case SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER:
|
||||
case SetInitialPasswordUserType.TDE_ORG_USER_RESET_PASSWORD_PERMISSION_REQUIRES_MP:
|
||||
// Remove wrapping "if" check and early return in PM-28143
|
||||
if (passwordInputResult.newApisFlagEnabled) {
|
||||
await this.setInitialPassword(passwordInputResult);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.setInitialPasswordOld(passwordInputResult); // remove in PM-28143
|
||||
|
||||
break;
|
||||
case SetInitialPasswordUserType.OFFBOARDED_TDE_ORG_USER:
|
||||
await this.setInitialPasswordTdeOffboarding(passwordInputResult);
|
||||
@@ -265,48 +257,6 @@ export class SetInitialPasswordComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private async setInitialPassword(passwordInputResult: PasswordInputResult) {
|
||||
const ctx = "Could not set initial password.";
|
||||
|
||||
assertTruthy(passwordInputResult.newPassword, "newPassword", ctx);
|
||||
assertTruthy(passwordInputResult.kdfConfig, "kdfConfig", ctx);
|
||||
assertTruthy(passwordInputResult.salt, "salt", ctx);
|
||||
assertNonNullish(passwordInputResult.newPasswordHint, "newPasswordHint", ctx); // can have an empty string as a valid value, so check non-nullish
|
||||
|
||||
assertTruthy(this.orgSsoIdentifier, "orgSsoIdentifier", ctx);
|
||||
assertTruthy(this.orgId, "orgId", ctx);
|
||||
assertTruthy(this.userType, "userType", ctx);
|
||||
assertTruthy(this.userId, "userId", ctx);
|
||||
assertNonNullish(this.resetPasswordAutoEnroll, "resetPasswordAutoEnroll", ctx); // can have `false` as a valid value, so check non-nullish
|
||||
|
||||
try {
|
||||
const credentials: SetInitialPasswordCredentials = {
|
||||
newPassword: passwordInputResult.newPassword,
|
||||
newPasswordHint: passwordInputResult.newPasswordHint,
|
||||
kdfConfig: passwordInputResult.kdfConfig,
|
||||
salt: passwordInputResult.salt,
|
||||
orgSsoIdentifier: this.orgSsoIdentifier,
|
||||
orgId: this.orgId,
|
||||
resetPasswordAutoEnroll: this.resetPasswordAutoEnroll,
|
||||
};
|
||||
|
||||
await this.setInitialPasswordService.setInitialPassword(
|
||||
credentials,
|
||||
this.userType,
|
||||
this.userId,
|
||||
);
|
||||
|
||||
this.showSuccessToastByUserType();
|
||||
|
||||
this.submitting = false;
|
||||
await this.router.navigate(["vault"]);
|
||||
} catch (e) {
|
||||
this.logService.error("Error setting initial password", e);
|
||||
this.validationService.showError(e);
|
||||
this.submitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async setInitialPasswordTdeOffboarding(passwordInputResult: PasswordInputResult) {
|
||||
const ctx = "Could not set initial password.";
|
||||
assertTruthy(passwordInputResult.newMasterKey, "newMasterKey", ctx);
|
||||
|
||||
@@ -58,16 +58,6 @@ export interface SetInitialPasswordCredentialsOld {
|
||||
salt: MasterPasswordSalt;
|
||||
}
|
||||
|
||||
export interface SetInitialPasswordCredentials {
|
||||
newPassword: string;
|
||||
newPasswordHint: string;
|
||||
kdfConfig: KdfConfig;
|
||||
salt: MasterPasswordSalt;
|
||||
orgSsoIdentifier: string;
|
||||
orgId: string;
|
||||
resetPasswordAutoEnroll: boolean;
|
||||
}
|
||||
|
||||
export interface SetInitialPasswordTdeOffboardingCredentials {
|
||||
newMasterKey: MasterKey;
|
||||
newServerMasterKeyHash: string;
|
||||
@@ -110,19 +100,4 @@ export abstract class SetInitialPasswordService {
|
||||
credentials: SetInitialPasswordTdeOffboardingCredentials,
|
||||
userId: UserId,
|
||||
) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Sets an initial password for an existing authed user who is either:
|
||||
* - {@link SetInitialPasswordUserType.JIT_PROVISIONED_MP_ORG_USER}
|
||||
* - {@link SetInitialPasswordUserType.TDE_ORG_USER_RESET_PASSWORD_PERMISSION_REQUIRES_MP}
|
||||
*
|
||||
* @param credentials An object of the credentials needed to set the initial password
|
||||
* @throws If any property on the `credentials` object is null or undefined, or if a
|
||||
* keyPair could not be found/created for a JIT_PROVISIONED_MP_ORG_USER
|
||||
*/
|
||||
abstract setInitialPassword: (
|
||||
credentials: SetInitialPasswordCredentials,
|
||||
userType: SetInitialPasswordUserType,
|
||||
userId: UserId,
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user