We would like to show a notification for users to perform the user presence gesture (e.g. touch the button) on USB devices so that there's a visual indication on the screen of what to do next. (The device itself should be in "wink" mode, but having it on screen would be helpful.)
We have code in libwebauthn that emits this, seemingly at the right time, according to logs, but the credential service doesn't receive it until about 20 seconds later. This seems to be some timeout issue/race condition.
Starting...
Starting credential service... ✅
Starting GUI thread... ✅
Starting D-Bus service... ✅
Waiting for messages...
2025-06-05T17:48:01.197050Z INFO xyz_iinuwa_credential_manager_portal_gtk::application: Credential Manager (xyz.iinuwa.CredentialManagerUi.Devel)
2025-06-05T17:48:01.197079Z INFO xyz_iinuwa_credential_manager_portal_gtk::application: Version: 0.1.0-90c2dd3 (Devel)
2025-06-05T17:48:01.197085Z INFO xyz_iinuwa_credential_manager_portal_gtk::application: Datadir: /home/isaiah/Development/rust/linux-webauthn-platform-api/build/xyz-iinuwa-credential-manager-portal-gtk/data/resources
2025-06-05T17:48:01.198326Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::application::imp: GtkApplication<ExampleApplication>::startup
2025-06-05T17:48:01.323066Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::application::imp: GtkApplication<ExampleApplication>::activate
Device { id: "0", transport: Usb }
Selected device 0
2025-06-05T17:48:03.279785Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: polling for USB status
2025-06-05T17:48:03.279828Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: current usb state: Idle
2025-06-05T17:48:03.286309Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: current usb state: Connected(HidDevice { backend: HidApiDevice(HidDeviceInfo { vendor_id: 4617, product_id: 48878 }) })
2025-06-05T17:48:03.286404Z INFO xyz_iinuwa_credential_manager_portal_gtk::view_model: Found USB device
2025-06-05T17:48:03.350957Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}:_negotiate_protocol: libwebauthn::webauthn: Selected protocol: FIDO2
2025-06-05T17:48:03.390799Z INFO webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Credential list BEFORE preflight: [Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }]
2025-06-05T17:48:03.582448Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Pre-flight: Found already known credential Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }
2025-06-05T17:48:03.582534Z INFO webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Credential list AFTER preflight: [Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }]
2025-06-05T17:48:03.638575Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}:user_verification:user_verification_helper: libwebauthn::webauthn: Checking if user verification is required rp_uv_preferred=true dev_uv_protected=true uv=true
2025-06-05T17:48:03.650791Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}:user_verification:user_verification_helper: libwebauthn::transport::channel: Sending state update: PinRequired(PinRequiredUpdate { reply_to: Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: false, is_tx_task_set: false } }) }, reason: RelyingPartyRequest, attempts_left: Some(8) })
2025-06-05T17:48:03.651118Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: current usb state: NeedsPin { attempts_left: Some(8), pin_tx: Sender { chan: Tx { inner: Chan { tx: Tx { block_tail: 0x7fffac00ea70, tail_position: 0 }, semaphore: Semaphore { semaphore: Semaphore { permits: 1 }, bound: 1 }, rx_waker: AtomicWaker, tx_count: 2, rx_fields: "..." } } } }
# I type in my PIN here and immediately get the below line
2025-06-05T17:48:06.207109Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::transport::channel: Sending state update: PresenceRequired
# Even though libwebauthn sends the data, the cred service doesn't see it, and so the GUI doesn't update. Notably, the device IS winking, and if I push it, the cred service skips to the Completed state and releases the credential properly
# 30 seconds pass, and it retries the operation
2025-06-05T17:48:36.499156Z WARN xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: Retrying WebAuthn get credential operation
2025-06-05T17:48:36.499223Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}:_negotiate_protocol: libwebauthn::webauthn: Selected protocol: FIDO2
2025-06-05T17:48:36.526780Z INFO webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Credential list BEFORE preflight: [Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }]
2025-06-05T17:48:36.723123Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Pre-flight: Found already known credential Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }
2025-06-05T17:48:36.723248Z INFO webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::proto::ctap2::preflight: Credential list AFTER preflight: [Ctap2PublicKeyCredentialDescriptor { id: [...], type: PublicKey, transports: None }]
# Device is still in winking for user presence state, so we skip the PIN this time.
# PresenceRequired emitted again from libwebauthn below.
2025-06-05T17:48:36.753117Z DEBUG webauthn_get_assertion{dev=SoloKeys Solo 2 Security Key (r964)}: libwebauthn::transport::channel: Sending state update: PresenceRequired
2025-06-05T17:48:36.753297Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: current usb state: NeedsUserPresence
# ^ now the cred service and GUI see the NeedsUserPresence state
# I got distracted and waited a while to push the button, so the delay between the above line and the one below is not important
2025-06-05T17:48:45.492149Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: USB update channel closed.
2025-06-05T17:48:45.492201Z DEBUG xyz_iinuwa_credential_manager_portal_gtk::credential_service::usb: Reached end of USB update task
We would like to show a notification for users to perform the user presence gesture (e.g. touch the button) on USB devices so that there's a visual indication on the screen of what to do next. (The device itself should be in "wink" mode, but having it on screen would be helpful.)
We have code in libwebauthn that emits this, seemingly at the right time, according to logs, but the credential service doesn't receive it until about 20 seconds later. This seems to be some timeout issue/race condition.
See logs (omitted credential ID for brevity):