diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 3af124a99c..5bb52511dc 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -9,6 +9,7 @@ import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitw import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service"; import { EventService as EventServiceAbstraction } from "@bitwarden/common/abstractions/event.service"; import { ExportService as ExportServiceAbstraction } from "@bitwarden/common/abstractions/export.service"; +import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction"; import { Fido2Service as Fido2ServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2.service.abstraction"; import { FileUploadService as FileUploadServiceAbstraction } from "@bitwarden/common/abstractions/fileUpload.service"; import { FolderApiServiceAbstraction } from "@bitwarden/common/abstractions/folder/folder-api.service.abstraction"; @@ -99,6 +100,7 @@ import BrowserLocalStorageService from "../services/browserLocalStorage.service" import BrowserMessagingService from "../services/browserMessaging.service"; import BrowserMessagingPrivateModeBackgroundService from "../services/browserMessagingPrivateModeBackground.service"; import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service"; +import { BrowserFido2UserInterfaceService } from "../services/fido2/browser-fido2-user-interface.service"; import { FolderService } from "../services/folders/folder.service"; import I18nService from "../services/i18n.service"; import { KeyGenerationService } from "../services/keyGeneration.service"; @@ -117,6 +119,16 @@ import RuntimeBackground from "./runtime.background"; import TabsBackground from "./tabs.background"; import WebRequestBackground from "./webRequest.background"; +export class Fido2UserInterfaceService implements Fido2UserInterfaceServiceAbstraction { + async verifyUser(): Promise { + return false; + } + + async verifyPresence(): Promise { + return false; + } +} + export default class MainBackground { messagingService: MessagingServiceAbstraction; storageService: AbstractStorageService; @@ -167,6 +179,7 @@ export default class MainBackground { policyApiService: PolicyApiServiceAbstraction; userVerificationApiService: UserVerificationApiServiceAbstraction; syncNotifierService: SyncNotifierServiceAbstraction; + fido2UserInterfaceService: Fido2UserInterfaceServiceAbstraction; fido2Service: Fido2ServiceAbstraction; // Passed to the popup for Safari to workaround issues with theming, downloading, etc. @@ -355,7 +368,7 @@ export default class MainBackground { // AuthService should send the messages to the background not popup. send = (subscriber: string, arg: any = {}) => { const message = Object.assign({}, { command: subscriber }, arg); - that.runtimeBackground.processMessage(message, that, null); + that.runtimeBackground.processMessage(message, that); }; })(); this.authService = new AuthService( @@ -464,7 +477,8 @@ export default class MainBackground { this.userVerificationApiService ); - this.fido2Service = new Fido2Service(); + this.fido2UserInterfaceService = new BrowserFido2UserInterfaceService(this.popupUtilsService); + this.fido2Service = new Fido2Service(this.fido2UserInterfaceService); const systemUtilsServiceReloadCallback = () => { const forceWindowReload = diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 77146633cf..34d3d98c3b 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -334,7 +334,7 @@ export class NativeMessagingBackground { return; } - this.runtimeBackground.processMessage({ command: "unlocked" }, null, null); + this.runtimeBackground.processMessage({ command: "unlocked" }, null); } break; } diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index 3b7d4fe205..0839535bd0 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -47,16 +47,20 @@ export default class RuntimeBackground { sender: chrome.runtime.MessageSender, sendResponse: any ) => { - await this.processMessage(msg, sender, sendResponse); + const response = await this.processMessage(msg, sender); + sendResponse(response); }; - BrowserApi.messageListener("runtime.background", backgroundMessageListener); + BrowserApi.messageListener("runtime.background", (msg, sender, sendResponse) => { + backgroundMessageListener(msg, sender, sendResponse); + return true; + }); if (this.main.popupOnlyContext) { (window as any).bitwardenBackgroundMessageListener = backgroundMessageListener; } } - async processMessage(msg: any, sender: any, sendResponse: any) { + async processMessage(msg: any, sender: any): Promise { switch (msg.command) { case "loggedIn": case "unlocked": { @@ -205,11 +209,9 @@ export default class RuntimeBackground { this.platformUtilsService.copyToClipboard(msg.identifier, { window: window }); break; case "fido2RegisterCredentialRequest": - sendResponse(await this.main.fido2Service.createCredential(msg.data)); - break; - default: - break; + return await this.main.fido2Service.createCredential(msg.data); } + return undefined; } private async autofillPage(tabToAutoFill: chrome.tabs.Tab) { diff --git a/apps/browser/src/browser/browserApi.ts b/apps/browser/src/browser/browserApi.ts index d64231833d..8cda35125b 100644 --- a/apps/browser/src/browser/browserApi.ts +++ b/apps/browser/src/browser/browserApi.ts @@ -126,13 +126,21 @@ export class BrowserApi { chrome.tabs.create({ url: url, active: active }); } + static createNewWindow( + url: string, + focused = true, + type: chrome.windows.createTypeEnum = "normal" + ) { + chrome.windows.create({ url, focused, type }); + } + static messageListener( name: string, - callback: (message: any, sender: chrome.runtime.MessageSender, response: any) => void + callback: (message: any, sender: chrome.runtime.MessageSender, response: any) => unknown ) { chrome.runtime.onMessage.addListener( (msg: any, sender: chrome.runtime.MessageSender, response: any) => { - callback(msg, sender, response); + return callback(msg, sender, response); } ); } diff --git a/apps/browser/src/popup/services/popup-utils.service.ts b/apps/browser/src/popup/services/popup-utils.service.ts index c224f417a3..d46a337cbe 100644 --- a/apps/browser/src/popup/services/popup-utils.service.ts +++ b/apps/browser/src/popup/services/popup-utils.service.ts @@ -67,7 +67,7 @@ export class PopupUtilsService { height: Math.round(bodyRect.height || 600), }); - if (this.inPopup(win)) { + if (win && this.inPopup(win)) { BrowserApi.closePopup(win); } } else if (typeof chrome !== "undefined" && chrome.tabs && chrome.tabs.create) { 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 new file mode 100644 index 0000000000..156ba86cab --- /dev/null +++ b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts @@ -0,0 +1,43 @@ +import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction"; + +import { BrowserApi } from "../../browser/browserApi"; +import { PopupUtilsService } from "../../popup/services/popup-utils.service"; + +const BrowserFido2MessageName = "BrowserFido2UserInterfaceServiceMessage"; + +type BrowserFido2Message = { + type: "VerifyUserRequest"; + id: string; +}; + +export interface BrowserFido2UserInterfaceRequestData { + requestId: string; +} + +export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServiceAbstraction { + constructor(private popupUtilsService: PopupUtilsService) { + BrowserApi.messageListener(BrowserFido2MessageName, this.processMessage.bind(this)); + } + + async verifyUser(): Promise { + return false; + } + + 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)); + } + + 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); + } +} diff --git a/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts b/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts new file mode 100644 index 0000000000..b49c565e47 --- /dev/null +++ b/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts @@ -0,0 +1,4 @@ +export abstract class Fido2UserInterfaceService { + verifyUser: () => Promise; + verifyPresence: () => Promise; +} diff --git a/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts b/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts index 767925915d..3b6e4e0c54 100644 --- a/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts +++ b/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts @@ -34,6 +34,6 @@ export interface CredentialRegistrationParams { } export abstract class Fido2Service { - createCredential: (params: CredentialRegistrationParams) => unknown; + createCredential: (params: CredentialRegistrationParams) => Promise; assertCredential: () => unknown; } diff --git a/libs/common/src/services/fido2/fido2.service.ts b/libs/common/src/services/fido2/fido2.service.ts index 38aef54891..1eae23f6bf 100644 --- a/libs/common/src/services/fido2/fido2.service.ts +++ b/libs/common/src/services/fido2/fido2.service.ts @@ -1,10 +1,14 @@ +import { Fido2UserInterfaceService } from "../../abstractions/fido2/fido2-user-interface.service.abstraction"; import { CredentialRegistrationParams, Fido2Service as Fido2ServiceAbstraction, } from "../../abstractions/fido2/fido2.service.abstraction"; export class Fido2Service implements Fido2ServiceAbstraction { - createCredential(params: CredentialRegistrationParams): unknown { + constructor(private fido2UserInterfaceService: Fido2UserInterfaceService) {} + + async createCredential(params: CredentialRegistrationParams): Promise { + await this.fido2UserInterfaceService.verifyPresence(); // eslint-disable-next-line no-console console.log("Fido2Service.registerCredential", params); return "createCredential response"; diff --git a/libs/common/src/services/fido2/noop-fido2-user-interface.service.ts b/libs/common/src/services/fido2/noop-fido2-user-interface.service.ts new file mode 100644 index 0000000000..ddd1c4e21d --- /dev/null +++ b/libs/common/src/services/fido2/noop-fido2-user-interface.service.ts @@ -0,0 +1,11 @@ +import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "../../abstractions/fido2/fido2-user-interface.service.abstraction"; + +export class Fido2UserInterfaceService implements Fido2UserInterfaceServiceAbstraction { + async verifyUser(): Promise { + return false; + } + + async verifyPresence(): Promise { + return false; + } +}