mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
[PM-20225] Prevent legacy users without userkey from logging in (#14267)
* Prevent legacy users without userkey from logging in * Remove further web-migration code for legacy users * Add i18n for legacy user error message * Update comment * Remove migrate legacy component * Remove i18n messages * Remove migrate legacy encryption reference
This commit is contained in:
@@ -1,2 +1 @@
|
||||
export * from "./web-two-factor-auth-component.service";
|
||||
export * from "./web-two-factor-auth-duo-component.service";
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import {
|
||||
DefaultTwoFactorAuthComponentService,
|
||||
TwoFactorAuthComponentService,
|
||||
LegacyKeyMigrationAction,
|
||||
} from "@bitwarden/auth/angular";
|
||||
|
||||
export class WebTwoFactorAuthComponentService
|
||||
extends DefaultTwoFactorAuthComponentService
|
||||
implements TwoFactorAuthComponentService
|
||||
{
|
||||
override determineLegacyKeyMigrationAction(): LegacyKeyMigrationAction {
|
||||
return LegacyKeyMigrationAction.NAVIGATE_TO_MIGRATION_COMPONENT;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ import {
|
||||
SetPasswordJitService,
|
||||
SsoComponentService,
|
||||
LoginDecryptionOptionsService,
|
||||
TwoFactorAuthComponentService,
|
||||
TwoFactorAuthDuoComponentService,
|
||||
ChangePasswordService,
|
||||
} from "@bitwarden/auth/angular";
|
||||
@@ -116,7 +115,6 @@ import {
|
||||
WebRegistrationFinishService,
|
||||
WebLoginComponentService,
|
||||
WebLoginDecryptionOptionsService,
|
||||
WebTwoFactorAuthComponentService,
|
||||
WebTwoFactorAuthDuoComponentService,
|
||||
LinkSsoService,
|
||||
} from "../auth";
|
||||
@@ -269,12 +267,6 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: WebLockComponentService,
|
||||
deps: [],
|
||||
}),
|
||||
// TODO: PM-18182 - Refactor component services into lazy loaded modules
|
||||
safeProvider({
|
||||
provide: TwoFactorAuthComponentService,
|
||||
useClass: WebTwoFactorAuthComponentService,
|
||||
deps: [],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SetPasswordJitService,
|
||||
useClass: WebSetPasswordJitService,
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<div class="tw-mt-12 tw-flex tw-justify-center">
|
||||
<div class="tw-max-w-xl">
|
||||
<h1 bitTypography="h1" class="tw-mb-4 tw-text-center">{{ "updateEncryptionKey" | i18n }}</h1>
|
||||
<div
|
||||
class="tw-block tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-8"
|
||||
>
|
||||
<p>
|
||||
{{ "updateEncryptionSchemeDesc" | i18n }}
|
||||
<a
|
||||
href="https://bitwarden.com/help/account-encryption-key/#rotate-your-encryption-key"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>{{ "learnMore" | i18n }}</a
|
||||
>
|
||||
</p>
|
||||
<bit-callout type="warning">{{ "updateEncryptionKeyWarning" | i18n }}</bit-callout>
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "masterPass" | i18n }}</bit-label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
bitInput
|
||||
type="password"
|
||||
formControlName="masterPassword"
|
||||
appAutofocus
|
||||
/>
|
||||
<button type="button" bitIconButton bitSuffix bitPasswordInputToggle></button>
|
||||
</bit-form-field>
|
||||
<button type="submit" bitButton bitFormButton buttonType="primary" block>
|
||||
{{ "updateEncryptionKey" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -1,100 +0,0 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
import { UserKeyRotationModule } from "../key-rotation/user-key-rotation.module";
|
||||
import { UserKeyRotationService } from "../key-rotation/user-key-rotation.service";
|
||||
|
||||
// The master key was originally used to encrypt user data, before the user key was introduced.
|
||||
// This component is used to migrate from the old encryption scheme to the new one.
|
||||
@Component({
|
||||
imports: [SharedModule, UserKeyRotationModule],
|
||||
templateUrl: "migrate-legacy-encryption.component.html",
|
||||
})
|
||||
export class MigrateFromLegacyEncryptionComponent {
|
||||
protected formGroup = new FormGroup({
|
||||
masterPassword: new FormControl("", [Validators.required]),
|
||||
});
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private keyRotationService: UserKeyRotationService,
|
||||
private i18nService: I18nService,
|
||||
private keyService: KeyService,
|
||||
private messagingService: MessagingService,
|
||||
private logService: LogService,
|
||||
private syncService: SyncService,
|
||||
private toastService: ToastService,
|
||||
private dialogService: DialogService,
|
||||
private folderApiService: FolderApiServiceAbstraction,
|
||||
) {}
|
||||
|
||||
submit = async () => {
|
||||
this.formGroup.markAsTouched();
|
||||
|
||||
if (this.formGroup.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeUser = await firstValueFrom(this.accountService.activeAccount$);
|
||||
if (activeUser == null) {
|
||||
throw new Error("No active user.");
|
||||
}
|
||||
|
||||
const hasUserKey = await this.keyService.hasUserKey(activeUser.id);
|
||||
if (hasUserKey) {
|
||||
this.messagingService.send("logout");
|
||||
throw new Error("User key already exists, cannot migrate legacy encryption.");
|
||||
}
|
||||
|
||||
const masterPassword = this.formGroup.value.masterPassword!;
|
||||
|
||||
try {
|
||||
await this.syncService.fullSync(false, true);
|
||||
|
||||
await this.keyRotationService.rotateUserKeyAndEncryptedDataLegacy(masterPassword, activeUser);
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("keyUpdated"),
|
||||
message: this.i18nService.t("logBackInOthersToo"),
|
||||
timeout: 15000,
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch (e) {
|
||||
// If the error is due to missing folders, we can delete all folders and try again
|
||||
if (
|
||||
e instanceof ErrorResponse &&
|
||||
e.message === "All existing folders must be included in the rotation."
|
||||
) {
|
||||
const deleteFolders = await this.dialogService.openSimpleDialog({
|
||||
type: "warning",
|
||||
title: { key: "encryptionKeyUpdateCannotProceed" },
|
||||
content: { key: "keyUpdateFoldersFailed" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: { key: "cancel" },
|
||||
});
|
||||
|
||||
if (deleteFolders) {
|
||||
await this.folderApiService.deleteAll(activeUser.id);
|
||||
await this.syncService.fullSync(true, true);
|
||||
await this.submit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.logService.error(e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -151,13 +151,6 @@ const routes: Routes = [
|
||||
canActivate: [authGuard],
|
||||
data: { titleId: "updatePassword" } satisfies RouteDataProperties,
|
||||
},
|
||||
{
|
||||
path: "migrate-legacy-encryption",
|
||||
loadComponent: () =>
|
||||
import("./key-management/migrate-encryption/migrate-legacy-encryption.component").then(
|
||||
(mod) => mod.MigrateFromLegacyEncryptionComponent,
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4473,9 +4473,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"encryptionKeyUpdateCannotProceed": {
|
||||
"message": "Encryption key update cannot proceed"
|
||||
},
|
||||
"editFieldLabel": {
|
||||
"message": "Edit $LABEL$",
|
||||
"placeholders": {
|
||||
@@ -4528,24 +4525,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"keyUpdateFoldersFailed": {
|
||||
"message": "When updating your encryption key, your folders could not be decrypted. To continue with the update, your folders must be deleted. No vault items will be deleted if you proceed."
|
||||
},
|
||||
"keyUpdated": {
|
||||
"message": "Key updated"
|
||||
},
|
||||
"updateEncryptionKey": {
|
||||
"message": "Update encryption key"
|
||||
},
|
||||
"updateEncryptionSchemeDesc": {
|
||||
"message": "We've changed the encryption scheme to provide better security. Update your encryption key now by entering your master password below."
|
||||
},
|
||||
"updateEncryptionKeyWarning": {
|
||||
"message": "After updating your encryption key, you are required to log out and back in to all Bitwarden applications that you are currently using (such as the mobile app or browser extensions). Failure to log out and back in (which downloads your new encryption key) may result in data corruption. We will attempt to log you out automatically, however, it may be delayed."
|
||||
},
|
||||
"updateEncryptionKeyAccountExportWarning": {
|
||||
"message": "Any account restricted exports you have saved will become invalid."
|
||||
},
|
||||
"legacyEncryptionUnsupported": {
|
||||
"message": "Legacy encryption is no longer supported. Please contact support to recover your account."
|
||||
},
|
||||
"subscription": {
|
||||
"message": "Subscription"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user