mirror of
https://github.com/bitwarden/browser
synced 2026-03-01 11:01:17 +00:00
[PM-29208] Remove individual cryptographic-key states & migrate key service (#18164)
* Remove inividual user key states and migrate to account cryptographic state * Fix browser * Fix tests * Clean up migration * Remove key-pair creation from login strategy * Add clearing for the account cryptographic state * Add migration * Cleanup * Fix linting
This commit is contained in:
committed by
jaasen-livefront
parent
d718cf6cda
commit
89c9200552
@@ -278,13 +278,6 @@ describe("LoginDecryptionOptionsComponent", () => {
|
||||
const expectedUserKey = new SymmetricCryptoKey(new Uint8Array(mockUserKeyBytes));
|
||||
|
||||
// Verify keys were set
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(mockPrivateKey, mockUserId);
|
||||
expect(keyService.setSignedPublicKey).toHaveBeenCalledWith(mockSignedPublicKey, mockUserId);
|
||||
expect(keyService.setUserSigningKey).toHaveBeenCalledWith(mockSigningKey, mockUserId);
|
||||
expect(securityStateService.setAccountSecurityState).toHaveBeenCalledWith(
|
||||
mockSecurityState,
|
||||
mockUserId,
|
||||
);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
V2: {
|
||||
|
||||
@@ -34,11 +34,6 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { AccountCryptographicStateService } from "@bitwarden/common/key-management/account-cryptography/account-cryptographic-state.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction";
|
||||
import { SecurityStateService } from "@bitwarden/common/key-management/security-state/abstractions/security-state.service";
|
||||
import {
|
||||
SignedPublicKey,
|
||||
SignedSecurityState,
|
||||
WrappedSigningKey,
|
||||
} from "@bitwarden/common/key-management/types";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -322,23 +317,6 @@ export class LoginDecryptionOptionsComponent implements OnInit {
|
||||
register_result.account_cryptographic_state,
|
||||
userId,
|
||||
);
|
||||
// Legacy individual states
|
||||
await this.keyService.setPrivateKey(
|
||||
register_result.account_cryptographic_state.V2.private_key,
|
||||
userId,
|
||||
);
|
||||
await this.keyService.setSignedPublicKey(
|
||||
register_result.account_cryptographic_state.V2.signed_public_key as SignedPublicKey,
|
||||
userId,
|
||||
);
|
||||
await this.keyService.setUserSigningKey(
|
||||
register_result.account_cryptographic_state.V2.signing_key as WrappedSigningKey,
|
||||
userId,
|
||||
);
|
||||
await this.securityStateService.setAccountSecurityState(
|
||||
register_result.account_cryptographic_state.V2.security_state as SignedSecurityState,
|
||||
userId,
|
||||
);
|
||||
|
||||
// TDE unlock
|
||||
await this.deviceTrustService.setDeviceKey(
|
||||
|
||||
@@ -180,7 +180,10 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, mockUserId);
|
||||
expect(deviceTrustService.trustDeviceIfRequired).toHaveBeenCalled();
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, mockUserId);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
{ V1: { private_key: tokenResponse.privateKey } },
|
||||
mockUserId,
|
||||
);
|
||||
});
|
||||
|
||||
it("sets keys after a successful authentication when only userKey provided in login credentials", async () => {
|
||||
@@ -207,7 +210,10 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
mockUserId,
|
||||
);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(decUserKey, mockUserId);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, mockUserId);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
{ V1: { private_key: tokenResponse.privateKey } },
|
||||
mockUserId,
|
||||
);
|
||||
|
||||
// trustDeviceIfRequired should be called
|
||||
expect(deviceTrustService.trustDeviceIfRequired).not.toHaveBeenCalled();
|
||||
|
||||
@@ -120,20 +120,14 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(
|
||||
protected override async setAccountCryptographicState(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.keyService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
if (response.accountKeysResponseModel) {
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exportCache(): CacheData {
|
||||
|
||||
@@ -19,7 +19,6 @@ import { TwoFactorService } from "@bitwarden/common/auth/two-factor";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { AccountCryptographicStateService } from "@bitwarden/common/key-management/account-cryptography/account-cryptographic-state.service";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { FakeMasterPasswordService } from "@bitwarden/common/key-management/master-password/services/fake-master-password.service";
|
||||
import {
|
||||
MasterKeyWrappedUserKey,
|
||||
@@ -38,15 +37,12 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import {
|
||||
PasswordStrengthServiceAbstraction,
|
||||
PasswordStrengthService,
|
||||
} from "@bitwarden/common/tools/password-strength";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { UserKey, MasterKey } from "@bitwarden/common/types/key";
|
||||
import { KdfConfigService, KeyService, PBKDF2KdfConfig } from "@bitwarden/key-management";
|
||||
|
||||
import { LoginStrategyServiceAbstraction } from "../abstractions";
|
||||
@@ -109,6 +105,12 @@ export function identityTokenResponseFactory(
|
||||
token_type: "Bearer",
|
||||
MasterPasswordPolicy: masterPasswordPolicyResponse,
|
||||
UserDecryptionOptions: userDecryptionOptions || defaultUserDecryptionOptionsServerResponse,
|
||||
AccountKeys: {
|
||||
publicKeyEncryptionKeyPair: {
|
||||
wrappedPrivateKey: privateKey,
|
||||
publicKey: "PUBLIC_KEY",
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -201,19 +203,7 @@ describe("LoginStrategy", () => {
|
||||
});
|
||||
|
||||
describe("base class", () => {
|
||||
const userKeyBytesLength = 64;
|
||||
const masterKeyBytesLength = 64;
|
||||
let userKey: UserKey;
|
||||
let masterKey: MasterKey;
|
||||
|
||||
beforeEach(() => {
|
||||
userKey = new SymmetricCryptoKey(
|
||||
new Uint8Array(userKeyBytesLength).buffer as CsprngArray,
|
||||
) as UserKey;
|
||||
masterKey = new SymmetricCryptoKey(
|
||||
new Uint8Array(masterKeyBytesLength).buffer as CsprngArray,
|
||||
) as MasterKey;
|
||||
|
||||
const mockVaultTimeoutAction = VaultTimeoutAction.Lock;
|
||||
const mockVaultTimeoutActionBSub = new BehaviorSubject<VaultTimeoutAction>(
|
||||
mockVaultTimeoutAction,
|
||||
@@ -335,39 +325,6 @@ describe("LoginStrategy", () => {
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
it("makes a new public and private key for an old account", async () => {
|
||||
const tokenResponse = identityTokenResponseFactory();
|
||||
tokenResponse.privateKey = null;
|
||||
keyService.makeKeyPair.mockResolvedValue(["PUBLIC_KEY", new EncString("PRIVATE_KEY")]);
|
||||
keyService.userKey$.mockReturnValue(new BehaviorSubject<UserKey>(userKey).asObservable());
|
||||
|
||||
apiService.postIdentityToken.mockResolvedValue(tokenResponse);
|
||||
masterPasswordService.masterKeySubject.next(masterKey);
|
||||
masterPasswordService.mock.decryptUserKeyWithMasterKey.mockResolvedValue(userKey);
|
||||
|
||||
await passwordLoginStrategy.logIn(credentials);
|
||||
|
||||
// User symmetric key must be set before the new RSA keypair is generated
|
||||
expect(keyService.setUserKey).toHaveBeenCalled();
|
||||
expect(keyService.makeKeyPair).toHaveBeenCalled();
|
||||
expect(keyService.setUserKey.mock.invocationCallOrder[0]).toBeLessThan(
|
||||
keyService.makeKeyPair.mock.invocationCallOrder[0],
|
||||
);
|
||||
|
||||
expect(apiService.postAccountKeys).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("throws if userKey is CoseEncrypt0 (V2 encryption) in createKeyPairForOldAccount", async () => {
|
||||
keyService.userKey$.mockReturnValue(
|
||||
new BehaviorSubject<UserKey>({
|
||||
inner: () => ({ type: 7 }),
|
||||
} as unknown as UserKey).asObservable(),
|
||||
);
|
||||
await expect(passwordLoginStrategy["createKeyPairForOldAccount"](userId)).resolves.toBe(
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Two-factor authentication", () => {
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
VaultTimeoutAction,
|
||||
VaultTimeoutSettingsService,
|
||||
} from "@bitwarden/common/key-management/vault-timeout";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
@@ -33,7 +32,6 @@ 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 { EncryptionType } from "@bitwarden/common/platform/enums";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { KeyService, KdfConfigService } from "@bitwarden/key-management";
|
||||
|
||||
@@ -265,7 +263,7 @@ export abstract class LoginStrategy {
|
||||
|
||||
await this.setMasterKey(response, userId);
|
||||
await this.setUserKey(response, userId);
|
||||
await this.setPrivateKey(response, userId);
|
||||
await this.setAccountCryptographicState(response, userId);
|
||||
|
||||
// This needs to run after the keys are set because it checks for the existence of the encrypted private key
|
||||
await this.processForceSetPasswordReason(response.forcePasswordReset, userId);
|
||||
@@ -283,7 +281,10 @@ export abstract class LoginStrategy {
|
||||
|
||||
protected abstract setUserKey(response: IdentityTokenResponse, userId: UserId): Promise<void>;
|
||||
|
||||
protected abstract setPrivateKey(response: IdentityTokenResponse, userId: UserId): Promise<void>;
|
||||
protected abstract setAccountCryptographicState(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void>;
|
||||
|
||||
// Old accounts used master key for encryption. We are forcing migrations but only need to
|
||||
// check on password logins
|
||||
@@ -315,28 +316,6 @@ export abstract class LoginStrategy {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async createKeyPairForOldAccount(userId: UserId) {
|
||||
try {
|
||||
const userKey = await firstValueFrom(this.keyService.userKey$(userId));
|
||||
if (userKey === null) {
|
||||
throw new Error("User key is null when creating key pair for old account");
|
||||
}
|
||||
|
||||
if (userKey.inner().type == EncryptionType.CoseEncrypt0) {
|
||||
throw new Error("Cannot create key pair for account on V2 encryption");
|
||||
}
|
||||
|
||||
const [publicKey, privateKey] = await this.keyService.makeKeyPair(userKey);
|
||||
if (!privateKey.encryptedString) {
|
||||
throw new Error("Failed to create encrypted private key");
|
||||
}
|
||||
await this.apiService.postAccountKeys(new KeysRequest(publicKey, privateKey.encryptedString));
|
||||
return privateKey.encryptedString;
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the response from the server when a 2FA is required.
|
||||
* It clears any existing 2FA token, as it's no longer valid, and sets up the necessary data for the 2FA process.
|
||||
|
||||
@@ -216,7 +216,10 @@ describe("PasswordLoginStrategy", () => {
|
||||
userId,
|
||||
);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
{ V1: { private_key: tokenResponse.privateKey } },
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not force the user to update their master password when there are no requirements", async () => {
|
||||
|
||||
@@ -148,20 +148,14 @@ export class PasswordLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(
|
||||
protected override async setAccountCryptographicState(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.keyService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
if (response.accountKeysResponseModel) {
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected override encryptionKeyMigrationRequired(response: IdentityTokenResponse): boolean {
|
||||
|
||||
@@ -196,13 +196,14 @@ describe("SsoLoginStrategy", () => {
|
||||
const tokenResponse = identityTokenResponseFactory();
|
||||
tokenResponse.key = null;
|
||||
tokenResponse.privateKey = null;
|
||||
tokenResponse.accountKeysResponseModel = null;
|
||||
apiService.postIdentityToken.mockResolvedValue(tokenResponse);
|
||||
|
||||
await ssoLoginStrategy.logIn(credentials);
|
||||
|
||||
expect(masterPasswordService.mock.setMasterKey).not.toHaveBeenCalled();
|
||||
expect(keyService.setUserKey).not.toHaveBeenCalled();
|
||||
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets master key encrypted user key for existing SSO users", async () => {
|
||||
|
||||
@@ -335,7 +335,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
await this.keyService.setUserKey(userKey, userId);
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(
|
||||
protected override async setAccountCryptographicState(
|
||||
tokenResponse: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
@@ -345,20 +345,6 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
if (tokenResponse.hasMasterKeyEncryptedUserKey()) {
|
||||
// User has masterKeyEncryptedUserKey, so set the userKeyEncryptedPrivateKey
|
||||
// Note: new JIT provisioned SSO users will not yet have a user asymmetric key pair
|
||||
// and so we don't want them falling into the createKeyPairForOldAccount flow
|
||||
await this.keyService.setPrivateKey(
|
||||
tokenResponse.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
} else if (tokenResponse.privateKey) {
|
||||
// User doesn't have masterKeyEncryptedUserKey but they do have a userKeyEncryptedPrivateKey
|
||||
// This is just existing TDE users or a TDE offboarder on an untrusted device
|
||||
await this.keyService.setPrivateKey(tokenResponse.privateKey, userId);
|
||||
}
|
||||
}
|
||||
|
||||
exportCache(): CacheData {
|
||||
|
||||
@@ -188,7 +188,10 @@ describe("UserApiLoginStrategy", () => {
|
||||
tokenResponse.key,
|
||||
userId,
|
||||
);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
{ V1: { private_key: tokenResponse.privateKey } },
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
it("gets and sets the master key if Key Connector is enabled", async () => {
|
||||
|
||||
@@ -79,20 +79,14 @@ export class UserApiLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(
|
||||
protected override async setAccountCryptographicState(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.keyService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
if (response.accountKeysResponseModel) {
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Overridden to save client ID and secret to token service
|
||||
|
||||
@@ -263,7 +263,10 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
mockPrfPrivateKey,
|
||||
);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(mockUserKey, userId);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(idTokenResponse.privateKey, userId);
|
||||
expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith(
|
||||
{ V1: { private_key: idTokenResponse.privateKey } },
|
||||
userId,
|
||||
);
|
||||
|
||||
// Master key and private key should not be set
|
||||
expect(masterPasswordService.mock.setMasterKey).not.toHaveBeenCalled();
|
||||
|
||||
@@ -100,20 +100,14 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(
|
||||
protected override async setAccountCryptographicState(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.keyService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
if (response.accountKeysResponseModel) {
|
||||
await this.accountCryptographicStateService.setAccountCryptographicState(
|
||||
response.accountKeysResponseModel.toWrappedAccountCryptographicState(),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exportCache(): CacheData {
|
||||
|
||||
@@ -495,6 +495,12 @@ describe("LoginStrategyService", () => {
|
||||
KdfParallelism: 1,
|
||||
Key: "KEY",
|
||||
PrivateKey: "PRIVATE_KEY",
|
||||
AccountKeys: {
|
||||
publicKeyEncryptionKeyPair: {
|
||||
wrappedPrivateKey: "PRIVATE_KEY",
|
||||
publicKey: "PUBLIC_KEY",
|
||||
},
|
||||
},
|
||||
access_token: "ACCESS_TOKEN",
|
||||
expires_in: 3600,
|
||||
refresh_token: "REFRESH_TOKEN",
|
||||
@@ -562,6 +568,12 @@ describe("LoginStrategyService", () => {
|
||||
KdfParallelism: 1,
|
||||
Key: "KEY",
|
||||
PrivateKey: "PRIVATE_KEY",
|
||||
AccountKeys: {
|
||||
publicKeyEncryptionKeyPair: {
|
||||
wrappedPrivateKey: "PRIVATE_KEY",
|
||||
publicKey: "PUBLIC_KEY",
|
||||
},
|
||||
},
|
||||
access_token: "ACCESS_TOKEN",
|
||||
expires_in: 3600,
|
||||
refresh_token: "REFRESH_TOKEN",
|
||||
@@ -627,6 +639,12 @@ describe("LoginStrategyService", () => {
|
||||
KdfIterations: PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1,
|
||||
Key: "KEY",
|
||||
PrivateKey: "PRIVATE_KEY",
|
||||
AccountKeys: {
|
||||
publicKeyEncryptionKeyPair: {
|
||||
wrappedPrivateKey: "PRIVATE_KEY",
|
||||
publicKey: "PUBLIC_KEY",
|
||||
},
|
||||
},
|
||||
access_token: "ACCESS_TOKEN",
|
||||
expires_in: 3600,
|
||||
refresh_token: "REFRESH_TOKEN",
|
||||
@@ -690,6 +708,12 @@ describe("LoginStrategyService", () => {
|
||||
KdfParallelism: 1,
|
||||
Key: "KEY",
|
||||
PrivateKey: "PRIVATE_KEY",
|
||||
AccountKeys: {
|
||||
publicKeyEncryptionKeyPair: {
|
||||
wrappedPrivateKey: "PRIVATE_KEY",
|
||||
publicKey: "PUBLIC_KEY",
|
||||
},
|
||||
},
|
||||
access_token: "ACCESS_TOKEN",
|
||||
expires_in: 3600,
|
||||
refresh_token: "REFRESH_TOKEN",
|
||||
|
||||
Reference in New Issue
Block a user