diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts
index d20a914249..1f12bb7062 100644
--- a/apps/browser/src/popup/app-routing.module.ts
+++ b/apps/browser/src/popup/app-routing.module.ts
@@ -17,6 +17,7 @@ import { SsoComponent } from "./accounts/sso.component";
import { TwoFactorOptionsComponent } from "./accounts/two-factor-options.component";
import { TwoFactorComponent } from "./accounts/two-factor.component";
import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component";
+import { Fido2Component } from "./fido2/fido2.component";
import { GeneratorComponent } from "./generator/generator.component";
import { PasswordGeneratorHistoryComponent } from "./generator/password-generator-history.component";
import { SendAddEditComponent } from "./send/send-add-edit.component";
@@ -59,6 +60,10 @@ const routes: Routes = [
canActivate: [UnauthGuard],
data: { state: "home" },
},
+ {
+ path: "fido2",
+ component: Fido2Component,
+ },
{
path: "login",
component: LoginComponent,
diff --git a/apps/browser/src/popup/fido2/fido2.component.html b/apps/browser/src/popup/fido2/fido2.component.html
new file mode 100644
index 0000000000..7001d76a7b
--- /dev/null
+++ b/apps/browser/src/popup/fido2/fido2.component.html
@@ -0,0 +1,4 @@
+
+ A site is asking for authentication
+
+
diff --git a/apps/browser/src/popup/fido2/fido2.component.ts b/apps/browser/src/popup/fido2/fido2.component.ts
new file mode 100644
index 0000000000..ea1ee36cc5
--- /dev/null
+++ b/apps/browser/src/popup/fido2/fido2.component.ts
@@ -0,0 +1,38 @@
+import { Component, HostListener } from "@angular/core";
+import { ActivatedRoute } from "@angular/router";
+
+import {
+ BrowserFido2Message,
+ BrowserFido2UserInterfaceService,
+} from "../../services/fido2/browser-fido2-user-interface.service";
+
+@Component({
+ selector: "app-fido2",
+ templateUrl: "fido2.component.html",
+ styleUrls: [],
+})
+export class Fido2Component {
+ constructor(private activatedRoute: ActivatedRoute) {}
+
+ get data() {
+ return this.activatedRoute.snapshot.queryParams as BrowserFido2Message;
+ }
+
+ async verify() {
+ const data = this.data;
+ BrowserFido2UserInterfaceService.sendMessage({
+ requestId: data.requestId,
+ type: "VerifyUserResponse",
+ });
+ window.close();
+ }
+
+ @HostListener("window:unload")
+ unloadHandler() {
+ const data = this.data;
+ BrowserFido2UserInterfaceService.sendMessage({
+ requestId: data.requestId,
+ type: "RequestCancelled",
+ });
+ }
+}
diff --git a/apps/browser/src/popup/scss/base.scss b/apps/browser/src/popup/scss/base.scss
index 8803c73aa6..b2d0d0fea2 100644
--- a/apps/browser/src/popup/scss/base.scss
+++ b/apps/browser/src/popup/scss/base.scss
@@ -589,3 +589,21 @@ main {
position: relative;
}
}
+
+app-fido2 {
+ .auth-wrapper {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+
+ .btn {
+ margin-top: 25px;
+ }
+ }
+}
diff --git a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts
index 156ba86cab..3088063f0f 100644
--- a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts
+++ b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts
@@ -1,20 +1,37 @@
+import { filter, first, lastValueFrom, Subject, takeUntil } from "rxjs";
+
import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction";
+import { Utils } from "@bitwarden/common/misc/utils";
import { BrowserApi } from "../../browser/browserApi";
import { PopupUtilsService } from "../../popup/services/popup-utils.service";
const BrowserFido2MessageName = "BrowserFido2UserInterfaceServiceMessage";
-type BrowserFido2Message = {
- type: "VerifyUserRequest";
- id: string;
-};
+export type BrowserFido2Message = { requestId: string } & (
+ | {
+ type: "VerifyUserRequest";
+ }
+ | {
+ type: "VerifyUserResponse";
+ }
+ | {
+ type: "RequestCancelled";
+ }
+);
export interface BrowserFido2UserInterfaceRequestData {
requestId: string;
}
export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServiceAbstraction {
+ static sendMessage(msg: BrowserFido2Message) {
+ BrowserApi.sendMessage(BrowserFido2MessageName, msg);
+ }
+
+ private messages$ = new Subject();
+ private destroy$ = new Subject();
+
constructor(private popupUtilsService: PopupUtilsService) {
BrowserApi.messageListener(BrowserFido2MessageName, this.processMessage.bind(this));
}
@@ -24,20 +41,27 @@ export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServi
}
async verifyPresence(): Promise {
- // eslint-disable-next-line no-console
- console.log("User Presence Verification requested");
- const id = "test";
- this.popupUtilsService.popOut(null, `popup/index.html?uilocation=popout#/fido2?id=${id}`);
- return await new Promise((resolve) => setTimeout(resolve, 60000));
+ const requestId = Utils.newGuid();
+ const data: BrowserFido2Message = { type: "VerifyUserRequest", requestId };
+ const queryParams = new URLSearchParams(data).toString();
+ this.popupUtilsService.popOut(null, `popup/index.html?uilocation=popout#/fido2?${queryParams}`);
+
+ const response = await lastValueFrom(
+ this.messages$.pipe(
+ filter((msg) => msg.requestId === requestId),
+ first(),
+ takeUntil(this.destroy$)
+ )
+ );
+
+ if (response.type === "VerifyUserResponse") {
+ return true;
+ }
+
+ return false;
}
private processMessage(msg: BrowserFido2Message) {
- // eslint-disable-next-line no-console
- console.log("BrowserFido2UserInterfaceService.processMessage", { msg });
- }
-
- private sendMessage(msg: BrowserFido2Message) {
- chrome.runtime.sendMessage({ test: "wat" });
- BrowserApi.sendMessage(BrowserFido2MessageName, msg);
+ this.messages$.next(msg);
}
}