diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index ac625a961c0..4ea59b8de07 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -838,7 +838,7 @@ export default class MainBackground { this.accountService, this.kdfConfigService, this.keyService, - this.securityStateService, + this.accountCryptographicStateService, this.apiService, this.stateProvider, this.configService, diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index 645c429e393..662b58bd28a 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -653,7 +653,7 @@ export class ServiceContainer { this.accountService, this.kdfConfigService, this.keyService, - this.securityStateService, + this.accountCryptographicStateService, this.apiService, this.stateProvider, this.configService, diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index ca46dee0216..3a21d2b788f 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -1651,7 +1651,7 @@ const safeProviders: SafeProvider[] = [ AccountServiceAbstraction, KdfConfigService, KeyService, - SecurityStateService, + AccountCryptographicStateService, ApiServiceAbstraction, StateProvider, ConfigService, diff --git a/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts b/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts index fb9c1fae77e..164886ed5a7 100644 --- a/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts +++ b/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts @@ -1,7 +1,6 @@ import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject, firstValueFrom, of } from "rxjs"; -import { SecurityStateService } from "@bitwarden/common/key-management/security-state/abstractions/security-state.service"; // This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. // eslint-disable-next-line no-restricted-imports import { KdfConfigService, KeyService, PBKDF2KdfConfig } from "@bitwarden/key-management"; @@ -15,6 +14,7 @@ import { mockAccountInfoWith, } from "../../../../spec"; import { ApiService } from "../../../abstractions/api.service"; +import { AccountCryptographicStateService } from "../../../key-management/account-cryptography/account-cryptographic-state.service"; import { EncryptedString } from "../../../key-management/crypto/models/enc-string"; import { UserId } from "../../../types/guid"; import { UserKey } from "../../../types/key"; @@ -44,7 +44,7 @@ describe("DefaultSdkService", () => { let platformUtilsService!: MockProxy; let kdfConfigService!: MockProxy; let keyService!: MockProxy; - let securityStateService!: MockProxy; + let accountCryptographicStateService!: MockProxy; let configService!: MockProxy; let service!: DefaultSdkService; let accountService!: FakeAccountService; @@ -59,7 +59,7 @@ describe("DefaultSdkService", () => { platformUtilsService = mock(); kdfConfigService = mock(); keyService = mock(); - securityStateService = mock(); + accountCryptographicStateService = mock(); apiService = mock(); const mockUserId = Utils.newGuid() as UserId; accountService = mockAccountServiceWith(mockUserId); @@ -78,7 +78,7 @@ describe("DefaultSdkService", () => { accountService, kdfConfigService, keyService, - securityStateService, + accountCryptographicStateService, apiService, fakeStateProvider, configService, @@ -103,13 +103,16 @@ describe("DefaultSdkService", () => { keyService.userKey$ .calledWith(userId) .mockReturnValue(of(new SymmetricCryptoKey(new Uint8Array(64)) as UserKey)); - keyService.userEncryptedPrivateKey$ - .calledWith(userId) - .mockReturnValue(of("private-key" as EncryptedString)); keyService.encryptedOrgKeys$.calledWith(userId).mockReturnValue(of({})); - keyService.userSigningKey$.calledWith(userId).mockReturnValue(of(null)); - keyService.userSignedPublicKey$.calledWith(userId).mockReturnValue(of(null)); - securityStateService.accountSecurityState$.calledWith(userId).mockReturnValue(of(null)); + accountCryptographicStateService.accountCryptographicState$ + .calledWith(userId) + .mockReturnValue( + of({ + V1: { + private_key: "private-key" as EncryptedString, + }, + }), + ); }); describe("given no client override has been set for the user", () => { diff --git a/libs/common/src/platform/services/sdk/default-sdk.service.ts b/libs/common/src/platform/services/sdk/default-sdk.service.ts index 5084f5f5f18..a40f0c69fd6 100644 --- a/libs/common/src/platform/services/sdk/default-sdk.service.ts +++ b/libs/common/src/platform/services/sdk/default-sdk.service.ts @@ -30,8 +30,8 @@ import { import { ApiService } from "../../../abstractions/api.service"; import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service"; +import { AccountCryptographicStateService } from "../../../key-management/account-cryptography/account-cryptographic-state.service"; import { EncString } from "../../../key-management/crypto/models/enc-string"; -import { SecurityStateService } from "../../../key-management/security-state/abstractions/security-state.service"; import { OrganizationId, UserId } from "../../../types/guid"; import { Environment, EnvironmentService } from "../../abstractions/environment.service"; import { PlatformUtilsService } from "../../abstractions/platform-utils.service"; @@ -103,7 +103,7 @@ export class DefaultSdkService implements SdkService { private accountService: AccountService, private kdfConfigService: KdfConfigService, private keyService: KeyService, - private securityStateService: SecurityStateService, + private accountCryptographyStateService: AccountCryptographicStateService, private apiService: ApiService, private stateProvider: StateProvider, private configService: ConfigService, @@ -163,105 +163,70 @@ export class DefaultSdkService implements SdkService { distinctUntilChanged(), ); const kdfParams$ = this.kdfConfigService.getKdfConfig$(userId).pipe(distinctUntilChanged()); - const privateKey$ = this.keyService - .userEncryptedPrivateKey$(userId) + const accountCryptographicState$ = this.accountCryptographyStateService + .accountCryptographicState$(userId) .pipe(distinctUntilChanged()); - const signingKey$ = this.keyService.userSigningKey$(userId).pipe(distinctUntilChanged()); const userKey$ = this.keyService.userKey$(userId).pipe(distinctUntilChanged()); const orgKeys$ = this.keyService.encryptedOrgKeys$(userId).pipe( distinctUntilChanged(compareValues), // The upstream observable emits different objects with the same values ); - const securityState$ = this.securityStateService - .accountSecurityState$(userId) - .pipe(distinctUntilChanged(compareValues)); - const signedPublicKey$ = this.keyService - .userSignedPublicKey$(userId) - .pipe(distinctUntilChanged(compareValues)); const client$ = combineLatest([ this.environmentService.getEnvironment$(userId), account$, kdfParams$, - privateKey$, + accountCryptographicState$, userKey$, - signingKey$, orgKeys$, - securityState$, - signedPublicKey$, SdkLoadService.Ready, // Makes sure we wait (once) for the SDK to be loaded ]).pipe( // switchMap is required to allow the clean-up logic to be executed when `combineLatest` emits a new value. - switchMap( - ([ - env, - account, - kdfParams, - privateKey, - userKey, - signingKey, - orgKeys, - securityState, - signedPublicKey, - ]) => { - // Create our own observable to be able to implement clean-up logic - return new Observable>((subscriber) => { - const createAndInitializeClient = async () => { - if (env == null || kdfParams == null || privateKey == null || userKey == null) { - return undefined; - } + switchMap(([env, account, kdfParams, accountCryptographicState, userKey, orgKeys]) => { + // Create our own observable to be able to implement clean-up logic + return new Observable>((subscriber) => { + const createAndInitializeClient = async () => { + if ( + env == null || + kdfParams == null || + accountCryptographicState == null || + userKey == null + ) { + return undefined; + } - const settings = this.toSettings(env); - const client = await this.sdkClientFactory.createSdkClient( - new JsTokenProvider(this.apiService, userId), - settings, - ); + const settings = this.toSettings(env); + const client = await this.sdkClientFactory.createSdkClient( + new JsTokenProvider(this.apiService, userId), + settings, + ); - let accountCryptographicState: WrappedAccountCryptographicState; - if (signingKey != null && securityState != null && signedPublicKey != null) { - accountCryptographicState = { - V2: { - private_key: privateKey, - signing_key: signingKey, - security_state: securityState, - signed_public_key: signedPublicKey, - }, - }; - } else { - accountCryptographicState = { - V1: { - private_key: privateKey, - }, - }; - } + await this.initializeClient( + userId, + client, + account, + kdfParams, + userKey, + accountCryptographicState, + orgKeys, + ); - await this.initializeClient( - userId, - client, - account, - kdfParams, - userKey, - accountCryptographicState, - orgKeys, - ); + return client; + }; - return client; - }; + let client: Rc | undefined; + createAndInitializeClient() + .then((c) => { + client = c === undefined ? undefined : new Rc(c); - let client: Rc | undefined; - createAndInitializeClient() - .then((c) => { - client = c === undefined ? undefined : new Rc(c); + subscriber.next(client); + }) + .catch((e) => { + subscriber.error(e); + }); - subscriber.next(client); - }) - .catch((e) => { - subscriber.error(e); - }); - - return () => client?.markForDisposal(); - }); - }, - ), + return () => client?.markForDisposal(); + }); + }), tap({ finalize: () => this.sdkClientCache.delete(userId) }), shareReplay({ refCount: true, bufferSize: 1 }), );