mirror of
https://github.com/bitwarden/browser.git
synced 2025-03-22 15:19:15 +01:00
[PM-5800] Remove passwordless-login feature flag (#7626)
* Removed passwordless-login feature flag * Removed conditional on login component. * Added back reference accidentally deleted. * Fixed initialization of the service in tests. * Removed unused private variable. * Updated DI to remove configService * Undid changes to workspace file. * Undid all changes to workspace file * Undid merge changes to collection dialog * Linting
This commit is contained in:
parent
2fa7580229
commit
bdc951194e
apps/web/src/app/auth
libs
angular/src
common/src
auth
abstractions/webauthn
services/webauthn-login
enums
@ -51,10 +51,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="tw-mb-3 tw-flex tw-flex-col tw-items-center tw-justify-center"
|
||||
*ngIf="showWebauthnLogin$ | async"
|
||||
>
|
||||
<div class="tw-mb-3 tw-flex tw-flex-col tw-items-center tw-justify-center">
|
||||
<p class="tw-mb-3">{{ "or" | i18n }}</p>
|
||||
|
||||
<a
|
||||
|
@ -126,6 +126,4 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<app-webauthn-login-settings
|
||||
*ngIf="showWebauthnLoginSettings$ | async"
|
||||
></app-webauthn-login-settings>
|
||||
<app-webauthn-login-settings></app-webauthn-login-settings>
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@ -8,7 +7,6 @@ import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@ -35,8 +33,6 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
checkForBreaches = true;
|
||||
characterMinimumMessage = "";
|
||||
|
||||
protected showWebauthnLoginSettings$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
@ -68,10 +64,6 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showWebauthnLoginSettings$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PasswordlessLogin,
|
||||
);
|
||||
|
||||
if (!(await this.userVerificationService.hasMasterPassword())) {
|
||||
// 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Directive, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { Subject } from "rxjs";
|
||||
import { take, takeUntil } from "rxjs/operators";
|
||||
|
||||
import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } from "@bitwarden/auth/common";
|
||||
@ -54,7 +54,6 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
||||
protected twoFactorRoute = "2fa";
|
||||
protected successRoute = "vault";
|
||||
protected forcePasswordResetRoute = "update-temp-password";
|
||||
protected showWebauthnLogin$: Observable<boolean>;
|
||||
|
||||
protected destroy$ = new Subject<void>();
|
||||
|
||||
@ -90,8 +89,6 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showWebauthnLogin$ = this.webAuthnLoginService.enabled$;
|
||||
|
||||
this.route?.queryParams.pipe(takeUntil(this.destroy$)).subscribe((params) => {
|
||||
if (!params) {
|
||||
return;
|
||||
|
@ -864,7 +864,6 @@ import { ModalService } from "./modal.service";
|
||||
deps: [
|
||||
WebAuthnLoginApiServiceAbstraction,
|
||||
LoginStrategyServiceAbstraction,
|
||||
ConfigServiceAbstraction,
|
||||
WebAuthnLoginPrfCryptoServiceAbstraction,
|
||||
WINDOW,
|
||||
LogService,
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { AuthResult } from "../../models/domain/auth-result";
|
||||
import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view";
|
||||
import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view";
|
||||
@ -8,11 +6,6 @@ import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn
|
||||
* Service for logging in with WebAuthnLogin credentials.
|
||||
*/
|
||||
export abstract class WebAuthnLoginServiceAbstraction {
|
||||
/**
|
||||
* An Observable that emits a boolean indicating whether the WebAuthn login feature is enabled.
|
||||
*/
|
||||
readonly enabled$: Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Gets the credential assertion options needed for initiating the WebAuthn
|
||||
* authentication process. It should provide the challenge and other data
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { LoginStrategyServiceAbstraction, WebAuthnLoginCredentials } from "@bitwarden/auth/common";
|
||||
|
||||
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
@ -23,7 +21,6 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
const webAuthnLoginApiService = mock<WebAuthnLoginApiServiceAbstraction>();
|
||||
const loginStrategyService = mock<LoginStrategyServiceAbstraction>();
|
||||
const configService = mock<ConfigServiceAbstraction>();
|
||||
const webAuthnLoginPrfCryptoService = mock<WebAuthnLoginPrfCryptoServiceAbstraction>();
|
||||
const navigatorCredentials = mock<CredentialsContainer>();
|
||||
const logService = mock<LogService>();
|
||||
@ -71,12 +68,10 @@ describe("WebAuthnLoginService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
function createWebAuthnLoginService(config: { featureEnabled: boolean }): WebAuthnLoginService {
|
||||
configService.getFeatureFlag$.mockReturnValue(of(config.featureEnabled));
|
||||
function createWebAuthnLoginService(): WebAuthnLoginService {
|
||||
return new WebAuthnLoginService(
|
||||
webAuthnLoginApiService,
|
||||
loginStrategyService,
|
||||
configService,
|
||||
webAuthnLoginPrfCryptoService,
|
||||
window,
|
||||
logService,
|
||||
@ -84,34 +79,14 @@ describe("WebAuthnLoginService", () => {
|
||||
}
|
||||
|
||||
it("instantiates", () => {
|
||||
webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
webAuthnLoginService = createWebAuthnLoginService();
|
||||
expect(webAuthnLoginService).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("enabled$", () => {
|
||||
it("should emit true when feature flag for PasswordlessLogin is enabled", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
|
||||
// Act & Assert
|
||||
const result = await firstValueFrom(webAuthnLoginService.enabled$);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should emit false when feature flag for PasswordlessLogin is disabled", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: false });
|
||||
|
||||
// Act & Assert
|
||||
const result = await firstValueFrom(webAuthnLoginService.enabled$);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCredentialAssertionOptions()", () => {
|
||||
it("webAuthnLoginService returns WebAuthnLoginCredentialAssertionOptionsView when getCredentialAssertionOptions is called with the feature enabled", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
const webAuthnLoginService = createWebAuthnLoginService();
|
||||
|
||||
const challenge = "6CG3jqMCVASJVXySMi9KWw";
|
||||
const token = "BWWebAuthnLoginAssertionOptions_CfDJ_2KBN892w";
|
||||
@ -154,7 +129,7 @@ describe("WebAuthnLoginService", () => {
|
||||
describe("assertCredential(...)", () => {
|
||||
it("should assert the credential and return WebAuthnLoginAssertionView on success", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
const webAuthnLoginService = createWebAuthnLoginService();
|
||||
const credentialAssertionOptions = buildCredentialAssertionOptions();
|
||||
|
||||
// Mock webAuthnUtils functions
|
||||
@ -222,7 +197,7 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
it("should return undefined on non-PublicKeyCredential browser response", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
const webAuthnLoginService = createWebAuthnLoginService();
|
||||
const credentialAssertionOptions = buildCredentialAssertionOptions();
|
||||
|
||||
// Mock the navigatorCredentials.get to return null
|
||||
@ -237,7 +212,7 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
it("should log an error and return undefined when navigatorCredentials.get throws an error", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
const webAuthnLoginService = createWebAuthnLoginService();
|
||||
const credentialAssertionOptions = buildCredentialAssertionOptions();
|
||||
|
||||
// Mock navigatorCredentials.get to throw an error
|
||||
@ -269,7 +244,7 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
it("should accept an assertion with a signed challenge and use it to try and login", async () => {
|
||||
// Arrange
|
||||
const webAuthnLoginService = createWebAuthnLoginService({ featureEnabled: true });
|
||||
const webAuthnLoginService = createWebAuthnLoginService();
|
||||
const assertion = buildWebAuthnLoginCredentialAssertionView();
|
||||
const mockAuthResult: AuthResult = new AuthResult();
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { LoginStrategyServiceAbstraction, WebAuthnLoginCredentials } from "@bitwarden/auth/common";
|
||||
|
||||
import { FeatureFlag } from "../../../enums/feature-flag.enum";
|
||||
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { PrfKey } from "../../../types/key";
|
||||
import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction";
|
||||
@ -16,19 +12,15 @@ import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn
|
||||
import { WebAuthnLoginAssertionResponseRequest } from "./request/webauthn-login-assertion-response.request";
|
||||
|
||||
export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
|
||||
readonly enabled$: Observable<boolean>;
|
||||
|
||||
private navigatorCredentials: CredentialsContainer;
|
||||
|
||||
constructor(
|
||||
private webAuthnLoginApiService: WebAuthnLoginApiServiceAbstraction,
|
||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||
private configService: ConfigServiceAbstraction,
|
||||
private webAuthnLoginPrfCryptoService: WebAuthnLoginPrfCryptoServiceAbstraction,
|
||||
private window: Window,
|
||||
private logService?: LogService,
|
||||
) {
|
||||
this.enabled$ = this.configService.getFeatureFlag$(FeatureFlag.PasswordlessLogin, false);
|
||||
this.navigatorCredentials = this.window.navigator.credentials;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
export enum FeatureFlag {
|
||||
PasswordlessLogin = "passwordless-login",
|
||||
BrowserFilelessImport = "browser-fileless-import",
|
||||
ItemShare = "item-share",
|
||||
FlexibleCollectionsV1 = "flexible-collections-v-1", // v-1 is intentional
|
||||
|
Loading…
Reference in New Issue
Block a user