From 9e5a936e2a371ec9a05b17b8cd0b4b98f33e85a9 Mon Sep 17 00:00:00 2001 From: Aleksandr Kolbasov Date: Tue, 30 Dec 2025 02:29:31 +0300 Subject: [PATCH 1/2] Remove the double check for fallback --- keepassxc-browser/content/passkeys.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/keepassxc-browser/content/passkeys.js b/keepassxc-browser/content/passkeys.js index e2e6217..c596eb9 100644 --- a/keepassxc-browser/content/passkeys.js +++ b/keepassxc-browser/content/passkeys.js @@ -203,8 +203,9 @@ if (!response.publicKey) { if (!response.fallback) { throwError(response?.errorCode, response?.errorMessage); + return null; } - return response.fallback ? originalCredentials.create(options) : null; + return originalCredentials.create(options); } return createPublicKeyCredential(response.publicKey); @@ -228,8 +229,9 @@ if (!response.publicKey) { if (!response.fallback) { throwError(response?.errorCode, response?.errorMessage); + return null; } - return response.fallback ? originalCredentials.get(options) : null; + return originalCredentials.get(options); } return createPublicKeyCredential(response.publicKey); From 7c6b3bff0a063be1f302b21702b6ca1c9933de71 Mon Sep 17 00:00:00 2001 From: Aleksandr Kolbasov Date: Fri, 16 Jan 2026 03:35:47 +0300 Subject: [PATCH 2/2] Waiting for the focus to return from KeePassXC-desktop back to the page --- keepassxc-browser/content/passkeys.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/keepassxc-browser/content/passkeys.js b/keepassxc-browser/content/passkeys.js index c596eb9..9f3c6b1 100644 --- a/keepassxc-browser/content/passkeys.js +++ b/keepassxc-browser/content/passkeys.js @@ -145,6 +145,29 @@ } }; + /** + * @returns {Promise} + */ + const waitForFocus = function () { + /* + Some browsers (Firefox, Safari) reject requests to original `navigator.credentials.create/get` if the page + is out of focus (when the user selects a passkey in KeePassXC-desktop). + + `document.visibilityState` is not suitable: if the page is visible, but the focus is on another application + (or DevTools), the request will be rejected. + */ + return new Promise((resolve) => { + if (document.hasFocus()) { + return resolve(); + } + document.addEventListener( + 'focus', + () => resolve(), + { capture: true, passive: true, once: true } + ); + }); + }; + // Throws errors to a correct exceptions const throwError = function(errorCode, errorMessage) { if ((!errorCode && !errorMessage) || errorCode === PASSKEYS_REQUEST_CANCELED) { @@ -205,6 +228,7 @@ throwError(response?.errorCode, response?.errorMessage); return null; } + await waitForFocus(); return originalCredentials.create(options); } @@ -231,6 +255,7 @@ throwError(response?.errorCode, response?.errorMessage); return null; } + await waitForFocus(); return originalCredentials.get(options); }