mirror of
https://github.com/bitwarden/browser
synced 2026-01-18 00:13:29 +00:00
feat(auth): [PM-9674] Remove Deprecated LockComponents (#12453)
This PR deletes the legacy lock components from the Angular clients and also removes feature flag control from the routing. The lock component will now be based entirely on the new, recently refreshed LockComponent in libs/auth/angular.
This commit is contained in:
@@ -1,100 +0,0 @@
|
||||
<form (ngSubmit)="submit()">
|
||||
<app-header>
|
||||
<div class="left"></div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" *ngIf="pinEnabled || masterPasswordEnabled">
|
||||
{{ "unlock" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</app-header>
|
||||
<main tabindex="-1">
|
||||
<ng-container *ngIf="fido2PopoutSessionData$ | async as fido2Data">
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div
|
||||
class="box-content-row box-content-row-flex"
|
||||
appBoxRow
|
||||
*ngIf="pinEnabled || masterPasswordEnabled"
|
||||
>
|
||||
<div class="row-main" *ngIf="pinEnabled">
|
||||
<label for="pin">{{ "pin" | i18n }}</label>
|
||||
<input
|
||||
id="pin"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="PIN"
|
||||
class="monospaced"
|
||||
[(ngModel)]="pin"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="row-main" *ngIf="masterPasswordEnabled && !pinEnabled">
|
||||
<label for="masterPassword">{{ "masterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
aria-describedby="masterPasswordHelp"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword()"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="masterPasswordHelp" class="box-footer">
|
||||
<p>
|
||||
{{
|
||||
fido2Data.isFido2Session
|
||||
? ("yourPasskeyIsLocked" | i18n)
|
||||
: ("yourVaultIsLocked" | i18n)
|
||||
}}
|
||||
</p>
|
||||
{{ "loggedInAsOn" | i18n: email : webVaultHostname }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="biometricLock">
|
||||
<div class="box-footer no-pad">
|
||||
<button
|
||||
type="button"
|
||||
class="btn primary block"
|
||||
(click)="unlockBiometric()"
|
||||
appStopClick
|
||||
[disabled]="pendingBiometric"
|
||||
>
|
||||
{{ "unlockWithBiometrics" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center" *ngIf="!fido2Data.isFido2Session">
|
||||
<button type="button" appStopClick (click)="logOut()">{{ "logOut" | i18n }}</button>
|
||||
</p>
|
||||
<app-callout *ngIf="biometricError" type="danger">{{ biometricError }}</app-callout>
|
||||
<p class="text-center text-muted" *ngIf="pendingBiometric">
|
||||
<i class="bwi bwi-spinner bwi-spin" aria-hidden="true"></i> {{ "awaitDesktop" | i18n }}
|
||||
</p>
|
||||
|
||||
<app-fido2-use-browser-link-v1></app-fido2-use-browser-link-v1>
|
||||
</ng-container>
|
||||
</main>
|
||||
</form>
|
||||
@@ -1,185 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, NgZone, OnInit } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
|
||||
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
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 { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import {
|
||||
KdfConfigService,
|
||||
KeyService,
|
||||
BiometricsService,
|
||||
BiometricStateService,
|
||||
} from "@bitwarden/key-management";
|
||||
|
||||
import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors";
|
||||
import { BrowserRouterService } from "../../platform/popup/services/browser-router.service";
|
||||
import { fido2PopoutSessionData$ } from "../../vault/popup/utils/fido2-popout-session-data";
|
||||
|
||||
@Component({
|
||||
selector: "app-lock",
|
||||
templateUrl: "lock.component.html",
|
||||
})
|
||||
export class LockComponent extends BaseLockComponent implements OnInit {
|
||||
private isInitialLockScreen: boolean;
|
||||
|
||||
biometricError: string;
|
||||
pendingBiometric = false;
|
||||
fido2PopoutSessionData$ = fido2PopoutSessionData$();
|
||||
|
||||
constructor(
|
||||
masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
messagingService: MessagingService,
|
||||
keyService: KeyService,
|
||||
vaultTimeoutService: VaultTimeoutService,
|
||||
vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||
environmentService: EnvironmentService,
|
||||
stateService: StateService,
|
||||
apiService: ApiService,
|
||||
logService: LogService,
|
||||
ngZone: NgZone,
|
||||
policyApiService: PolicyApiServiceAbstraction,
|
||||
policyService: InternalPolicyService,
|
||||
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
authService: AuthService,
|
||||
dialogService: DialogService,
|
||||
deviceTrustService: DeviceTrustServiceAbstraction,
|
||||
userVerificationService: UserVerificationService,
|
||||
pinService: PinServiceAbstraction,
|
||||
private routerService: BrowserRouterService,
|
||||
biometricStateService: BiometricStateService,
|
||||
biometricsService: BiometricsService,
|
||||
accountService: AccountService,
|
||||
kdfConfigService: KdfConfigService,
|
||||
syncService: SyncService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
masterPasswordService,
|
||||
router,
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
messagingService,
|
||||
keyService,
|
||||
vaultTimeoutService,
|
||||
vaultTimeoutSettingsService,
|
||||
environmentService,
|
||||
stateService,
|
||||
apiService,
|
||||
logService,
|
||||
ngZone,
|
||||
policyApiService,
|
||||
policyService,
|
||||
passwordStrengthService,
|
||||
dialogService,
|
||||
deviceTrustService,
|
||||
userVerificationService,
|
||||
pinService,
|
||||
biometricStateService,
|
||||
biometricsService,
|
||||
accountService,
|
||||
authService,
|
||||
kdfConfigService,
|
||||
syncService,
|
||||
toastService,
|
||||
);
|
||||
this.successRoute = "/tabs/current";
|
||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||
|
||||
this.onSuccessfulSubmit = async () => {
|
||||
const previousUrl = this.routerService.getPreviousUrl();
|
||||
if (previousUrl) {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.router.navigateByUrl(previousUrl);
|
||||
} else {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.router.navigate([this.successRoute]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
const autoBiometricsPrompt = await firstValueFrom(
|
||||
this.biometricStateService.promptAutomatically$,
|
||||
);
|
||||
|
||||
window.setTimeout(async () => {
|
||||
document.getElementById(this.pinEnabled ? "pin" : "masterPassword")?.focus();
|
||||
if (
|
||||
this.biometricLock &&
|
||||
autoBiometricsPrompt &&
|
||||
this.isInitialLockScreen &&
|
||||
(await this.authService.getAuthStatus()) === AuthenticationStatus.Locked
|
||||
) {
|
||||
await this.unlockBiometric(true);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
override async unlockBiometric(automaticPrompt: boolean = false): Promise<boolean> {
|
||||
if (!this.biometricLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.biometricError = null;
|
||||
|
||||
let success;
|
||||
try {
|
||||
const available = await super.isBiometricUnlockAvailable();
|
||||
if (!available) {
|
||||
if (!automaticPrompt) {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
type: "warning",
|
||||
title: { key: "biometricsNotAvailableTitle" },
|
||||
content: { key: "biometricsNotAvailableDesc" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.pendingBiometric = true;
|
||||
success = await super.unlockBiometric();
|
||||
}
|
||||
} catch (e) {
|
||||
const error = BiometricErrors[e?.message as BiometricErrorTypes];
|
||||
|
||||
if (error == null) {
|
||||
this.logService.error("Unknown error: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.biometricError = this.i18nService.t(error.description);
|
||||
} finally {
|
||||
this.pendingBiometric = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
unauthGuardFn,
|
||||
} from "@bitwarden/angular/auth/guards";
|
||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||
import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-refresh-redirect";
|
||||
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
||||
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
|
||||
import {
|
||||
@@ -26,7 +25,7 @@ import {
|
||||
LoginComponent,
|
||||
LoginSecondaryContentComponent,
|
||||
LockIcon,
|
||||
LockV2Component,
|
||||
LockComponent,
|
||||
LoginViaAuthRequestComponent,
|
||||
PasswordHintComponent,
|
||||
RegistrationFinishComponent,
|
||||
@@ -60,7 +59,6 @@ import {
|
||||
} from "../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component";
|
||||
import { HintComponent } from "../auth/popup/hint.component";
|
||||
import { HomeComponent } from "../auth/popup/home.component";
|
||||
import { LockComponent } from "../auth/popup/lock.component";
|
||||
import { LoginDecryptionOptionsComponentV1 } from "../auth/popup/login-decryption-options/login-decryption-options-v1.component";
|
||||
import { LoginComponentV1 } from "../auth/popup/login-v1.component";
|
||||
import { LoginViaAuthRequestComponentV1 } from "../auth/popup/login-via-auth-request-v1.component";
|
||||
@@ -173,13 +171,6 @@ const routes: Routes = [
|
||||
canActivate: [fido2AuthGuard],
|
||||
data: { elevation: 1 } satisfies RouteDataProperties,
|
||||
}),
|
||||
{
|
||||
path: "lock",
|
||||
component: LockComponent,
|
||||
canActivate: [lockGuard()],
|
||||
canMatch: [extensionRefreshRedirect("/lockV2")],
|
||||
data: { elevation: 1, doNotSaveUrl: true } satisfies RouteDataProperties,
|
||||
},
|
||||
...twofactorRefactorSwap(
|
||||
TwoFactorComponent,
|
||||
AnonLayoutWrapperComponent,
|
||||
@@ -650,8 +641,8 @@ const routes: Routes = [
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "lockV2",
|
||||
canActivate: [canAccessFeature(FeatureFlag.ExtensionRefresh), lockGuard()],
|
||||
path: "lock",
|
||||
canActivate: [lockGuard()],
|
||||
data: {
|
||||
pageIcon: LockIcon,
|
||||
pageTitle: {
|
||||
@@ -662,19 +653,19 @@ const routes: Routes = [
|
||||
elevation: 1,
|
||||
/**
|
||||
* This ensures that in a passkey flow the `/fido2?<queryParams>` URL does not get
|
||||
* overwritten in the `BrowserRouterService` by the `/lockV2` route. This way, after
|
||||
* overwritten in the `BrowserRouterService` by the `/lock` route. This way, after
|
||||
* unlocking, the user can be redirected back to the `/fido2?<queryParams>` URL.
|
||||
*
|
||||
* Also, this prevents a routing loop when using biometrics to unlock the vault in MV2 (Firefox),
|
||||
* locking up the browser (https://bitwarden.atlassian.net/browse/PM-16116). This involves the
|
||||
* `popup-router-cache.service` pushing the `lockV2` route to the history.
|
||||
* `popup-router-cache.service` pushing the `lock` route to the history.
|
||||
*/
|
||||
doNotSaveUrl: true,
|
||||
} satisfies ExtensionAnonLayoutWrapperData & RouteDataProperties,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: LockV2Component,
|
||||
component: LockComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -23,7 +23,6 @@ import { EnvironmentComponent } from "../auth/popup/environment.component";
|
||||
import { ExtensionAnonLayoutWrapperComponent } from "../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component";
|
||||
import { HintComponent } from "../auth/popup/hint.component";
|
||||
import { HomeComponent } from "../auth/popup/home.component";
|
||||
import { LockComponent } from "../auth/popup/lock.component";
|
||||
import { LoginDecryptionOptionsComponentV1 } from "../auth/popup/login-decryption-options/login-decryption-options-v1.component";
|
||||
import { LoginComponentV1 } from "../auth/popup/login-v1.component";
|
||||
import { LoginViaAuthRequestComponentV1 } from "../auth/popup/login-via-auth-request-v1.component";
|
||||
@@ -156,7 +155,6 @@ import "../platform/popup/locales";
|
||||
VaultFilterComponent,
|
||||
HintComponent,
|
||||
HomeComponent,
|
||||
LockComponent,
|
||||
LoginViaAuthRequestComponentV1,
|
||||
LoginComponentV1,
|
||||
LoginDecryptionOptionsComponentV1,
|
||||
|
||||
Reference in New Issue
Block a user