Skip to content

Passkeys fallback: wait the window.onfocus event#2810

Open
a2kolbasov wants to merge 2 commits intokeepassxreboot:developfrom
a2kolbasov:passkeys/fallback-delay
Open

Passkeys fallback: wait the window.onfocus event#2810
a2kolbasov wants to merge 2 commits intokeepassxreboot:developfrom
a2kolbasov:passkeys/fallback-delay

Conversation

@a2kolbasov
Copy link
Copy Markdown
Contributor

@a2kolbasov a2kolbasov commented Dec 30, 2025

Some browsers (like Firefox) reject requests to navigator.credentials.create/get if the page is out of focus (meaning the built-in functionality -- the originalCredentials variable). When the user selects a passkey in KeePassXC-desktop, there is no focus on the page. When the request is canceled, a race begins between whether the focus returns to the page and whether the originalCredentials call occurs. It depends on the operating system's window manager.

If the user starts switching windows during the request, and when canceling the request, focus is returned to a non-browser, the browser will reject the request regardless of the OS.

Resolves #2493

Screenshots or videos

Testing strategy

As in #2493 (comment).

It is also possible at the time of the Passkey request:

  1. Do not cancel it
  2. Return to the browser and focus on the Web Console (click on the code entry field), docking option is not "Separate Window")
  3. Return to KeePassXC and cancel the request

The focus will return in DevTools and the browser will reject the request.

If you need to call the built-in library in Firefox to work with USB keys, regardless of the OS: go to about:config, set security.webauth.webauthn_enable_softtoken to true.

Type of change

  • ✅ Bug fix (non-breaking change that fixes an issue)

@varjolintu
Copy link
Copy Markdown
Member

This is clearly some bug in Firefox itself.

@droidmonkey
Copy link
Copy Markdown
Member

This is an ugly workaround to what is ultimately browser behavior. The behavior should be reported to mozilla for correction.

@a2kolbasov
Copy link
Copy Markdown
Contributor Author

Chrome behaves differently, but still in a similar way.

Disable keepassxc-browser, go to https://github.com/login, execute

setTimeout(() => document.querySelector('.js-webauthn-confirm-button').click(), 5_000)

, switch to another tab and wait for the timer to expire. When you return, you will see the same error in the console.


Browsers block requests from inactive pages, but they define its activity differently.

The call from the password manager is no different (for browsers) from the code on the page that calls navigator.credentials.get.

And the spoof of navigator.credentials itself is generally ugly too. But this is a hack due to the fact that browsers do not provide an API similar to the API for HTTP Auth (or the like).


And here are examples from the WebAuthn specification:

@a2kolbasov a2kolbasov force-pushed the passkeys/fallback-delay branch from d502ca2 to 800d831 Compare January 13, 2026 17:01
@a2kolbasov a2kolbasov marked this pull request as ready for review January 13, 2026 17:04
@a2kolbasov a2kolbasov marked this pull request as draft January 14, 2026 21:03
@a2kolbasov a2kolbasov force-pushed the passkeys/fallback-delay branch from 800d831 to 7c6b3bf Compare January 16, 2026 00:43
@a2kolbasov
Copy link
Copy Markdown
Contributor Author

The same thing happens in Safari. The video shows:

  1. If the focus is on DevTools
  2. If the focus is on window.top instead of window.self.
safari.mp4

tested on a self-written site via BrowserStack, MacOS Tahoe, Safari 26.2


I conducted additional testing. document.hasFocus() returns true in all iframes, regardless of which one is being checked (document.hasFocus() === window.top.document.hasFocus() always). However, the focus event does not pass through an iframe. When switching between applications, the focus returns to the last active iframe (where the WebAuthn call was made), and the event should be handled on that iframe.

I also replaced a callback with await Promse<void>.

@a2kolbasov a2kolbasov marked this pull request as ready for review January 16, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"passkeys fallback" doesn't appear to work as advertised

3 participants