@@ -221,7 +221,6 @@ impl InProcessUsbHandler {
221221 } ,
222222 None => Err ( Error :: Internal ( "USB UV handler channel closed" . to_string ( ) ) ) ,
223223 } ,
224- UsbStateInternal :: Completed ( _) => Ok ( prev_usb_state) ,
225224 UsbStateInternal :: SelectCredential {
226225 response,
227226 cred_tx : _,
@@ -264,14 +263,13 @@ impl InProcessUsbHandler {
264263 ) )
265264 }
266265 } ,
266+ UsbStateInternal :: Completed ( _) => break Ok ( ( ) ) ,
267+ UsbStateInternal :: Failed ( err) => break Err ( err) ,
267268 } ;
268- state = next_usb_state? ;
269+ state = next_usb_state. map_or_else ( |err| UsbStateInternal :: Failed ( err ) , |s| s ) ;
269270 tx. send ( state. clone ( ) ) . await . map_err ( |_| {
270271 Error :: Internal ( "USB state channel receiver closed prematurely" . to_string ( ) )
271272 } ) ?;
272- if let UsbStateInternal :: Completed ( _) = state {
273- break Ok ( ( ) ) ;
274- }
275273 }
276274 }
277275}
@@ -330,6 +328,7 @@ async fn handle_events(
330328 }
331329 }
332330 . map_err ( |err| match err {
331+ WebAuthnError :: Ctap ( CtapError :: PINAuthBlocked ) => Error :: PinAttemptsExhausted ,
333332 WebAuthnError :: Ctap ( CtapError :: NoCredentials ) => Error :: NoCredentials ,
334333 _ => Error :: AuthenticatorError ,
335334 } ) ;
@@ -378,6 +377,10 @@ pub(super) enum UsbStateInternal {
378377 /// Awaiting FIDO USB device to be plugged in.
379378 Waiting ,
380379
380+ /// When we encounter multiple devices, we let all of them blink and continue
381+ /// with the one that was tapped.
382+ SelectingDevice ( Vec < HidDevice > ) ,
383+
381384 /// USB device connected, prompt user to tap
382385 Connected ( HidDevice ) ,
383386
@@ -388,28 +391,25 @@ pub(super) enum UsbStateInternal {
388391 } ,
389392
390393 /// The device needs on-device user verification.
391- NeedsUserVerification {
392- attempts_left : Option < u32 > ,
393- } ,
394+ NeedsUserVerification { attempts_left : Option < u32 > } ,
394395
395396 /// The device needs evidence of user presence (e.g. touch) to release the credential.
396397 NeedsUserPresence ,
397398
398- // Multiple credentials have been found and the user has to select which to use
399+ /// Multiple credentials have been found and the user has to select which to use
399400 SelectCredential {
400401 response : GetAssertionResponse ,
401402 cred_tx : mpsc:: Sender < String > ,
402403 } ,
403404
404405 /// USB tapped, received credential
405406 Completed ( CredentialResponse ) ,
407+
408+ /// There was an error while interacting with the authenticator.
409+ Failed ( Error ) ,
406410 // TODO: implement cancellation
407411 // This isn't actually sent from the server.
408412 //UserCancelled,
409-
410- // When we encounter multiple devices, we let all of them blink and continue
411- // with the one that was tapped.
412- SelectingDevice ( Vec < HidDevice > ) ,
413413}
414414
415415/// Used to share public state between credential service and UI.
@@ -422,6 +422,10 @@ pub enum UsbState {
422422 /// Awaiting FIDO USB device to be plugged in.
423423 Waiting ,
424424
425+ // When we encounter multiple devices, we let all of them blink and continue
426+ // with the one that was tapped.
427+ SelectingDevice ,
428+
425429 /// USB device connected, prompt user to tap
426430 Connected ,
427431
@@ -438,23 +442,22 @@ pub enum UsbState {
438442
439443 /// The device needs evidence of user presence (e.g. touch) to release the credential.
440444 NeedsUserPresence ,
441-
442- /// USB tapped, received credential
443- Completed ,
444445 // TODO: implement cancellation
445446 // This isn't actually sent from the server.
446447 //UserCancelled,
447448
448- // When we encounter multiple devices, we let all of them blink and continue
449- // with the one that was tapped.
450- SelectingDevice ,
451-
452449 // Multiple credentials have been found and the user has to select which to use
453450 // List of user-identities to decide which to use.
454451 SelectCredential {
455452 creds : Vec < Credential > ,
456453 cred_tx : mpsc:: Sender < String > ,
457454 } ,
455+
456+ /// USB tapped, received credential
457+ Completed ,
458+
459+ /// Interaction with the authenticator failed.
460+ Failed ( Error ) ,
458461}
459462
460463impl From < UsbStateInternal > for UsbState {
@@ -509,6 +512,7 @@ impl From<UsbStateInternal> for UsbState {
509512 cred_tx,
510513 }
511514 }
515+ UsbStateInternal :: Failed ( err) => UsbState :: Failed ( err) ,
512516 }
513517 }
514518}
@@ -532,14 +536,6 @@ async fn handle_usb_updates(
532536 }
533537 }
534538 UxUpdate :: PinRequired ( pin_update) => {
535- if pin_update. attempts_left . is_some_and ( |num| num <= 1 ) {
536- // TODO: cancel authenticator operation
537- // Err("No more PIN attempts allowed. Select a different authenticator or try again later.".to_string())
538- if let Err ( err) = signal_tx. send ( Err ( Error :: PinAttemptsExhausted ) ) . await {
539- tracing:: error!( "Authenticator cannot process anymore PIN requests, but we cannot relay the message to credential service: {:?}" , err) ;
540- }
541- continue ;
542- }
543539 let ( pin_tx, mut pin_rx) = mpsc:: channel ( 1 ) ;
544540 if let Err ( err) = signal_tx
545541 . send ( Ok ( UsbUvMessage :: NeedsPin {
0 commit comments