mirror of
https://github.com/bitwarden/browser
synced 2026-01-21 11:53:34 +00:00
fix(register): [PM-27085] Account Register Uses New Data Types - Initial changes.
This commit is contained in:
@@ -18,7 +18,9 @@ import {
|
||||
EncryptedString,
|
||||
EncString,
|
||||
} from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
export class WebRegistrationFinishService
|
||||
@@ -28,12 +30,13 @@ export class WebRegistrationFinishService
|
||||
constructor(
|
||||
protected keyService: KeyService,
|
||||
protected accountApiService: AccountApiService,
|
||||
protected masterPasswordService: MasterPasswordServiceAbstraction,
|
||||
private organizationInviteService: OrganizationInviteService,
|
||||
private policyApiService: PolicyApiServiceAbstraction,
|
||||
private logService: LogService,
|
||||
private policyService: PolicyService,
|
||||
) {
|
||||
super(keyService, accountApiService);
|
||||
super(keyService, accountApiService, masterPasswordService);
|
||||
}
|
||||
|
||||
override async getOrgNameFromOrgInvite(): Promise<string | null> {
|
||||
@@ -78,6 +81,7 @@ export class WebRegistrationFinishService
|
||||
|
||||
// Note: the org invite token and email verification are mutually exclusive. Only one will be present.
|
||||
override async buildRegisterRequest(
|
||||
newUserKey: UserKey,
|
||||
email: string,
|
||||
passwordInputResult: PasswordInputResult,
|
||||
encryptedUserKey: EncryptedString,
|
||||
@@ -90,6 +94,7 @@ export class WebRegistrationFinishService
|
||||
providerUserId?: string,
|
||||
): Promise<RegisterFinishRequest> {
|
||||
const registerRequest = await super.buildRegisterRequest(
|
||||
newUserKey,
|
||||
email,
|
||||
passwordInputResult,
|
||||
encryptedUserKey,
|
||||
|
||||
@@ -73,7 +73,10 @@ import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-managemen
|
||||
import { AccountCryptographicStateService } from "@bitwarden/common/key-management/account-cryptography/account-cryptographic-state.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import {
|
||||
InternalMasterPasswordServiceAbstraction,
|
||||
MasterPasswordServiceAbstraction,
|
||||
} from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { SessionTimeoutTypeService } from "@bitwarden/common/key-management/session-timeout";
|
||||
import {
|
||||
VaultTimeout,
|
||||
@@ -286,6 +289,7 @@ const safeProviders: SafeProvider[] = [
|
||||
deps: [
|
||||
KeyServiceAbstraction,
|
||||
AccountApiServiceAbstraction,
|
||||
MasterPasswordServiceAbstraction,
|
||||
OrganizationInviteService,
|
||||
PolicyApiServiceAbstraction,
|
||||
LogService,
|
||||
|
||||
@@ -1598,7 +1598,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: RegistrationFinishServiceAbstraction,
|
||||
useClass: DefaultRegistrationFinishService,
|
||||
deps: [KeyService, AccountApiServiceAbstraction],
|
||||
deps: [KeyService, AccountApiServiceAbstraction, MasterPasswordServiceAbstraction],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: TwoFactorAuthComponentService,
|
||||
|
||||
@@ -2,6 +2,11 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
|
||||
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
|
||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import {
|
||||
MasterPasswordUnlockData,
|
||||
MasterPasswordSalt,
|
||||
} from "@bitwarden/common/key-management/master-password/types/master-password.types";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||
@@ -16,12 +21,18 @@ describe("DefaultRegistrationFinishService", () => {
|
||||
|
||||
let keyService: MockProxy<KeyService>;
|
||||
let accountApiService: MockProxy<AccountApiService>;
|
||||
let masterPasswordService: MockProxy<MasterPasswordServiceAbstraction>;
|
||||
|
||||
beforeEach(() => {
|
||||
keyService = mock<KeyService>();
|
||||
accountApiService = mock<AccountApiService>();
|
||||
masterPasswordService = mock<MasterPasswordServiceAbstraction>();
|
||||
|
||||
service = new DefaultRegistrationFinishService(keyService, accountApiService);
|
||||
service = new DefaultRegistrationFinishService(
|
||||
keyService,
|
||||
accountApiService,
|
||||
masterPasswordService,
|
||||
);
|
||||
});
|
||||
|
||||
it("instantiates", () => {
|
||||
@@ -74,6 +85,7 @@ describe("DefaultRegistrationFinishService", () => {
|
||||
|
||||
it("throws an error if the user key cannot be created", async () => {
|
||||
keyService.makeUserKey.mockResolvedValue([null, null]);
|
||||
masterPasswordService.emailToSalt.mockReturnValue("salt" as unknown as MasterPasswordSalt);
|
||||
|
||||
await expect(service.finishRegistration(email, passwordInputResult)).rejects.toThrow(
|
||||
"User key could not be created",
|
||||
@@ -84,6 +96,19 @@ describe("DefaultRegistrationFinishService", () => {
|
||||
keyService.makeUserKey.mockResolvedValue([userKey, userKeyEncString]);
|
||||
keyService.makeKeyPair.mockResolvedValue(userKeyPair);
|
||||
accountApiService.registerFinish.mockResolvedValue();
|
||||
masterPasswordService.emailToSalt.mockReturnValue("salt" as unknown as MasterPasswordSalt);
|
||||
masterPasswordService.makeMasterPasswordAuthenticationData.mockResolvedValue({
|
||||
salt: "salt" as unknown as MasterPasswordSalt,
|
||||
kdf: DEFAULT_KDF_CONFIG,
|
||||
masterPasswordAuthenticationHash: "authHash" as unknown as string,
|
||||
});
|
||||
masterPasswordService.makeMasterPasswordUnlockData.mockResolvedValue(
|
||||
new MasterPasswordUnlockData(
|
||||
"salt" as unknown as MasterPasswordSalt,
|
||||
DEFAULT_KDF_CONFIG,
|
||||
new EncString("wrapped") as unknown as any,
|
||||
),
|
||||
);
|
||||
|
||||
await service.finishRegistration(email, passwordInputResult, emailVerificationToken);
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
EncryptedString,
|
||||
EncString,
|
||||
} from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { PasswordInputResult } from "../../input-password/password-input-result";
|
||||
@@ -18,6 +20,7 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
||||
constructor(
|
||||
protected keyService: KeyService,
|
||||
protected accountApiService: AccountApiService,
|
||||
protected masterPasswordService: MasterPasswordServiceAbstraction,
|
||||
) {}
|
||||
|
||||
getOrgNameFromOrgInvite(): Promise<string | null> {
|
||||
@@ -48,6 +51,7 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
||||
const userAsymmetricKeys = await this.keyService.makeKeyPair(newUserKey);
|
||||
|
||||
const registerRequest = await this.buildRegisterRequest(
|
||||
newUserKey,
|
||||
email,
|
||||
passwordInputResult,
|
||||
newEncUserKey.encryptedString,
|
||||
@@ -64,6 +68,7 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
||||
}
|
||||
|
||||
protected async buildRegisterRequest(
|
||||
newUserKey: UserKey,
|
||||
email: string,
|
||||
passwordInputResult: PasswordInputResult,
|
||||
encryptedUserKey: EncryptedString,
|
||||
@@ -80,14 +85,32 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
||||
userAsymmetricKeys[1].encryptedString,
|
||||
);
|
||||
|
||||
// Get salt value, for now we derive it from the email but this could change to be random bytes
|
||||
// in the future once the email and salt are separated.
|
||||
const salt = this.masterPasswordService.emailToSalt(email);
|
||||
|
||||
const masterPasswordAuthentication =
|
||||
await this.masterPasswordService.makeMasterPasswordAuthenticationData(
|
||||
passwordInputResult.newPassword,
|
||||
passwordInputResult.kdfConfig,
|
||||
salt,
|
||||
);
|
||||
|
||||
const masterPasswordUnlock = await this.masterPasswordService.makeMasterPasswordUnlockData(
|
||||
passwordInputResult.newPassword,
|
||||
passwordInputResult.kdfConfig,
|
||||
salt,
|
||||
newUserKey,
|
||||
);
|
||||
|
||||
const registerFinishRequest = new RegisterFinishRequest(
|
||||
email,
|
||||
passwordInputResult.newServerMasterKeyHash,
|
||||
passwordInputResult.newPasswordHint,
|
||||
encryptedUserKey,
|
||||
userAsymmetricKeysRequest,
|
||||
passwordInputResult.kdfConfig.kdfType,
|
||||
passwordInputResult.kdfConfig.iterations,
|
||||
masterPasswordAuthentication,
|
||||
masterPasswordUnlock,
|
||||
);
|
||||
|
||||
if (emailVerificationToken) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { KdfType } from "@bitwarden/key-management";
|
||||
|
||||
import { EncryptedString } from "../../../../key-management/crypto/models/enc-string";
|
||||
import {
|
||||
MasterPasswordAuthenticationData,
|
||||
MasterPasswordUnlockData,
|
||||
} from "../../../../key-management/master-password/types/master-password.types";
|
||||
import { KeysRequest } from "../../../../models/request/keys.request";
|
||||
|
||||
export class RegisterFinishRequest {
|
||||
@@ -15,10 +15,8 @@ export class RegisterFinishRequest {
|
||||
public userSymmetricKey: EncryptedString,
|
||||
public userAsymmetricKeys: KeysRequest,
|
||||
|
||||
public kdf: KdfType,
|
||||
public kdfIterations: number,
|
||||
public kdfMemory?: number,
|
||||
public kdfParallelism?: number,
|
||||
public masterPasswordAuthentication: MasterPasswordAuthenticationData,
|
||||
public masterPasswordUnlock: MasterPasswordUnlockData,
|
||||
|
||||
public emailVerificationToken?: string,
|
||||
public orgSponsoredFreeFamilyPlanToken?: string,
|
||||
|
||||
Reference in New Issue
Block a user