Skip to content

fix: send CTAPHID_KEEPALIVE while CTAP2 requests are pending - #43

Open
Xart3mis wants to merge 1 commit into
matejsmycka:mainfrom
Xart3mis:fix/ctaphid-keepalive
Open

Xart3mis wants to merge 1 commit into
matejsmycka:mainfrom
Xart3mis:fix/ctaphid-keepalive

Conversation

@Xart3mis

@Xart3mis Xart3mis commented Nov 5, 2026

Copy link
Copy Markdown

Registering a passkey with --auth fprintd fails in Firefox on Linux most of the time. Firefox shows "The request is not allowed by the user agent or the platform in the current context", while linux-id logs MakeCredential ok for the same request.

Firefox's HID transport (authenticator-rs, src/transport/linux/device.rs) gives up on a read after 2 seconds and expects the authenticator to send CTAPHID_KEEPALIVE while it works. CTAP 2.1 §11.2.9.1.4 says to send one every 100 ms. linux-id never sends any, so a request that takes longer than 2s gets dropped. A fingerprint scan plus the TPM signing step takes 2 to 13 seconds on my machine. The only registrations that went through were the ones that hit the 5s UV cache and answered in under a second.

With this change, MakeCredential and GetAssertion send a keepalive (status PROCESSING) every 100 ms until the reply is written. The keepalive goroutine is stopped and joined before the reply goes out, so no keepalive frame can follow it. If a handler returns without replying, the deferred halt still stops the goroutine.

withKeepalive only does anything when the responder implements WriteKeepalive, so the existing test fakes didn't need changes. I added TestHandleCtap2_SendsKeepaliveUntilReply, which holds the verifier for 500 ms and checks that only keepalives come before the reply and nothing comes after it.

Testing: go test ./... passes. I built the AUR package with this patch and installed it. Registering and signing in on webauthn.io with fprintd now works on the first try.

CTAPHID_CANCEL is still unsupported. I left that out to keep this change small.

Firefox on Linux stops reading from a HID authenticator after 2s of
silence. A fingerprint scan plus the TPM signature often takes longer
than that, so registration failed in the browser even though linux-id
logged MakeCredential ok.

MakeCredential and GetAssertion now send a PROCESSING keepalive every
100 ms until the reply is written.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant