mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +00:00
[PM-25131] Initialize provider keys on the SDK (#16183)
* [PM-25131] Initialize provider keys on the SDK * Remove null default * Typechecking
This commit is contained in:
@@ -27,10 +27,9 @@ import {
|
|||||||
UnsignedSharedKey,
|
UnsignedSharedKey,
|
||||||
} from "@bitwarden/sdk-internal";
|
} from "@bitwarden/sdk-internal";
|
||||||
|
|
||||||
import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data";
|
|
||||||
import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service";
|
import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service";
|
||||||
import { DeviceType } from "../../../enums/device-type.enum";
|
import { DeviceType } from "../../../enums/device-type.enum";
|
||||||
import { EncryptedString } from "../../../key-management/crypto/models/enc-string";
|
import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string";
|
||||||
import { OrganizationId, UserId } from "../../../types/guid";
|
import { OrganizationId, UserId } from "../../../types/guid";
|
||||||
import { UserKey } from "../../../types/key";
|
import { UserKey } from "../../../types/key";
|
||||||
import { Environment, EnvironmentService } from "../../abstractions/environment.service";
|
import { Environment, EnvironmentService } from "../../abstractions/environment.service";
|
||||||
@@ -220,7 +219,7 @@ export class DefaultSdkService implements SdkService {
|
|||||||
kdfParams: KdfConfig,
|
kdfParams: KdfConfig,
|
||||||
privateKey: EncryptedString,
|
privateKey: EncryptedString,
|
||||||
userKey: UserKey,
|
userKey: UserKey,
|
||||||
orgKeys: Record<OrganizationId, EncryptedOrganizationKeyData> | null,
|
orgKeys: Record<OrganizationId, EncString>,
|
||||||
) {
|
) {
|
||||||
await client.crypto().initialize_user_crypto({
|
await client.crypto().initialize_user_crypto({
|
||||||
userId: asUuid(userId),
|
userId: asUuid(userId),
|
||||||
@@ -245,9 +244,7 @@ export class DefaultSdkService implements SdkService {
|
|||||||
// null to make sure any existing org keys are cleared.
|
// null to make sure any existing org keys are cleared.
|
||||||
await client.crypto().initialize_org_crypto({
|
await client.crypto().initialize_org_crypto({
|
||||||
organizationKeys: new Map(
|
organizationKeys: new Map(
|
||||||
Object.entries(orgKeys ?? {})
|
Object.entries(orgKeys).map(([k, v]) => [asUuid(k), v.toJSON() as UnsignedSharedKey]),
|
||||||
.filter(([_, v]) => v.type === "organization")
|
|
||||||
.map(([k, v]) => [asUuid(k), v.key as UnsignedSharedKey]),
|
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { EncryptedOrganizationKeyData } from "@bitwarden/common/admin-console/models/data/encrypted-organization-key.data";
|
|
||||||
import { ProfileOrganizationResponse } from "@bitwarden/common/admin-console/models/response/profile-organization.response";
|
import { ProfileOrganizationResponse } from "@bitwarden/common/admin-console/models/response/profile-organization.response";
|
||||||
import { ProfileProviderOrganizationResponse } from "@bitwarden/common/admin-console/models/response/profile-provider-organization.response";
|
import { ProfileProviderOrganizationResponse } from "@bitwarden/common/admin-console/models/response/profile-provider-organization.response";
|
||||||
import { ProfileProviderResponse } from "@bitwarden/common/admin-console/models/response/profile-provider.response";
|
import { ProfileProviderResponse } from "@bitwarden/common/admin-console/models/response/profile-provider.response";
|
||||||
@@ -406,9 +405,7 @@ export abstract class KeyService {
|
|||||||
* @deprecated Temporary function to allow the SDK to be initialized after the login process, it
|
* @deprecated Temporary function to allow the SDK to be initialized after the login process, it
|
||||||
* will be removed when auth has been migrated to the SDK.
|
* will be removed when auth has been migrated to the SDK.
|
||||||
*/
|
*/
|
||||||
abstract encryptedOrgKeys$(
|
abstract encryptedOrgKeys$(userId: UserId): Observable<Record<OrganizationId, EncString>>;
|
||||||
userId: UserId,
|
|
||||||
): Observable<Record<OrganizationId, EncryptedOrganizationKeyData> | null>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an observable stream of the users public key. If the user is does not have
|
* Gets an observable stream of the users public key. If the user is does not have
|
||||||
|
|||||||
@@ -907,10 +907,57 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
|||||||
return this.cipherDecryptionKeys$(userId).pipe(map((keys) => keys?.orgKeys ?? null));
|
return this.cipherDecryptionKeys$(userId).pipe(map((keys) => keys?.orgKeys ?? null));
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedOrgKeys$(
|
encryptedOrgKeys$(userId: UserId): Observable<Record<OrganizationId, EncString>> {
|
||||||
userId: UserId,
|
return this.userPrivateKey$(userId)?.pipe(
|
||||||
): Observable<Record<OrganizationId, EncryptedOrganizationKeyData> | null> {
|
switchMap((userPrivateKey) => {
|
||||||
return this.stateProvider.getUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS).state$;
|
if (userPrivateKey == null) {
|
||||||
|
// We can't do any org based decryption
|
||||||
|
return of({});
|
||||||
|
}
|
||||||
|
|
||||||
|
return combineLatest([
|
||||||
|
this.stateProvider.getUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS).state$,
|
||||||
|
this.providerKeysHelper$(userId, userPrivateKey),
|
||||||
|
]).pipe(
|
||||||
|
switchMap(async ([encryptedOrgKeys, providerKeys]) => {
|
||||||
|
const userPubKey = await this.derivePublicKey(userPrivateKey);
|
||||||
|
|
||||||
|
const result: Record<OrganizationId, EncString> = {};
|
||||||
|
encryptedOrgKeys = encryptedOrgKeys ?? {};
|
||||||
|
for (const orgId of Object.keys(encryptedOrgKeys) as OrganizationId[]) {
|
||||||
|
if (result[orgId] != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const encrypted = BaseEncryptedOrganizationKey.fromData(encryptedOrgKeys[orgId]);
|
||||||
|
if (encrypted == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let orgKey: EncString;
|
||||||
|
|
||||||
|
// Because the SDK only supports user encrypted org keys, we need to re-encrypt
|
||||||
|
// any provider encrypted org keys with the user's public key. This should be removed
|
||||||
|
// once the SDK has support for provider keys.
|
||||||
|
if (BaseEncryptedOrganizationKey.isProviderEncrypted(encrypted)) {
|
||||||
|
if (providerKeys == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
orgKey = await this.encryptService.encapsulateKeyUnsigned(
|
||||||
|
await encrypted.decrypt(this.encryptService, providerKeys!),
|
||||||
|
userPubKey!,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
orgKey = encrypted.encryptedOrganizationKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[orgId] = orgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
cipherDecryptionKeys$(userId: UserId): Observable<CipherDecryptionKeys | null> {
|
cipherDecryptionKeys$(userId: UserId): Observable<CipherDecryptionKeys | null> {
|
||||||
|
|||||||
Reference in New Issue
Block a user