mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
[PM-5735] Create kdf Service (#8715)
* key connector migration initial * migrator complete * fix dependencies * finalized tests * fix deps and sync main * clean up definition file * fixing tests * fixed tests * fixing CLI, Browser, Desktop builds * fixed factory options * reverting exports * implemented UserKeyDefinition clearOn * Initial Kdf Service Changes * rename and account setting kdfconfig * fixing tests and renaming migration * fixed DI ordering for browser * rename and fix DI * Clean up Migrations * fixing migrations * begin data structure changes for kdf config * Make KDF more type safe; co-author: jlf0dev * fixing tests * Fixed CLI login and comments * set now accepts userId and test updates --------- Co-authored-by: Jake Fink <jfink@bitwarden.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
|
||||
@@ -44,6 +45,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
let userDecryptionOptions: MockProxy<InternalUserDecryptionOptionsServiceAbstraction>;
|
||||
let deviceTrustService: MockProxy<DeviceTrustServiceAbstraction>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
const mockUserId = Utils.newGuid() as UserId;
|
||||
let accountService: FakeAccountService;
|
||||
@@ -77,6 +79,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
userDecryptionOptions = mock<InternalUserDecryptionOptionsServiceAbstraction>();
|
||||
deviceTrustService = mock<DeviceTrustServiceAbstraction>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
accountService = mockAccountServiceWith(mockUserId);
|
||||
masterPasswordService = new FakeMasterPasswordService();
|
||||
@@ -101,6 +104,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
userDecryptionOptions,
|
||||
deviceTrustService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
tokenResponse = identityTokenResponseFactory();
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -63,6 +64,7 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
|
||||
private deviceTrustService: DeviceTrustServiceAbstraction,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
super(
|
||||
accountService,
|
||||
@@ -78,6 +80,7 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
this.cache = new BehaviorSubject(data);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -117,6 +118,7 @@ describe("LoginStrategy", () => {
|
||||
let policyService: MockProxy<PolicyService>;
|
||||
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let passwordLoginStrategy: PasswordLoginStrategy;
|
||||
let credentials: PasswordLoginCredentials;
|
||||
@@ -136,6 +138,7 @@ describe("LoginStrategy", () => {
|
||||
stateService = mock<StateService>();
|
||||
twoFactorService = mock<TwoFactorService>();
|
||||
userDecryptionOptionsService = mock<InternalUserDecryptionOptionsServiceAbstraction>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
policyService = mock<PolicyService>();
|
||||
passwordStrengthService = mock<PasswordStrengthService>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
@@ -162,6 +165,7 @@ describe("LoginStrategy", () => {
|
||||
policyService,
|
||||
loginStrategyService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
credentials = new PasswordLoginCredentials(email, masterPassword);
|
||||
});
|
||||
@@ -208,8 +212,6 @@ describe("LoginStrategy", () => {
|
||||
userId: userId,
|
||||
name: name,
|
||||
email: email,
|
||||
kdfIterations: kdfIterations,
|
||||
kdfType: kdf,
|
||||
},
|
||||
},
|
||||
keys: new AccountKeys(),
|
||||
@@ -404,6 +406,7 @@ describe("LoginStrategy", () => {
|
||||
policyService,
|
||||
loginStrategyService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
apiService.postIdentityToken.mockResolvedValue(identityTokenResponseFactory());
|
||||
|
||||
@@ -2,12 +2,14 @@ import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
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";
|
||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||
import { Argon2KdfConfig, PBKDF2KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import { DeviceRequest } from "@bitwarden/common/auth/models/request/identity-token/device.request";
|
||||
import { PasswordTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/password-token.request";
|
||||
import { SsoTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/sso-token.request";
|
||||
@@ -27,6 +29,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||
import { Account, AccountProfile } from "@bitwarden/common/platform/models/domain/account";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
@@ -72,6 +75,7 @@ export abstract class LoginStrategy {
|
||||
protected twoFactorService: TwoFactorService,
|
||||
protected userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
|
||||
protected billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected KdfConfigService: KdfConfigService,
|
||||
) {}
|
||||
|
||||
abstract exportCache(): CacheData;
|
||||
@@ -182,10 +186,6 @@ export abstract class LoginStrategy {
|
||||
userId,
|
||||
name: accountInformation.name,
|
||||
email: accountInformation.email,
|
||||
kdfIterations: tokenResponse.kdfIterations,
|
||||
kdfMemory: tokenResponse.kdfMemory,
|
||||
kdfParallelism: tokenResponse.kdfParallelism,
|
||||
kdfType: tokenResponse.kdf,
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -195,6 +195,17 @@ export abstract class LoginStrategy {
|
||||
UserDecryptionOptions.fromResponse(tokenResponse),
|
||||
);
|
||||
|
||||
await this.KdfConfigService.setKdfConfig(
|
||||
userId as UserId,
|
||||
tokenResponse.kdf === KdfType.PBKDF2_SHA256
|
||||
? new PBKDF2KdfConfig(tokenResponse.kdfIterations)
|
||||
: new Argon2KdfConfig(
|
||||
tokenResponse.kdfIterations,
|
||||
tokenResponse.kdfMemory,
|
||||
tokenResponse.kdfParallelism,
|
||||
),
|
||||
);
|
||||
|
||||
await this.billingAccountProfileStateService.setHasPremium(accountInformation.premium, false);
|
||||
return userId as UserId;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -71,6 +72,7 @@ describe("PasswordLoginStrategy", () => {
|
||||
let policyService: MockProxy<PolicyService>;
|
||||
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let passwordLoginStrategy: PasswordLoginStrategy;
|
||||
let credentials: PasswordLoginCredentials;
|
||||
@@ -94,6 +96,7 @@ describe("PasswordLoginStrategy", () => {
|
||||
policyService = mock<PolicyService>();
|
||||
passwordStrengthService = mock<PasswordStrengthService>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
appIdService.getAppId.mockResolvedValue(deviceId);
|
||||
tokenService.decodeAccessToken.mockResolvedValue({});
|
||||
@@ -127,6 +130,7 @@ describe("PasswordLoginStrategy", () => {
|
||||
policyService,
|
||||
loginStrategyService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
credentials = new PasswordLoginCredentials(email, masterPassword);
|
||||
tokenResponse = identityTokenResponseFactory(masterPasswordPolicy);
|
||||
|
||||
@@ -5,6 +5,7 @@ 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 { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -89,6 +90,7 @@ export class PasswordLoginStrategy extends LoginStrategy {
|
||||
private policyService: PolicyService,
|
||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
super(
|
||||
accountService,
|
||||
@@ -104,6 +106,7 @@ export class PasswordLoginStrategy extends LoginStrategy {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
this.cache = new BehaviorSubject(data);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -54,6 +55,7 @@ describe("SsoLoginStrategy", () => {
|
||||
let authRequestService: MockProxy<AuthRequestServiceAbstraction>;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let ssoLoginStrategy: SsoLoginStrategy;
|
||||
let credentials: SsoLoginCredentials;
|
||||
@@ -86,6 +88,7 @@ describe("SsoLoginStrategy", () => {
|
||||
authRequestService = mock<AuthRequestServiceAbstraction>();
|
||||
i18nService = mock<I18nService>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
tokenService.getTwoFactorToken.mockResolvedValue(null);
|
||||
appIdService.getAppId.mockResolvedValue(deviceId);
|
||||
@@ -110,6 +113,7 @@ describe("SsoLoginStrategy", () => {
|
||||
authRequestService,
|
||||
i18nService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
credentials = new SsoLoginCredentials(ssoCode, ssoCodeVerifier, ssoRedirectUrl, ssoOrgId);
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
@@ -98,6 +99,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
private authRequestService: AuthRequestServiceAbstraction,
|
||||
private i18nService: I18nService,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
super(
|
||||
accountService,
|
||||
@@ -113,6 +115,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
this.cache = new BehaviorSubject(data);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -49,6 +50,7 @@ describe("UserApiLoginStrategy", () => {
|
||||
let keyConnectorService: MockProxy<KeyConnectorService>;
|
||||
let environmentService: MockProxy<EnvironmentService>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let apiLogInStrategy: UserApiLoginStrategy;
|
||||
let credentials: UserApiLoginCredentials;
|
||||
@@ -76,6 +78,7 @@ describe("UserApiLoginStrategy", () => {
|
||||
keyConnectorService = mock<KeyConnectorService>();
|
||||
environmentService = mock<EnvironmentService>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
appIdService.getAppId.mockResolvedValue(deviceId);
|
||||
tokenService.getTwoFactorToken.mockResolvedValue(null);
|
||||
@@ -98,6 +101,7 @@ describe("UserApiLoginStrategy", () => {
|
||||
environmentService,
|
||||
keyConnectorService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
credentials = new UserApiLoginCredentials(apiClientId, apiClientSecret);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
@@ -57,6 +58,7 @@ export class UserApiLoginStrategy extends LoginStrategy {
|
||||
private environmentService: EnvironmentService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
super(
|
||||
accountService,
|
||||
@@ -72,6 +74,7 @@ export class UserApiLoginStrategy extends LoginStrategy {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
this.cache = new BehaviorSubject(data);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||
@@ -42,6 +43,7 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
let twoFactorService!: MockProxy<TwoFactorService>;
|
||||
let userDecryptionOptionsService: MockProxy<InternalUserDecryptionOptionsServiceAbstraction>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let webAuthnLoginStrategy!: WebAuthnLoginStrategy;
|
||||
|
||||
@@ -81,6 +83,7 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
twoFactorService = mock<TwoFactorService>();
|
||||
userDecryptionOptionsService = mock<InternalUserDecryptionOptionsServiceAbstraction>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
tokenService.getTwoFactorToken.mockResolvedValue(null);
|
||||
appIdService.getAppId.mockResolvedValue(deviceId);
|
||||
@@ -101,6 +104,7 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
// Create credentials
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -57,6 +58,7 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
|
||||
twoFactorService: TwoFactorService,
|
||||
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
super(
|
||||
accountService,
|
||||
@@ -72,6 +74,7 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
|
||||
twoFactorService,
|
||||
userDecryptionOptionsService,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
this.cache = new BehaviorSubject(data);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
@@ -66,6 +67,7 @@ describe("LoginStrategyService", () => {
|
||||
let authRequestService: MockProxy<AuthRequestServiceAbstraction>;
|
||||
let userDecryptionOptionsService: MockProxy<InternalUserDecryptionOptionsServiceAbstraction>;
|
||||
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||
|
||||
let stateProvider: FakeGlobalStateProvider;
|
||||
let loginStrategyCacheExpirationState: FakeGlobalState<Date | null>;
|
||||
@@ -95,6 +97,7 @@ describe("LoginStrategyService", () => {
|
||||
userDecryptionOptionsService = mock<UserDecryptionOptionsService>();
|
||||
billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||
stateProvider = new FakeGlobalStateProvider();
|
||||
kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
sut = new LoginStrategyService(
|
||||
accountService,
|
||||
@@ -119,6 +122,7 @@ describe("LoginStrategyService", () => {
|
||||
userDecryptionOptionsService,
|
||||
stateProvider,
|
||||
billingAccountProfileStateService,
|
||||
kdfConfigService,
|
||||
);
|
||||
|
||||
loginStrategyCacheExpirationState = stateProvider.getFake(CACHE_EXPIRATION_KEY);
|
||||
|
||||
@@ -10,13 +10,18 @@ import {
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
|
||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import {
|
||||
Argon2KdfConfig,
|
||||
KdfConfig,
|
||||
PBKDF2KdfConfig,
|
||||
} from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
||||
import { PasswordlessAuthRequest } from "@bitwarden/common/auth/models/request/passwordless-auth.request";
|
||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||
@@ -32,7 +37,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums/kdf-type.enum";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { GlobalState, GlobalStateProvider } from "@bitwarden/common/platform/state";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/src/auth/abstractions/device-trust.service.abstraction";
|
||||
@@ -105,6 +110,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
protected userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
|
||||
protected stateProvider: GlobalStateProvider,
|
||||
protected billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
this.currentAuthnTypeState = this.stateProvider.get(CURRENT_LOGIN_STRATEGY_KEY);
|
||||
this.loginStrategyCacheState = this.stateProvider.get(CACHE_KEY);
|
||||
@@ -233,24 +239,25 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
|
||||
async makePreloginKey(masterPassword: string, email: string): Promise<MasterKey> {
|
||||
email = email.trim().toLowerCase();
|
||||
let kdf: KdfType = null;
|
||||
let kdfConfig: KdfConfig = null;
|
||||
try {
|
||||
const preloginResponse = await this.apiService.postPrelogin(new PreloginRequest(email));
|
||||
if (preloginResponse != null) {
|
||||
kdf = preloginResponse.kdf;
|
||||
kdfConfig = new KdfConfig(
|
||||
preloginResponse.kdfIterations,
|
||||
preloginResponse.kdfMemory,
|
||||
preloginResponse.kdfParallelism,
|
||||
);
|
||||
kdfConfig =
|
||||
preloginResponse.kdf === KdfType.PBKDF2_SHA256
|
||||
? new PBKDF2KdfConfig(preloginResponse.kdfIterations)
|
||||
: new Argon2KdfConfig(
|
||||
preloginResponse.kdfIterations,
|
||||
preloginResponse.kdfMemory,
|
||||
preloginResponse.kdfParallelism,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e == null || e.statusCode !== 404) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return await this.cryptoService.makeMasterKey(masterPassword, email, kdf, kdfConfig);
|
||||
return await this.cryptoService.makeMasterKey(masterPassword, email, kdfConfig);
|
||||
}
|
||||
|
||||
// TODO: move to auth request service
|
||||
@@ -354,6 +361,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.policyService,
|
||||
this,
|
||||
this.billingAccountProfileStateService,
|
||||
this.kdfConfigService,
|
||||
);
|
||||
case AuthenticationType.Sso:
|
||||
return new SsoLoginStrategy(
|
||||
@@ -375,6 +383,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.authRequestService,
|
||||
this.i18nService,
|
||||
this.billingAccountProfileStateService,
|
||||
this.kdfConfigService,
|
||||
);
|
||||
case AuthenticationType.UserApiKey:
|
||||
return new UserApiLoginStrategy(
|
||||
@@ -394,6 +403,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.environmentService,
|
||||
this.keyConnectorService,
|
||||
this.billingAccountProfileStateService,
|
||||
this.kdfConfigService,
|
||||
);
|
||||
case AuthenticationType.AuthRequest:
|
||||
return new AuthRequestLoginStrategy(
|
||||
@@ -412,6 +422,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.userDecryptionOptionsService,
|
||||
this.deviceTrustService,
|
||||
this.billingAccountProfileStateService,
|
||||
this.kdfConfigService,
|
||||
);
|
||||
case AuthenticationType.WebAuthn:
|
||||
return new WebAuthnLoginStrategy(
|
||||
@@ -429,6 +440,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
||||
this.twoFactorService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.billingAccountProfileStateService,
|
||||
this.kdfConfigService,
|
||||
);
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { PinLockType } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
@@ -16,6 +16,7 @@ export class PinCryptoService implements PinCryptoServiceAbstraction {
|
||||
private cryptoService: CryptoService,
|
||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||
private logService: LogService,
|
||||
private kdfConfigService: KdfConfigService,
|
||||
) {}
|
||||
async decryptUserKeyWithPin(pin: string): Promise<UserKey | null> {
|
||||
try {
|
||||
@@ -24,8 +25,7 @@ export class PinCryptoService implements PinCryptoServiceAbstraction {
|
||||
const { pinKeyEncryptedUserKey, oldPinKeyEncryptedMasterKey } =
|
||||
await this.getPinKeyEncryptedKeys(pinLockType);
|
||||
|
||||
const kdf: KdfType = await this.stateService.getKdfType();
|
||||
const kdfConfig: KdfConfig = await this.stateService.getKdfConfig();
|
||||
const kdfConfig: KdfConfig = await this.kdfConfigService.getKdfConfig();
|
||||
let userKey: UserKey;
|
||||
const email = await this.stateService.getEmail();
|
||||
if (oldPinKeyEncryptedMasterKey) {
|
||||
@@ -33,7 +33,6 @@ export class PinCryptoService implements PinCryptoServiceAbstraction {
|
||||
pinLockType === "TRANSIENT",
|
||||
pin,
|
||||
email,
|
||||
kdf,
|
||||
kdfConfig,
|
||||
oldPinKeyEncryptedMasterKey,
|
||||
);
|
||||
@@ -41,7 +40,6 @@ export class PinCryptoService implements PinCryptoServiceAbstraction {
|
||||
userKey = await this.cryptoService.decryptUserKeyWithPin(
|
||||
pin,
|
||||
email,
|
||||
kdf,
|
||||
kdfConfig,
|
||||
pinKeyEncryptedUserKey,
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/platform/enums";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
|
||||
import { PinCryptoService } from "./pin-crypto.service.implementation";
|
||||
|
||||
describe("PinCryptoService", () => {
|
||||
let pinCryptoService: PinCryptoService;
|
||||
|
||||
@@ -20,6 +22,7 @@ describe("PinCryptoService", () => {
|
||||
const cryptoService = mock<CryptoService>();
|
||||
const vaultTimeoutSettingsService = mock<VaultTimeoutSettingsService>();
|
||||
const logService = mock<LogService>();
|
||||
const kdfConfigService = mock<KdfConfigService>();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
@@ -29,6 +32,7 @@ describe("PinCryptoService", () => {
|
||||
cryptoService,
|
||||
vaultTimeoutSettingsService,
|
||||
logService,
|
||||
kdfConfigService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -39,7 +43,6 @@ describe("PinCryptoService", () => {
|
||||
describe("decryptUserKeyWithPin(...)", () => {
|
||||
const mockPin = "1234";
|
||||
const mockProtectedPin = "protectedPin";
|
||||
const DEFAULT_PBKDF2_ITERATIONS = 600000;
|
||||
const mockUserEmail = "user@example.com";
|
||||
const mockUserKey = new SymmetricCryptoKey(randomBytes(32)) as UserKey;
|
||||
|
||||
@@ -49,7 +52,7 @@ describe("PinCryptoService", () => {
|
||||
) {
|
||||
vaultTimeoutSettingsService.isPinLockSet.mockResolvedValue(pinLockType);
|
||||
|
||||
stateService.getKdfConfig.mockResolvedValue(new KdfConfig(DEFAULT_PBKDF2_ITERATIONS));
|
||||
kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG);
|
||||
stateService.getEmail.mockResolvedValue(mockUserEmail);
|
||||
|
||||
if (migrationStatus === "PRE") {
|
||||
|
||||
Reference in New Issue
Block a user