Skip to content

Commit

Permalink
Specify clearOn options for platform services (#8584)
Browse files Browse the repository at this point in the history
* Use UserKeys in biometric state

* Remove global clear todo. Answer is never

* User UserKeys in crypto state

* Clear userkey on both lock and logout via User Key Definitions

* Use UserKeyDefinitions in environment service

* Rely on userKeyDefinition to clear org keys

* Rely on userKeyDefinition to clear provider keys

* Rely on userKeyDefinition to clear user keys

* Rely on userKeyDefinitions to clear user asym key pair
  • Loading branch information
MGibson1 authored Apr 9, 2024
1 parent aefea43 commit c02723d
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 364 deletions.
8 changes: 2 additions & 6 deletions libs/common/spec/fake-account-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,8 @@ export class FakeAccountService implements AccountService {
get activeUserId() {
return this._activeUserId;
}
get accounts$() {
return this.accountsSubject.asObservable();
}
get activeAccount$() {
return this.activeAccountSubject.asObservable();
}
accounts$ = this.accountsSubject.asObservable();
activeAccount$ = this.activeAccountSubject.asObservable();
accountLock$: Observable<UserId>;
accountLogout$: Observable<UserId>;

Expand Down
26 changes: 1 addition & 25 deletions libs/common/src/platform/abstractions/crypto.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export abstract class CryptoService {
* any other necessary versions (such as auto, biometrics,
* or pin)
*
* @throws when key is null. Use {@link clearUserKey} instead
* @throws when key is null. Lock the account to clear a key
* @param key The user key to set
* @param userId The desired user
*/
Expand Down Expand Up @@ -93,13 +93,6 @@ export abstract class CryptoService {
* @returns A new user key and the master key protected version of it
*/
abstract makeUserKey(key: MasterKey): Promise<[UserKey, EncString]>;
/**
* Clears the user key
* @param clearStoredKeys Clears all stored versions of the user keys as well,
* such as the biometrics key
* @param userId The desired user
*/
abstract clearUserKey(clearSecretStorage?: boolean, userId?: string): Promise<void>;
/**
* Clears the user's stored version of the user key
* @param keySuffix The desired version of the key to clear
Expand Down Expand Up @@ -238,12 +231,6 @@ export abstract class CryptoService {
abstract makeDataEncKey<T extends UserKey | OrgKey>(
key: T,
): Promise<[SymmetricCryptoKey, EncString]>;
/**
* Clears the user's stored organization keys
* @param memoryOnly Clear only the in-memory keys
* @param userId The desired user
*/
abstract clearOrgKeys(memoryOnly?: boolean, userId?: string): Promise<void>;
/**
* Stores the encrypted provider keys and clears any decrypted
* provider keys currently in memory
Expand All @@ -260,11 +247,6 @@ export abstract class CryptoService {
* @returns A record of the provider Ids to their symmetric keys
*/
abstract getProviderKeys(): Promise<Record<ProviderId, ProviderKey>>;
/**
* @param memoryOnly Clear only the in-memory keys
* @param userId The desired user
*/
abstract clearProviderKeys(memoryOnly?: boolean, userId?: string): Promise<void>;
/**
* Returns the public key from memory. If not available, extracts it
* from the private key and stores it in memory
Expand Down Expand Up @@ -304,12 +286,6 @@ export abstract class CryptoService {
* @returns A new keypair: [publicKey in Base64, encrypted privateKey]
*/
abstract makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]>;
/**
* Clears the user's key pair
* @param memoryOnly Clear only the in-memory keys
* @param userId The desired user
*/
abstract clearKeyPair(memoryOnly?: boolean, userId?: string): Promise<void[]>;
/**
* @param pin The user's pin
* @param salt The user's salt
Expand Down
12 changes: 9 additions & 3 deletions libs/common/src/platform/biometrics/biometric.state.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EncryptedString } from "../models/domain/enc-string";
import { KeyDefinition } from "../state";
import { KeyDefinition, UserKeyDefinition } from "../state";

import {
BIOMETRIC_UNLOCK_ENABLED,
Expand All @@ -22,9 +22,15 @@ describe.each([
])(
"deserializes state %s",
(
...args: [KeyDefinition<EncryptedString>, EncryptedString] | [KeyDefinition<boolean>, boolean]
...args:
| [UserKeyDefinition<EncryptedString>, EncryptedString]
| [UserKeyDefinition<boolean>, boolean]
| [KeyDefinition<boolean>, boolean]
) => {
function testDeserialization<T>(keyDefinition: KeyDefinition<T>, state: T) {
function testDeserialization<T>(
keyDefinition: UserKeyDefinition<T> | KeyDefinition<T>,
state: T,
) {
const deserialized = keyDefinition.deserializer(JSON.parse(JSON.stringify(state)));
expect(deserialized).toEqual(state);
}
Expand Down
17 changes: 11 additions & 6 deletions libs/common/src/platform/biometrics/biometric.state.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { UserId } from "../../types/guid";
import { EncryptedString } from "../models/domain/enc-string";
import { KeyDefinition, BIOMETRIC_SETTINGS_DISK } from "../state";
import { KeyDefinition, BIOMETRIC_SETTINGS_DISK, UserKeyDefinition } from "../state";

/**
* Indicates whether the user elected to store a biometric key to unlock their vault.
*/
export const BIOMETRIC_UNLOCK_ENABLED = new KeyDefinition<boolean>(
export const BIOMETRIC_UNLOCK_ENABLED = new UserKeyDefinition<boolean>(
BIOMETRIC_SETTINGS_DISK,
"biometricUnlockEnabled",
{
deserializer: (obj) => obj,
clearOn: [],
},
);

Expand All @@ -18,11 +19,12 @@ export const BIOMETRIC_UNLOCK_ENABLED = new KeyDefinition<boolean>(
*
* A true setting controls whether {@link ENCRYPTED_CLIENT_KEY_HALF} is set.
*/
export const REQUIRE_PASSWORD_ON_START = new KeyDefinition<boolean>(
export const REQUIRE_PASSWORD_ON_START = new UserKeyDefinition<boolean>(
BIOMETRIC_SETTINGS_DISK,
"requirePasswordOnStart",
{
deserializer: (value) => value,
clearOn: [],
},
);

Expand All @@ -33,23 +35,25 @@ export const REQUIRE_PASSWORD_ON_START = new KeyDefinition<boolean>(
* For operating systems without application-level key storage, this key half is concatenated with a signature
* provided by the OS and used to encrypt the biometric key prior to storage.
*/
export const ENCRYPTED_CLIENT_KEY_HALF = new KeyDefinition<EncryptedString>(
export const ENCRYPTED_CLIENT_KEY_HALF = new UserKeyDefinition<EncryptedString>(
BIOMETRIC_SETTINGS_DISK,
"clientKeyHalf",
{
deserializer: (obj) => obj,
clearOn: ["logout"],
},
);

/**
* Indicates the user has been warned about the security implications of using biometrics and, depending on the OS,
* recommended to require a password on first unlock of an application instance.
*/
export const DISMISSED_REQUIRE_PASSWORD_ON_START_CALLOUT = new KeyDefinition<boolean>(
export const DISMISSED_REQUIRE_PASSWORD_ON_START_CALLOUT = new UserKeyDefinition<boolean>(
BIOMETRIC_SETTINGS_DISK,
"dismissedBiometricRequirePasswordOnStartCallout",
{
deserializer: (obj) => obj,
clearOn: [],
},
);

Expand All @@ -68,11 +72,12 @@ export const PROMPT_CANCELLED = KeyDefinition.record<boolean, UserId>(
/**
* Stores whether the user has elected to automatically prompt for biometric unlock on application start.
*/
export const PROMPT_AUTOMATICALLY = new KeyDefinition<boolean>(
export const PROMPT_AUTOMATICALLY = new UserKeyDefinition<boolean>(
BIOMETRIC_SETTINGS_DISK,
"promptAutomatically",
{
deserializer: (obj) => obj,
clearOn: [],
},
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export const USER_SERVER_CONFIG = new UserKeyDefinition<ServerConfig>(CONFIG_DIS
clearOn: ["logout"],
});

// TODO MDG: When to clean these up?
export const GLOBAL_SERVER_CONFIGURATIONS = KeyDefinition.record<ServerConfig, ApiUrl>(
CONFIG_DISK,
"byServer",
Expand Down
Loading

0 comments on commit c02723d

Please sign in to comment.