Skip to content

Commit cef8cd0

Browse files
committed
Add 'Failed' USB state
1 parent 88d4004 commit cef8cd0

3 files changed

Lines changed: 29 additions & 34 deletions

File tree

  • xyz-iinuwa-credential-manager-portal-gtk/src

xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pub enum Error {
199199
AuthenticatorError,
200200
NoCredentials,
201201
PinAttemptsExhausted,
202-
UserVerficiationAttemptsExhausted,
202+
// TODO: We may want to hide the details on this variant from the public API.
203203
Internal(String),
204204
}
205205

xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/usb.rs

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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

460463
impl 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 {

xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,7 @@ impl<C: CredentialServiceClient + Send> ViewModel<C> {
235235
}
236236
}
237237

238-
Event::Background(BackgroundEvent::UsbPressed) => {
239-
println!("UsbPressed");
240-
}
241238
Event::Background(BackgroundEvent::UsbStateChanged(state)) => {
242-
// TODO: do we need to store the USB state?
243239
match state {
244240
UsbState::Connected => {
245241
info!("Found USB device")
@@ -284,6 +280,10 @@ impl<C: CredentialServiceClient + Send> ViewModel<C> {
284280
.await
285281
.unwrap();
286282
}
283+
// TODO: Provide more specific error messages using the wrapped Error.
284+
UsbState::Failed(_) => {
285+
self.tx_update.send(ViewUpdate::Failed).await.unwrap()
286+
}
287287
}
288288
}
289289
Event::Background(BackgroundEvent::HybridQrStateChanged(state)) => {
@@ -361,7 +361,6 @@ pub enum ViewUpdate {
361361
}
362362

363363
pub enum BackgroundEvent {
364-
UsbPressed,
365364
UsbStateChanged(UsbState),
366365
HybridQrStateChanged(HybridState),
367366
}

0 commit comments

Comments
 (0)