1
0
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:
Jared Snider
2024-04-01 16:02:58 -04:00
committed by GitHub
parent 94843bdd8b
commit c202c93378
32 changed files with 738 additions and 334 deletions

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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(),
}),
);

View File

@@ -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,