Update `EnrollMasterPasswordResetComponent` to include a server-side hash check

This commit is contained in:
Addison Beck 2024-04-17 14:00:16 -05:00
parent e9dad3cc67
commit 71271614f8
No known key found for this signature in database
2 changed files with 29 additions and 18 deletions

View File

@ -2,6 +2,8 @@ import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/admin-console/abstractions/organization-user/requests";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationWithSecret } from "@bitwarden/common/auth/types/verification";
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";
@ -26,6 +28,7 @@ export class EnrollMasterPasswordReset {
i18nService: I18nService,
syncService: SyncService,
logService: LogService,
userVerificationService: UserVerificationService,
) {
const result = await UserVerificationDialogComponent.open(dialogService, {
title: "enrollAccountRecovery",
@ -33,36 +36,41 @@ export class EnrollMasterPasswordReset {
text: "resetPasswordEnrollmentWarning",
type: "warning",
},
verificationType: {
type: "custom",
verificationFn: async (secret: VerificationWithSecret) => {
const request = (await userVerificationService.buildRequest(
secret,
)) as OrganizationUserResetPasswordEnrollmentRequest;
request.resetPasswordKey = await resetPasswordService.buildRecoveryKey(
data.organization.id,
);
// Process the enrollment request, which is an endpoint that is
// gated by a server-side check of the master password hash
await organizationUserService.putOrganizationUserResetPasswordEnrollment(
data.organization.id,
data.organization.userId,
request,
);
return true;
},
},
});
// Handle the result of the dialog based on user action and verification success
// User canceled enrollment
if (result.userAction === "cancel") {
return;
}
// User confirmed the dialog so check verification success
// Enrollment failed
if (!result.verificationSuccess) {
// verification failed
return;
}
// Verification succeeded
// Enrollment succeeded
try {
// This object is missing most of the properties in the
// `OrganizationUserResetPasswordEnrollmentRequest()`, but those
// properties don't carry over to the server model anyway and are
// never used by this flow.
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = await resetPasswordService.buildRecoveryKey(data.organization.id);
await organizationUserService.putOrganizationUserResetPasswordEnrollment(
data.organization.id,
data.organization.userId,
request,
);
platformUtilsService.showToast("success", null, i18nService.t("enrollPasswordResetSuccess"));
await syncService.fullSync(true);
} catch (e) {
logService.error(e);

View File

@ -10,6 +10,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
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";
@ -48,6 +49,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
private dialogService: DialogService,
private resetPasswordService: OrganizationUserResetPasswordService,
private userVerificationService: UserVerificationService,
) {}
async ngOnInit() {
@ -155,6 +157,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
this.i18nService,
this.syncService,
this.logService,
this.userVerificationService,
);
} else {
// Remove reset password