This commit is contained in:
Rui Tomé 2024-04-25 23:42:02 +01:00 committed by GitHub
commit f94eaa697c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 98 additions and 48 deletions

View File

@ -1,2 +1,2 @@
export * from "./pending-organization-auth-request.response";
export * from "./organization-auth-request.service";
export * from "./organization-auth-request-api.service";

View File

@ -4,14 +4,14 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { PendingAuthRequestView } from "../../views/pending-auth-request.view";
import { PendingAuthRequestView } from "../../views/auth-requests/pending-auth-request.view";
import { AdminAuthRequestUpdateRequest } from "./admin-auth-request-update.request";
import { BulkDenyAuthRequestsRequest } from "./bulk-deny-auth-requests.request";
import { PendingOrganizationAuthRequestResponse } from "./pending-organization-auth-request.response";
@Injectable()
export class OrganizationAuthRequestService {
export class OrganizationAuthRequestApiService {
constructor(private apiService: ApiService) {}
async listPendingRequests(organizationId: string): Promise<PendingAuthRequestView[]> {

View File

@ -0,0 +1,76 @@
import { Injectable } from "@angular/core";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { PendingAuthRequestView } from "../../views/auth-requests/pending-auth-request.view";
import { OrganizationAuthRequestApiService } from "bitwarden_license/bit-common/src/admin-console/services/auth-requests";
@Injectable()
export class OrganizationAuthRequestService {
constructor(
private organizationAuthRequestApiService: OrganizationAuthRequestApiService,
private cryptoService: CryptoService,
) {}
async listPendingRequests(organizationId: string): Promise<PendingAuthRequestView[]> {
return await this.organizationAuthRequestApiService.listPendingRequests(organizationId);
}
async denyPendingRequests(organizationId: string, ...requestIds: string[]): Promise<void> {
await this.organizationAuthRequestApiService.denyPendingRequests(organizationId, ...requestIds);
}
async approvePendingRequest(
organizationId: string,
encryptedUserKey: string,
encryptedOrgPrivateKey: string,
devicePublicKey: string,
requestId: string,
) {
const encryptedKey = await this.getEncryptedUserKey(
organizationId,
encryptedUserKey,
encryptedOrgPrivateKey,
devicePublicKey,
);
await this.organizationAuthRequestApiService.approvePendingRequest(
organizationId,
requestId,
encryptedKey,
);
}
/**
* Creates a copy of the user key that has been encrypted with the provided device's public key.
* @param devicePublicKey
* @param resetPasswordDetails
* @private
*/
private async getEncryptedUserKey(
organizationId: string,
encryptedUserKey: string,
encryptedOrgPrivateKey: string,
devicePublicKey: string,
): Promise<EncString> {
const devicePubKey = Utils.fromB64ToArray(devicePublicKey);
// Decrypt Organization's encrypted Private Key with org key
const orgSymKey = await this.cryptoService.getOrgKey(organizationId);
const decOrgPrivateKey = await this.cryptoService.decryptToBytes(
new EncString(encryptedOrgPrivateKey),
orgSymKey,
);
// Decrypt user key with decrypted org private key
const decValue = await this.cryptoService.rsaDecrypt(encryptedUserKey, decOrgPrivateKey);
const userKey = new SymmetricCryptoKey(decValue);
// Re-encrypt user Key with the Device Public Key
return await this.cryptoService.rsaEncrypt(userKey.key, devicePubKey);
}
}

View File

@ -1,6 +1,6 @@
import { View } from "@bitwarden/common/models/view/view";
import { PendingOrganizationAuthRequestResponse } from "../services/auth-requests";
import { PendingOrganizationAuthRequestResponse } from "../../services/auth-requests";
export class PendingAuthRequestView implements View {
id: string;

View File

@ -1,8 +1,9 @@
import { NgModule } from "@angular/core";
import { OrganizationAuthRequestService } from "./services/auth-requests";
import { OrganizationAuthRequestApiService } from "../../../../../../bit-common/src/admin-console/services/auth-requests/organization-auth-request-api.service";
import { OrganizationAuthRequestService } from "../../../../../../bit-common/src/admin-console/services/auth-requests/organization-auth-request.service";
@NgModule({
providers: [OrganizationAuthRequestService],
providers: [OrganizationAuthRequestApiService, OrganizationAuthRequestService],
})
export class CoreOrganizationModule {}

View File

@ -3,21 +3,15 @@ import { ActivatedRoute } from "@angular/router";
import { BehaviorSubject, Subject, switchMap, takeUntil, tap } from "rxjs";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { OrganizationUserResetPasswordDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-user/responses";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { TableDataSource } from "@bitwarden/components";
import { Devices } from "@bitwarden/web-vault/app/admin-console/icons";
import { OrganizationAuthRequestService } from "../../core/services/auth-requests";
import { PendingAuthRequestView } from "../../core/views/pending-auth-request.view";
import { OrganizationAuthRequestService } from "../../../../../../../bit-common/src/admin-console/services/auth-requests/organization-auth-request.service";
import { PendingAuthRequestView } from "../../../../../../../bit-common/src/admin-console/views/auth-requests/pending-auth-request.view";
@Component({
selector: "app-org-device-approvals",
templateUrl: "./device-approvals.component.html",
@ -36,7 +30,6 @@ export class DeviceApprovalsComponent implements OnInit, OnDestroy {
constructor(
private organizationAuthRequestService: OrganizationAuthRequestService,
private organizationUserService: OrganizationUserService,
private cryptoService: CryptoService,
private route: ActivatedRoute,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService,
@ -64,35 +57,6 @@ export class DeviceApprovalsComponent implements OnInit, OnDestroy {
});
}
/**
* Creates a copy of the user key that has been encrypted with the provided device's public key.
* @param devicePublicKey
* @param resetPasswordDetails
* @private
*/
private async getEncryptedUserKey(
devicePublicKey: string,
resetPasswordDetails: OrganizationUserResetPasswordDetailsResponse,
): Promise<EncString> {
const encryptedUserKey = resetPasswordDetails.resetPasswordKey;
const encryptedOrgPrivateKey = resetPasswordDetails.encryptedPrivateKey;
const devicePubKey = Utils.fromB64ToArray(devicePublicKey);
// Decrypt Organization's encrypted Private Key with org key
const orgSymKey = await this.cryptoService.getOrgKey(this.organizationId);
const decOrgPrivateKey = await this.cryptoService.decryptToBytes(
new EncString(encryptedOrgPrivateKey),
orgSymKey,
);
// Decrypt user key with decrypted org private key
const decValue = await this.cryptoService.rsaDecrypt(encryptedUserKey, decOrgPrivateKey);
const userKey = new SymmetricCryptoKey(decValue);
// Re-encrypt user Key with the Device Public Key
return await this.cryptoService.rsaEncrypt(userKey.key, devicePubKey);
}
async approveRequest(authRequest: PendingAuthRequestView) {
await this.performAsyncAction(async () => {
const details = await this.organizationUserService.getOrganizationUserResetPasswordDetails(
@ -110,12 +74,12 @@ export class DeviceApprovalsComponent implements OnInit, OnDestroy {
return;
}
const encryptedKey = await this.getEncryptedUserKey(authRequest.publicKey, details);
await this.organizationAuthRequestService.approvePendingRequest(
this.organizationId,
details.resetPasswordKey,
details.encryptedPrivateKey,
authRequest.publicKey,
authRequest.id,
encryptedKey,
);
this.platformUtilsService.showToast(

View File

@ -28,6 +28,10 @@
"name": "libs",
"path": "libs",
},
{
"name": "common (bit)",
"path": "bitwarden_license/bit-common",
},
],
"settings": {
"eslint.options": {

View File

@ -38,6 +38,11 @@
],
"useDefineForClassFields": false
},
"include": ["apps/web/src/**/*", "libs/*/src/**/*", "bitwarden_license/bit-web/src/**/*"],
"include": [
"apps/web/src/**/*",
"libs/*/src/**/*",
"bitwarden_license/bit-web/src/**/*",
"bitwarden_license/bit-common/src/**/*"
],
"exclude": ["apps/web/src/**/*.spec.ts", "libs/*/src/**/*.spec.ts", "**/*.spec-util.ts"]
}