1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 05:13:29 +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:
Bernd Schoolmann
2025-06-02 23:56:29 +02:00
committed by GitHub
parent 26caeb3083
commit 23ec6bacc9
19 changed files with 27 additions and 265 deletions

View File

@@ -79,7 +79,6 @@ describe("lockGuard", () => {
{ path: "", component: EmptyComponent },
{ path: "lock", component: EmptyComponent, canActivate: [lockGuard()] },
{ path: "non-lock-route", component: EmptyComponent },
{ path: "migrate-legacy-encryption", component: EmptyComponent },
]),
],
providers: [
@@ -182,18 +181,6 @@ describe("lockGuard", () => {
expect(messagingService.send).toHaveBeenCalledWith("logout");
});
it("should send the user to migrate-legacy-encryption if they are a legacy user on a web client", async () => {
const { router } = setup({
authStatus: AuthenticationStatus.Locked,
canLock: true,
isLegacyUser: true,
clientType: ClientType.Web,
});
await router.navigate(["lock"]);
expect(router.url).toBe("/migrate-legacy-encryption");
});
it("should allow navigation to the lock route when device trust is supported, the user has a MP, and the user is coming from the login-initiated page", async () => {
const { router } = setup({
authStatus: AuthenticationStatus.Locked,

View File

@@ -11,11 +11,9 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { ClientType } from "@bitwarden/common/enums";
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction";
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { KeyService } from "@bitwarden/key-management";
/**
@@ -33,7 +31,6 @@ export function lockGuard(): CanActivateFn {
const authService = inject(AuthService);
const keyService = inject(KeyService);
const deviceTrustService = inject(DeviceTrustServiceAbstraction);
const platformUtilService = inject(PlatformUtilsService);
const messagingService = inject(MessagingService);
const router = inject(Router);
const userVerificationService = inject(UserVerificationService);
@@ -59,12 +56,7 @@ export function lockGuard(): CanActivateFn {
return false;
}
// If legacy user on web, redirect to migration page
if (await keyService.isLegacyUser()) {
if (platformUtilService.getClientType() === ClientType.Web) {
return router.createUrlTree(["migrate-legacy-encryption"]);
}
// Log out legacy users on other clients
messagingService.send("logout");
return false;
}

View File

@@ -282,16 +282,12 @@ export class LoginComponent implements OnInit, OnDestroy {
private async handleAuthResult(authResult: AuthResult): Promise<void> {
if (authResult.requiresEncryptionKeyMigration) {
/* Legacy accounts used the master key to encrypt data.
Migration is required but only performed on Web. */
if (this.clientType === ClientType.Web) {
await this.router.navigate(["migrate-legacy-encryption"]);
} else {
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccured"),
message: this.i18nService.t("encryptionKeyMigrationRequired"),
});
}
This is now unsupported and requires a downgraded client */
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccured"),
message: this.i18nService.t("legacyEncryptionUnsupported"),
});
return;
}

View File

@@ -1,6 +1,5 @@
import {
DuoLaunchAction,
LegacyKeyMigrationAction,
TwoFactorAuthComponentService,
} from "./two-factor-auth-component.service";
@@ -9,10 +8,6 @@ export class DefaultTwoFactorAuthComponentService implements TwoFactorAuthCompon
return false;
}
determineLegacyKeyMigrationAction() {
return LegacyKeyMigrationAction.PREVENT_LOGIN_AND_SHOW_REQUIRE_MIGRATION_WARNING;
}
determineDuoLaunchAction(): DuoLaunchAction {
return DuoLaunchAction.DIRECT_LAUNCH;
}

View File

@@ -1,12 +1,5 @@
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum LegacyKeyMigrationAction {
PREVENT_LOGIN_AND_SHOW_REQUIRE_MIGRATION_WARNING,
NAVIGATE_TO_MIGRATION_COMPONENT,
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum DuoLaunchAction {
@@ -38,18 +31,6 @@ export abstract class TwoFactorAuthComponentService {
*/
abstract removePopupWidthExtension?(): void;
/**
* We used to use the user's master key to encrypt their data. We deprecated that approach
* and now use a user key. This method should be called if we detect that the user
* is still using the old master key encryption scheme (server sends down a flag to
* indicate this). This method then determines what action to take based on the client.
*
* We have two possible actions:
* 1. Prevent the user from logging in and show a warning that they need to migrate their key on the web client today.
* 2. Navigate the user to the key migration component on the web client.
*/
abstract determineLegacyKeyMigrationAction(): LegacyKeyMigrationAction;
/**
* Optionally closes any single action popouts (extension only).
* @returns true if we are in a single action popout and it was closed, false otherwise.

View File

@@ -69,7 +69,6 @@ import {
} from "./two-factor-auth-component-cache.service";
import {
DuoLaunchAction,
LegacyKeyMigrationAction,
TwoFactorAuthComponentService,
} from "./two-factor-auth-component.service";
import {
@@ -388,22 +387,12 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy {
if (!result.requiresEncryptionKeyMigration) {
return false;
}
// Migration is forced so prevent login via return
const legacyKeyMigrationAction: LegacyKeyMigrationAction =
this.twoFactorAuthComponentService.determineLegacyKeyMigrationAction();
switch (legacyKeyMigrationAction) {
case LegacyKeyMigrationAction.NAVIGATE_TO_MIGRATION_COMPONENT:
await this.router.navigate(["migrate-legacy-encryption"]);
break;
case LegacyKeyMigrationAction.PREVENT_LOGIN_AND_SHOW_REQUIRE_MIGRATION_WARNING:
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccured"),
message: this.i18nService.t("encryptionKeyMigrationRequired"),
});
break;
}
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccured"),
message: this.i18nService.t("legacyEncryptionUnsupported"),
});
return true;
}

View File

@@ -17,7 +17,6 @@ import { IdentityDeviceVerificationResponse } from "@bitwarden/common/auth/model
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { ClientType } from "@bitwarden/common/enums";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
import {
@@ -254,13 +253,10 @@ export abstract class LoginStrategy {
protected async processTokenResponse(response: IdentityTokenResponse): Promise<AuthResult> {
const result = new AuthResult();
// Old encryption keys must be migrated, but is currently only available on web.
// Other clients shouldn't continue the login process.
// Encryption key migration of legacy users (with no userkey) is not supported anymore
if (this.encryptionKeyMigrationRequired(response)) {
result.requiresEncryptionKeyMigration = true;
if (this.platformUtilsService.getClientType() !== ClientType.Web) {
return result;
}
return result;
}
// Must come before setting keys, user key needs email to update additional keys.