mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
feat(auth): implement view data persistence in 2FA flows
Add persistence to two-factor authentication in the extension login flow. Implements caching of form state to improve user experience when navigating between authentication steps. Includes feature flag for controlled rollout.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
// Must mock modules before importing
|
||||
@@ -26,22 +27,26 @@ describe("ExtensionTwoFactorAuthEmailComponentService", () => {
|
||||
|
||||
let dialogService: MockProxy<DialogService>;
|
||||
let window: MockProxy<Window>;
|
||||
let configService: MockProxy<ConfigService>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
dialogService = mock<DialogService>();
|
||||
window = mock<Window>();
|
||||
configService = mock<ConfigService>();
|
||||
|
||||
extensionTwoFactorAuthEmailComponentService = new ExtensionTwoFactorAuthEmailComponentService(
|
||||
dialogService,
|
||||
window,
|
||||
configService,
|
||||
);
|
||||
});
|
||||
|
||||
describe("openPopoutIfApprovedForEmail2fa", () => {
|
||||
it("should open a popout if the user confirms the warning to popout the extension when in the popup", async () => {
|
||||
// Arrange
|
||||
configService.getFeatureFlag.mockResolvedValue(false);
|
||||
dialogService.openSimpleDialog.mockResolvedValue(true);
|
||||
|
||||
jest.spyOn(BrowserPopupUtils, "inPopup").mockReturnValue(true);
|
||||
@@ -61,6 +66,7 @@ describe("ExtensionTwoFactorAuthEmailComponentService", () => {
|
||||
|
||||
it("should not open a popout if the user cancels the warning to popout the extension when in the popup", async () => {
|
||||
// Arrange
|
||||
configService.getFeatureFlag.mockResolvedValue(false);
|
||||
dialogService.openSimpleDialog.mockResolvedValue(false);
|
||||
|
||||
jest.spyOn(BrowserPopupUtils, "inPopup").mockReturnValue(true);
|
||||
@@ -80,6 +86,7 @@ describe("ExtensionTwoFactorAuthEmailComponentService", () => {
|
||||
|
||||
it("should not open a popout if not in the popup", async () => {
|
||||
// Arrange
|
||||
configService.getFeatureFlag.mockResolvedValue(false);
|
||||
jest.spyOn(BrowserPopupUtils, "inPopup").mockReturnValue(false);
|
||||
|
||||
// Act
|
||||
@@ -89,5 +96,15 @@ describe("ExtensionTwoFactorAuthEmailComponentService", () => {
|
||||
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||
expect(openTwoFactorAuthEmailPopout).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not prompt or open a popout if the feature flag is enabled", async () => {
|
||||
configService.getFeatureFlag.mockResolvedValue(true);
|
||||
jest.spyOn(BrowserPopupUtils, "inPopup").mockReturnValue(true);
|
||||
|
||||
await extensionTwoFactorAuthEmailComponentService.openPopoutIfApprovedForEmail2fa();
|
||||
|
||||
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||
expect(openTwoFactorAuthEmailPopout).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import {
|
||||
DefaultTwoFactorAuthEmailComponentService,
|
||||
TwoFactorAuthEmailComponentService,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { openTwoFactorAuthEmailPopout } from "../../auth/popup/utils/auth-popout-window";
|
||||
@@ -15,11 +17,21 @@ export class ExtensionTwoFactorAuthEmailComponentService
|
||||
constructor(
|
||||
private dialogService: DialogService,
|
||||
private window: Window,
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async openPopoutIfApprovedForEmail2fa(): Promise<void> {
|
||||
const isTwoFactorFormPersistenceEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.PM9115_TwoFactorExtensionDataPersistence,
|
||||
);
|
||||
|
||||
if (isTwoFactorFormPersistenceEnabled) {
|
||||
// If the feature flag is enabled, we don't need to prompt the user to open the popout
|
||||
return;
|
||||
}
|
||||
|
||||
if (BrowserPopupUtils.inPopup(this.window)) {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "warning" },
|
||||
|
||||
@@ -557,7 +557,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: TwoFactorAuthEmailComponentService,
|
||||
useClass: ExtensionTwoFactorAuthEmailComponentService,
|
||||
deps: [DialogService, WINDOW],
|
||||
deps: [DialogService, WINDOW, ConfigService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: TwoFactorAuthWebAuthnComponentService,
|
||||
|
||||
Reference in New Issue
Block a user