From 93676824c20481ef573b15a28dc72ce93c290369 Mon Sep 17 00:00:00 2001 From: Cesar Gonzalez Date: Thu, 17 Aug 2023 08:14:58 -0500 Subject: [PATCH] [PM-2907] Shopify Passkey Broken on Firefox When Extension is Installed (#6003) * [PM-2907] Shopify Passkey Broken on Firefox When Extension is Installed * [PM-2907] Shopify Passkey Broken on Firefox When Extension is Installed * [PM-2907] Shopify Passkey Broken on Firefox When Extension is Installed --- .../src/background/runtime.background.ts | 8 +- .../src/vault/fido2/content/content-script.ts | 127 ++++++++++-------- .../fido2/fido2-client.service.abstraction.ts | 1 + .../services/fido2/fido2-client.service.ts | 12 +- 4 files changed, 85 insertions(+), 63 deletions(-) diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index 3c2ac7a96cc..2636dedf5a2 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -52,7 +52,11 @@ export default class RuntimeBackground { sender: chrome.runtime.MessageSender, sendResponse: any ) => { - const messagesWithResponse = ["fido2RegisterCredentialRequest", "fido2GetCredentialRequest"]; + const messagesWithResponse = [ + "checkFido2FeatureEnabled", + "fido2RegisterCredentialRequest", + "fido2GetCredentialRequest", + ]; if (messagesWithResponse.includes(msg.command)) { this.processMessage(msg, sender).then( @@ -233,6 +237,8 @@ export default class RuntimeBackground { case "fido2AbortRequest": this.abortControllers.get(msg.abortedRequestId)?.abort(); break; + case "checkFido2FeatureEnabled": + return await this.main.fido2ClientService.isFido2FeatureEnabled(); case "fido2RegisterCredentialRequest": return await this.main.fido2ClientService .createCredential(msg.data, this.createAbortController(msg.requestId)) diff --git a/apps/browser/src/vault/fido2/content/content-script.ts b/apps/browser/src/vault/fido2/content/content-script.ts index 2fcf0bef900..eb266aff4d0 100644 --- a/apps/browser/src/vault/fido2/content/content-script.ts +++ b/apps/browser/src/vault/fido2/content/content-script.ts @@ -1,65 +1,80 @@ import { Message, MessageType } from "./messaging/message"; import { Messenger } from "./messaging/messenger"; -const s = document.createElement("script"); -s.src = chrome.runtime.getURL("content/fido2/page-script.js"); -(document.head || document.documentElement).appendChild(s); +function checkFido2FeatureEnabled() { + chrome.runtime.sendMessage( + { command: "checkFido2FeatureEnabled" }, + (response: { result?: boolean }) => initializeFido2ContentScript(response.result) + ); +} -const messenger = Messenger.forDOMCommunication(window); - -messenger.handler = async (message, abortController) => { - const abortHandler = () => - chrome.runtime.sendMessage({ - command: "fido2AbortRequest", - abortedRequestId: message.metadata.requestId, - }); - abortController.signal.addEventListener("abort", abortHandler); - - if (message.type === MessageType.CredentialCreationRequest) { - return new Promise((resolve, reject) => { - chrome.runtime.sendMessage( - { - command: "fido2RegisterCredentialRequest", - data: message.data, - requestId: message.metadata.requestId, - }, - (response) => { - if (response.error !== undefined) { - return reject(response.error); - } - - resolve({ - type: MessageType.CredentialCreationResponse, - result: response.result, - }); - } - ); - }); +function initializeFido2ContentScript(isFido2FeatureEnabled: boolean) { + if (isFido2FeatureEnabled !== true) { + return; } - if (message.type === MessageType.CredentialGetRequest) { - return new Promise((resolve, reject) => { - chrome.runtime.sendMessage( - { - command: "fido2GetCredentialRequest", - data: message.data, - requestId: message.metadata.requestId, - }, - (response) => { - if (response.error !== undefined) { - return reject(response.error); + const s = document.createElement("script"); + s.src = chrome.runtime.getURL("content/fido2/page-script.js"); + (document.head || document.documentElement).appendChild(s); + + const messenger = Messenger.forDOMCommunication(window); + + messenger.handler = async (message, abortController) => { + const abortHandler = () => + chrome.runtime.sendMessage({ + command: "fido2AbortRequest", + abortedRequestId: message.metadata.requestId, + }); + abortController.signal.addEventListener("abort", abortHandler); + + if (message.type === MessageType.CredentialCreationRequest) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage( + { + command: "fido2RegisterCredentialRequest", + data: message.data, + requestId: message.metadata.requestId, + }, + (response) => { + if (response.error !== undefined) { + return reject(response.error); + } + + resolve({ + type: MessageType.CredentialCreationResponse, + result: response.result, + }); } + ); + }); + } - resolve({ - type: MessageType.CredentialGetResponse, - result: response.result, - }); - } - ); - }).finally(() => - abortController.signal.removeEventListener("abort", abortHandler) - ) as Promise; - } + if (message.type === MessageType.CredentialGetRequest) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage( + { + command: "fido2GetCredentialRequest", + data: message.data, + requestId: message.metadata.requestId, + }, + (response) => { + if (response.error !== undefined) { + return reject(response.error); + } - return undefined; -}; + resolve({ + type: MessageType.CredentialGetResponse, + result: response.result, + }); + } + ); + }).finally(() => + abortController.signal.removeEventListener("abort", abortHandler) + ) as Promise; + } + + return undefined; + }; +} + +checkFido2FeatureEnabled(); diff --git a/libs/common/src/vault/abstractions/fido2/fido2-client.service.abstraction.ts b/libs/common/src/vault/abstractions/fido2/fido2-client.service.abstraction.ts index baefc6d509d..f888b5d6892 100644 --- a/libs/common/src/vault/abstractions/fido2/fido2-client.service.abstraction.ts +++ b/libs/common/src/vault/abstractions/fido2/fido2-client.service.abstraction.ts @@ -11,6 +11,7 @@ export abstract class Fido2ClientService { params: AssertCredentialParams, abortController?: AbortController ) => Promise; + isFido2FeatureEnabled: () => Promise; } export interface CreateCredentialParams { diff --git a/libs/common/src/vault/services/fido2/fido2-client.service.ts b/libs/common/src/vault/services/fido2/fido2-client.service.ts index 0932799a78b..4733010944a 100644 --- a/libs/common/src/vault/services/fido2/fido2-client.service.ts +++ b/libs/common/src/vault/services/fido2/fido2-client.service.ts @@ -34,13 +34,15 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction { private logService?: LogService ) {} + async isFido2FeatureEnabled(): Promise { + return await this.configService.getFeatureFlagBool(FeatureFlag.Fido2VaultCredentials); + } + async createCredential( params: CreateCredentialParams, abortController = new AbortController() ): Promise { - const enableFido2VaultCredentials = await this.configService.getFeatureFlagBool( - FeatureFlag.Fido2VaultCredentials - ); + const enableFido2VaultCredentials = await this.isFido2FeatureEnabled(); if (!enableFido2VaultCredentials) { this.logService?.warning(`[Fido2Client] Fido2VaultCredential is not enabled`); @@ -191,9 +193,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction { params: AssertCredentialParams, abortController = new AbortController() ): Promise { - const enableFido2VaultCredentials = await this.configService.getFeatureFlagBool( - FeatureFlag.Fido2VaultCredentials - ); + const enableFido2VaultCredentials = await this.isFido2FeatureEnabled(); if (!enableFido2VaultCredentials) { this.logService?.warning(`[Fido2Client] Fido2VaultCredential is not enabled`);