Set user ever had user key and add comment

pull/20004/head
Bernd Schoolmann 2 weeks ago
parent 8f1cd1efaa
commit f494037c34
No known key found for this signature in database

@ -2,6 +2,17 @@ import { UserKey } from "../../../types/key";
import { SymmetricCryptoKey } from "../../models/domain/symmetric-crypto-key";
import { CRYPTO_DISK, CRYPTO_MEMORY, UserKeyDefinition } from "../../state";
/**
* Ever had user key is a hack that allows differentiating TDE users that
* have logged and unlocked in at least once fully, from ones that have not.
* Depending on this, routing happens to the login-initiated or lock component.
* The former allows trusting the device, and has master password (if available)
* or trusted-device / admin approval as unlock methods. The latter has regular
* lock methods.
*
* Ideally, this state hack would be replaced by a more robust solution that just
* checks the available unlock methods, and routes depending on those.
*/
export const USER_EVER_HAD_USER_KEY = new UserKeyDefinition<boolean>(
CRYPTO_DISK,
"everHadUserKey",

@ -23,6 +23,8 @@ import { LogService } from "@bitwarden/logging";
import { PureCrypto } from "@bitwarden/sdk-internal";
import { StateProvider, StateService } from "@bitwarden/state";
import { USER_EVER_HAD_USER_KEY } from "@bitwarden/common/platform/services/key-state/user-key.state";
import { DefaultUnlockService } from "./default-unlock.service";
const mockUserId = "b1e2d3c4-a1b2-c3d4-e5f6-a1b2c3d4e5f6" as UserId;
@ -106,6 +108,7 @@ describe("DefaultUnlockService", () => {
const mockStateUpdate = jest.fn().mockResolvedValue(undefined);
stateProvider.getUser.mockReturnValue({ update: mockStateUpdate } as any);
stateProvider.setUserState.mockResolvedValue(undefined);
service = new DefaultUnlockService(
registerSdkService,
@ -180,6 +183,11 @@ describe("DefaultUnlockService", () => {
expect(stateService.setUserKeyAutoUnlock).toHaveBeenCalledWith(userEncryptionKey.toBase64(), {
userId: mockUserId,
});
expect(stateProvider.setUserState).toHaveBeenCalledWith(
USER_EVER_HAD_USER_KEY,
true,
mockUserId,
);
});
});
@ -208,6 +216,26 @@ describe("DefaultUnlockService", () => {
service.unlockWithMasterPassword(mockUserId, mockMasterPassword),
).rejects.toThrow("SDK not available");
});
it("sets unlock side effects after successful unlock", async () => {
const userEncryptionKey = new SymmetricCryptoKey(new Uint8Array(64) as CsprngArray);
mockCrypto.get_user_encryption_key.mockResolvedValue(userEncryptionKey.toBase64());
await service.unlockWithMasterPassword(mockUserId, mockMasterPassword);
expect(biometricsService.setBiometricProtectedUnlockKeyForUser).toHaveBeenCalledWith(
mockUserId,
expect.any(SymmetricCryptoKey),
);
expect(stateService.setUserKeyAutoUnlock).toHaveBeenCalledWith(userEncryptionKey.toBase64(), {
userId: mockUserId,
});
expect(stateProvider.setUserState).toHaveBeenCalledWith(
USER_EVER_HAD_USER_KEY,
true,
mockUserId,
);
});
});
describe("unlockWithBiometrics", () => {
@ -246,5 +274,24 @@ describe("DefaultUnlockService", () => {
await expect(service.unlockWithBiometrics(mockUserId)).rejects.toThrow("SDK not available");
});
});
});
it("sets unlock side effects after successful unlock", async () => {
biometricsService.unlockWithBiometricsForUser.mockResolvedValue(mockUserKey);
const userEncryptionKey = new SymmetricCryptoKey(new Uint8Array(64) as CsprngArray);
mockCrypto.get_user_encryption_key.mockResolvedValue(userEncryptionKey.toBase64());
await service.unlockWithBiometrics(mockUserId);
expect(biometricsService.setBiometricProtectedUnlockKeyForUser).toHaveBeenCalledWith(
mockUserId,
expect.any(SymmetricCryptoKey),
);
expect(stateService.setUserKeyAutoUnlock).toHaveBeenCalledWith(userEncryptionKey.toBase64(), {
userId: mockUserId,
});
expect(stateProvider.setUserState).toHaveBeenCalledWith(
USER_EVER_HAD_USER_KEY,
true,
mockUserId,
);
});

@ -37,6 +37,7 @@ import { StateProvider, StateService } from "@bitwarden/state";
import { UserId } from "@bitwarden/user-core";
import { UnlockService } from "./unlock.service";
import { USER_EVER_HAD_USER_KEY } from "@bitwarden/common/platform/services/key-state/user-key.state";
export class DefaultUnlockService implements UnlockService {
constructor(
@ -251,6 +252,7 @@ export class DefaultUnlockService implements UnlockService {
if (await this.shouldStoreSessionKey(userId)) {
await this.stateService.setUserKeyAutoUnlock(userKey.toBase64(), { userId: userId });
}
await this.stateProvider.setUserState(USER_EVER_HAD_USER_KEY, true, userId);
}
private async shouldStoreSessionKey(userId: UserId): Promise<boolean> {

Loading…
Cancel
Save