mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
Auth/PM-5268 - DeviceTrustCryptoService state provider migration (#7882)
* PM-5268 - Add DEVICE_TRUST_DISK to state definitions * PM-5268 - DeviceTrustCryptoService - Get most of state provider refactor done - WIP - commented out stuff for now. * PM-5268 - DeviceTrustCryptoServiceStateProviderMigrator - WIP - got first draft of migrator in place and working on tests. Rollback tests are failing for some reason TBD. * PM-5268 - more WIP on device trust crypto service migrator tests * PM-5268 - DeviceTrustCryptoServiceStateProviderMigrator - Refactor based on call with platform * PM-5268 - DeviceTrustCryptoServiceStateProviderMigrator - tests passing * PM-5268 - Update DeviceTrustCryptoService to convert over to state providers + update all service instantiations / dependencies to ensure state provider is passed in or injected. * PM-5268 - Register new migration * PM-5268 - Temporarily remove device trust crypto service from migrator to ease merge conflicts as there are 6 more migrators before I can apply mine in main. * PM-5268 - Update migration numbers of DeviceTrustCryptoServiceStateProviderMigrator based on latest migrations from main. * PM-5268 - (1) Export new KeyDefinitions from DeviceTrustCryptoService for use in test suite (2) Update DeviceTrustCryptoService test file to use state provider. * PM-5268 - Fix DeviceTrustCryptoServiceStateProviderMigrator tests to use proper versions * PM-5268 - Actually fix all instances of DeviceTrustCryptoServiceStateProviderMigrator test failures * PM-5268 - Clean up state service, account, and login strategy of all migrated references * PM-5268 - Account - finish cleaning up device key * PM-5268 - StateService - clean up last reference to device key * PM-5268 - Remove even more device key refs. *facepalm* * PM-5268 - Finish resolving merge conflicts by incrementing migration version from 22 to 23 * PM-5268 - bump migration versions * PM-5268 - DeviceTrustCryptoService - Implement secure storage functionality for getDeviceKey and setDeviceKey (to achieve feature parity with the ElectronStateService implementation prior to the state provider migration). Tests to follow shortly. * PM-5268 - DeviceTrustCryptoService tests - getDeviceKey now tested with all new secure storage scenarios. SetDeviceKey tests to follow. * PM-5268 - DeviceTrustCryptoService tests - test all setDeviceKey scenarios with state provider & secure storage * PM-5268 - Update DeviceTrustCryptoService deps to actually use secure storage svc on platforms that support it. * PM-5268 - Bump migration version due to merge conflicts. * PM-5268 - Bump migration version * PM-5268 - tweak jsdocs to be single line per PR feedback * PM-5268 - DeviceTrustCryptoSvc - improve debuggability. * PM-5268 - Remove state service as a dependency on the device trust crypto service (woo!) * PM-5268 - Update migration test json to correctly reflect reality. * PM-5268 - DeviceTrustCryptoSvc - getDeviceKey - add throw error for active user id missing. * PM-5268 - Fix tests * PM-5268 - WIP start on adding user id to every method on device trust crypto service. * PM-5268 - Update lock comp dependencies across clients * PM-5268 - Update login via auth request deps across clients to add acct service. * PM-5268 - UserKeyRotationSvc - add acct service to get active acct id for call to rotateDevicesTrust and then update tests. * PM-5268 - WIP on trying to fix device trust crypto svc tests. * PM-5268 - More WIP device trust crypto svc tests passing * PM-5268 - Device Trust crypto service - get all tests passing * PM-5268 - DeviceTrustCryptoService.getDeviceKey - fix secure storage b64 to symmetric crypto key conversion * PM-5268 - Add more tests and update test names * PM-5268 - rename state to indicate it was disk local * PM-5268 - DeviceTrustCryptoService - save symmetric key in JSON format * PM-5268 - Fix lock comp tests by adding acct service dep * PM-5268 - Update set device key tests to pass * PM-5268 - Bump migration versions again * PM-5268 - Fix user key rotation svc tests * PM-5268 - Update web jest config to allow use of common spec in user-key-rotation-svc tests * PM-5268 - Bump migration version * PM-5268 - Per PR feedback, save off user id * PM-5268 - bump migration version * PM-5268 - Per PR feedback, remove unnecessary await. * PM-5268 - Bump migration verson
This commit is contained in:
@@ -16,6 +16,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 { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { InternalUserDecryptionOptionsServiceAbstraction } from "../abstractions/user-decryption-options.service.abstraction";
|
||||
import { AuthRequestLoginCredentials } from "../models/domain/login-credentials";
|
||||
@@ -128,8 +129,10 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
await this.cryptoService.setUserKey(authRequestCredentials.decryptedUserKey);
|
||||
} else {
|
||||
await this.trySetUserKeyWithMasterKey();
|
||||
|
||||
const userId = (await this.stateService.getUserId()) as UserId;
|
||||
// Establish trust if required after setting user key
|
||||
await this.deviceTrustCryptoService.trustDeviceIfRequired();
|
||||
await this.deviceTrustCryptoService.trustDeviceIfRequired(userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
PasswordStrengthService,
|
||||
} from "@bitwarden/common/tools/password-strength";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
import { UserKey, MasterKey, DeviceKey } from "@bitwarden/common/types/key";
|
||||
import { UserKey, MasterKey } from "@bitwarden/common/types/key";
|
||||
|
||||
import { LoginStrategyServiceAbstraction } from "../abstractions";
|
||||
import { InternalUserDecryptionOptionsServiceAbstraction } from "../abstractions/user-decryption-options.service.abstraction";
|
||||
@@ -215,29 +215,6 @@ describe("LoginStrategy", () => {
|
||||
expect(messagingService.send).toHaveBeenCalledWith("loggedIn");
|
||||
});
|
||||
|
||||
it("persists a device key for trusted device encryption when it exists on login", async () => {
|
||||
// Arrange
|
||||
const idTokenResponse = identityTokenResponseFactory();
|
||||
apiService.postIdentityToken.mockResolvedValue(idTokenResponse);
|
||||
|
||||
const deviceKey = new SymmetricCryptoKey(
|
||||
new Uint8Array(userKeyBytesLength).buffer as CsprngArray,
|
||||
) as DeviceKey;
|
||||
|
||||
stateService.getDeviceKey.mockResolvedValue(deviceKey);
|
||||
|
||||
const accountKeys = new AccountKeys();
|
||||
accountKeys.deviceKey = deviceKey;
|
||||
|
||||
// Act
|
||||
await passwordLoginStrategy.logIn(credentials);
|
||||
|
||||
// Assert
|
||||
expect(stateService.addAccount).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ keys: accountKeys }),
|
||||
);
|
||||
});
|
||||
|
||||
it("builds AuthResult", async () => {
|
||||
const tokenResponse = identityTokenResponseFactory();
|
||||
tokenResponse.forcePasswordReset = true;
|
||||
|
||||
@@ -26,7 +26,6 @@ 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 {
|
||||
AccountKeys,
|
||||
Account,
|
||||
AccountProfile,
|
||||
AccountTokens,
|
||||
@@ -160,18 +159,8 @@ export abstract class LoginStrategy {
|
||||
protected async saveAccountInformation(tokenResponse: IdentityTokenResponse): Promise<void> {
|
||||
const accountInformation = await this.tokenService.decodeAccessToken(tokenResponse.accessToken);
|
||||
|
||||
// Must persist existing device key if it exists for trusted device decryption to work
|
||||
// However, we must provide a user id so that the device key can be retrieved
|
||||
// as the state service won't have an active account at this point in time
|
||||
// even though the data exists in local storage.
|
||||
const userId = accountInformation.sub;
|
||||
|
||||
const deviceKey = await this.stateService.getDeviceKey({ userId });
|
||||
const accountKeys = new AccountKeys();
|
||||
if (deviceKey) {
|
||||
accountKeys.deviceKey = deviceKey;
|
||||
}
|
||||
|
||||
// If you don't persist existing admin auth requests on login, they will get deleted.
|
||||
const adminAuthRequest = await this.stateService.getAdminAuthRequest({ userId });
|
||||
|
||||
@@ -204,7 +193,6 @@ export abstract class LoginStrategy {
|
||||
tokens: {
|
||||
...new AccountTokens(),
|
||||
},
|
||||
keys: accountKeys,
|
||||
adminAuthRequest: adminAuthRequest?.toJSON(),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -20,6 +20,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 { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import {
|
||||
InternalUserDecryptionOptionsServiceAbstraction,
|
||||
@@ -284,7 +285,8 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
if (await this.cryptoService.hasUserKey()) {
|
||||
// Now that we have a decrypted user key in memory, we can check if we
|
||||
// need to establish trust on the current device
|
||||
await this.deviceTrustCryptoService.trustDeviceIfRequired();
|
||||
const userId = (await this.stateService.getUserId()) as UserId;
|
||||
await this.deviceTrustCryptoService.trustDeviceIfRequired(userId);
|
||||
|
||||
// if we successfully decrypted the user key, we can delete the admin auth request out of state
|
||||
// TODO: eventually we post and clean up DB as well once consumed on client
|
||||
@@ -298,7 +300,9 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
private async trySetUserKeyWithDeviceKey(tokenResponse: IdentityTokenResponse): Promise<void> {
|
||||
const trustedDeviceOption = tokenResponse.userDecryptionOptions?.trustedDeviceOption;
|
||||
|
||||
const deviceKey = await this.deviceTrustCryptoService.getDeviceKey();
|
||||
const userId = (await this.stateService.getUserId()) as UserId;
|
||||
|
||||
const deviceKey = await this.deviceTrustCryptoService.getDeviceKey(userId);
|
||||
const encDevicePrivateKey = trustedDeviceOption?.encryptedPrivateKey;
|
||||
const encUserKey = trustedDeviceOption?.encryptedUserKey;
|
||||
|
||||
@@ -307,6 +311,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
|
||||
const userKey = await this.deviceTrustCryptoService.decryptUserKeyWithDeviceKey(
|
||||
userId,
|
||||
encDevicePrivateKey,
|
||||
encUserKey,
|
||||
deviceKey,
|
||||
|
||||
Reference in New Issue
Block a user