From 288908c33758faea27956aa5e830de64db5fef1f Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Wed, 30 Apr 2025 07:44:51 +0200 Subject: [PATCH 1/3] Implement "Select devices" flow --- .../Cargo.lock | 2 +- .../Cargo.toml | 2 +- .../src/credential_service/mod.rs | 78 +++++++++++++++---- .../src/view_model/gtk/mod.rs | 46 +++++++---- .../src/view_model/mod.rs | 78 ++++++++++++------- 5 files changed, 149 insertions(+), 57 deletions(-) diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock index 535978d..3586ad1 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock @@ -1950,7 +1950,7 @@ dependencies = [ [[package]] name = "libwebauthn" version = "0.1.2" -source = "git+https://github.com/linux-credentials/libwebauthn?rev=dc23daed528f512f2bcb61fce9eb6b8ee74066e2#dc23daed528f512f2bcb61fce9eb6b8ee74066e2" +source = "git+https://github.com/linux-credentials/libwebauthn?rev=7efdc9324039ea7776a3a71a79d087f791b1ed91#7efdc9324039ea7776a3a71a79d087f791b1ed91" dependencies = [ "aes", "async-trait", diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml index 6b643aa..1bf2b0b 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml @@ -20,7 +20,7 @@ serde_json = "1.0.140" tracing = "0.1.41" tracing-subscriber = "0.3" zbus = "5.5.0" -libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "dc23daed528f512f2bcb61fce9eb6b8ee74066e2" } +libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "7efdc9324039ea7776a3a71a79d087f791b1ed91" } async-trait = "0.1.88" tokio = { version = "1", features = ["rt-multi-thread"] } diff --git a/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs b/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs index 0106e0c..e49a653 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs +++ b/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs @@ -7,7 +7,7 @@ use std::{ use libwebauthn::{ self, ops::webauthn::{GetAssertionResponse, MakeCredentialResponse}, - transport::Device as _, + transport::{hid::HidDevice, Device as _}, webauthn::{Error as WebAuthnError, WebAuthn}, UxUpdate, }; @@ -35,6 +35,8 @@ pub struct CredentialService { usb_state: AsyncArc>, usb_uv_handler: UsbUvHandler, + internal_hid_devices: Vec, + chosen_hid_device: Option, internal_device_credentials: Vec, internal_device_state: InternalDeviceState, internal_pin_attempts_left: u32, @@ -81,6 +83,7 @@ impl CredentialService { usb_state: usb_state.clone(), usb_uv_handler: UsbUvHandler::new(), + internal_hid_devices: Vec::new(), internal_device_credentials, internal_device_state: InternalDeviceState::Idle, internal_pin_attempts_left: 5, @@ -88,6 +91,7 @@ impl CredentialService { cred_request, cred_response, + chosen_hid_device: None, } } @@ -97,32 +101,73 @@ impl CredentialService { pub(crate) async fn poll_device_discovery_usb(&mut self) -> Result { debug!("polling for USB status"); - let prev_usb_state = self.usb_state.lock().await.clone(); + let prev_usb_state = *self.usb_state.lock().await; let next_usb_state = match prev_usb_state { UsbState::Idle | UsbState::Waiting => { - let devices = libwebauthn::transport::hid::list_devices().await.unwrap(); - if devices.is_empty() { + self.internal_hid_devices = + libwebauthn::transport::hid::list_devices().await.unwrap(); + if self.internal_hid_devices.is_empty() { let state = UsbState::Waiting; *self.usb_state.lock().await = state; return Ok(state); - } - if devices.is_empty() { - Ok(UsbState::Waiting) - } else { + } else if self.internal_hid_devices.len() == 1 { + self.chosen_hid_device = Some(self.internal_hid_devices.swap_remove(0)); Ok(UsbState::Connected) + } else { + Ok(UsbState::SelectingDevice) } } + UsbState::SelectingDevice => { + let (blinking_tx, mut blinking_rx) = tokio::sync::mpsc::channel::>( + self.internal_hid_devices.len(), + ); + let mut expected_answers = self.internal_hid_devices.len(); + for mut device in self.internal_hid_devices.drain(..) { + let tx = blinking_tx.clone(); + tokio().spawn(async move { + let (mut channel, _state_rx) = device.channel().await.unwrap(); + let res = channel + .blink_and_wait_for_user_presence(Duration::from_secs(300)) + .await; + drop(channel); + match res { + Ok(true) => { + let _ = tx.send(Some(device)).await; + } + Ok(false) | Err(_) => { + let _ = tx.send(None).await; + } + } + }); + } + let mut state = UsbState::Idle; + while let Some(msg) = blinking_rx.recv().await { + expected_answers -= 1; + match msg { + Some(device) => { + self.chosen_hid_device = Some(device); + state = UsbState::Connected; + break; + } + None => { + if expected_answers == 0 { + break; + } else { + continue; + } + } + } + } + Ok(state) + } UsbState::Connected => { - // TODO: I'm not sure how we want to handle multiple usb devices - // just take the first one found for now. - // TODO: store this device reference, perhaps in the enum itself let handler = self.usb_uv_handler.clone(); let cred_request = self.cred_request.clone(); let signal_tx = self.usb_uv_handler.signal_tx.clone(); let pin_rx = self.usb_uv_handler.pin_rx.clone(); + let mut device = self.chosen_hid_device.take().unwrap(); + self.internal_hid_devices.clear(); tokio().spawn(async move { - let mut devices = libwebauthn::transport::hid::list_devices().await.unwrap(); - let device = devices.first_mut().unwrap(); let (mut channel, state_rx) = device.channel().await.unwrap(); tokio().spawn(async move { handle_usb_updates(signal_tx, pin_rx, state_rx).await; @@ -288,7 +333,7 @@ impl CredentialService { UsbState::UserCancelled => Ok(prev_usb_state), }?; - *self.usb_state.lock().await = next_usb_state; + *self.usb_state.lock().await = next_usb_state.clone(); Ok(next_usb_state) } @@ -402,7 +447,6 @@ impl CredentialService { } } - #[derive(Copy, Clone, Debug, Default, PartialEq)] pub enum UsbState { /// Not polling for FIDO USB device. @@ -433,6 +477,10 @@ pub enum UsbState { // This isn't actually sent from the server. UserCancelled, + + // When we encounter multiple devices, we let all of them blink and continue + // with the one that was tapped. + SelectingDevice, } #[derive(Clone, Debug, Default, PartialEq)] diff --git a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/gtk/mod.rs b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/gtk/mod.rs index a9f20be..3cbb09a 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/gtk/mod.rs +++ b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/gtk/mod.rs @@ -89,7 +89,8 @@ impl ViewModel { self.imp().tx.replace(Some(tx)); self.imp().rx.replace(Some(rx)); glib::spawn_future_local(clone!( - #[weak(rename_to = view_model)] self, + #[weak(rename_to = view_model)] + self, async move { loop { let rx = view_model.imp().rx.borrow(); @@ -99,20 +100,33 @@ impl ViewModel { // TODO: hack so I don't have to unset this in every event manually. view_model.set_usb_pin_entry_visible(false); match update { - ViewUpdate::SetTitle(title) => { view_model.set_title(title) }, - ViewUpdate::SetDevices(devices) => { view_model.update_devices(&devices) }, - ViewUpdate::SetCredentials(credentials) => { view_model.update_credentials(&credentials) }, - ViewUpdate::SelectDevice(device) => { view_model.select_device(&device) }, - ViewUpdate::SelectCredential(cred_id) => { view_model.select_credential(cred_id) }, + ViewUpdate::SetTitle(title) => view_model.set_title(title), + ViewUpdate::SetDevices(devices) => { + view_model.update_devices(&devices) + } + ViewUpdate::SetCredentials(credentials) => { + view_model.update_credentials(&credentials) + } + ViewUpdate::SelectingDevice => view_model.selecting_device(), + ViewUpdate::WaitingForDevice(device) => { + view_model.waiting_for_device(&device) + } + ViewUpdate::SelectCredential(cred_id) => { + view_model.select_credential(cred_id) + } ViewUpdate::UsbNeedsPin { attempts_left } => { let prompt = match attempts_left { - Some(1) => "Enter your PIN. 1 attempt remaining.".to_string(), - Some(attempts_left) => format!("Enter your PIN. {attempts_left} attempts remaining."), + Some(1) => { + "Enter your PIN. 1 attempt remaining.".to_string() + } + Some(attempts_left) => format!( + "Enter your PIN. {attempts_left} attempts remaining." + ), None => format!("Enter your PIN."), }; view_model.set_prompt(prompt); view_model.set_usb_pin_entry_visible(true); - }, + } ViewUpdate::UsbNeedsUserVerification { attempts_left } => { let prompt = match attempts_left { Some(1) => "Touch your device again. 1 attempt remaining.".to_string(), @@ -120,15 +134,15 @@ impl ViewModel { None => format!("Touch your device."), }; view_model.set_prompt(prompt); - }, + } ViewUpdate::UsbNeedsUserPresence => { view_model.set_prompt("Touch your device"); - }, + } ViewUpdate::Completed => { view_model.set_completed(true); - }, + } } - }, + } Err(e) => { debug!("ViewModel event listener interrupted: {}", e); break; @@ -228,7 +242,7 @@ impl ViewModel { self.set_credentials(credential_list); } - fn select_device(&self, device: &Device) { + fn waiting_for_device(&self, device: &Device) { match device.transport { Transport::Usb => { self.set_prompt("Insert your security key."); @@ -242,6 +256,10 @@ impl ViewModel { self.set_selected_credential(""); } + fn selecting_device(&self) { + self.set_prompt("Multiple devices found. Please select with which to proceed."); + } + fn select_credential(&self, cred_id: String) { self.set_selected_credential(cred_id); } diff --git a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs index 62b1951..a4a0748 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs +++ b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs @@ -232,13 +232,16 @@ impl ViewModel { match prev_state { UsbState::Completed => break, UsbState::UserCancelled => break, - _ => {}, + _ => {} }; async_std::task::sleep(Duration::from_millis(50)).await; - }, + } Err(err) => { // TODO: move to error page - tracing::error!("There was an error trying to get credentials from USB: {}", err); + tracing::error!( + "There was an error trying to get credentials from USB: {}", + err + ); break; } }; @@ -266,9 +269,11 @@ impl ViewModel { { if prev_state != current_state { println!("{:?}", current_state); - tx.send(BackgroundEvent::InternalDeviceStateChanged(current_state.clone())) - .await - .unwrap(); + tx.send(BackgroundEvent::InternalDeviceStateChanged( + current_state.clone(), + )) + .await + .unwrap(); } prev_state = current_state; } @@ -280,7 +285,7 @@ impl ViewModel { } self.tx_update - .send(ViewUpdate::SelectDevice(device.clone())) + .send(ViewUpdate::WaitingForDevice(device.clone())) .await .unwrap(); } @@ -356,22 +361,34 @@ impl ViewModel { } UsbState::NeedsPin { attempts_left } => { - self.tx_update.send(ViewUpdate::UsbNeedsPin { attempts_left }).await.unwrap(); + self.tx_update + .send(ViewUpdate::UsbNeedsPin { attempts_left }) + .await + .unwrap(); } UsbState::NeedsUserVerification { attempts_left } => { - self.tx_update.send(ViewUpdate::UsbNeedsUserVerification { attempts_left }).await.unwrap(); + self.tx_update + .send(ViewUpdate::UsbNeedsUserVerification { attempts_left }) + .await + .unwrap(); } - UsbState::NeedsUserPresence => { - self.tx_update.send(ViewUpdate::UsbNeedsUserPresence).await.unwrap(); + UsbState::NeedsUserPresence => { + self.tx_update + .send(ViewUpdate::UsbNeedsUserPresence) + .await + .unwrap(); } UsbState::Completed => { - self.credential_service - .lock() - .await - .complete_auth(); + self.credential_service.lock().await.complete_auth(); self.tx_update.send(ViewUpdate::Completed).await.unwrap(); } - _ => {} + UsbState::SelectingDevice => { + self.tx_update + .send(ViewUpdate::SelectingDevice) + .await + .unwrap(); + } + UsbState::NotListening | UsbState::Waiting | UsbState::UserCancelled => {} } } Event::Background(BackgroundEvent::InternalDeviceStateChanged(state)) => { @@ -381,10 +398,7 @@ impl ViewModel { // self.tx_update.send(ViewUpdate::InternalDeviceNeedsPin).await.unwrap(); // }, InternalDeviceState::Completed { device, cred_id } => { - self.credential_service - .lock() - .await - .complete_auth(); + self.credential_service.lock().await.complete_auth(); self.tx_update.send(ViewUpdate::Completed).await.unwrap(); } _ => {} @@ -408,12 +422,13 @@ pub enum ViewUpdate { SetTitle(String), SetDevices(Vec), SetCredentials(Vec), - SelectDevice(Device), + WaitingForDevice(Device), SelectCredential(String), UsbNeedsPin { attempts_left: Option }, UsbNeedsUserVerification { attempts_left: Option }, UsbNeedsUserPresence, Completed, + SelectingDevice, } pub enum BackgroundEvent { @@ -547,7 +562,6 @@ impl From for String { } } - impl Transport { fn as_str(&self) -> &'static str { match self { @@ -571,10 +585,14 @@ pub enum UsbState { Waiting, /// The device needs the PIN to be entered. - NeedsPin { attempts_left: Option }, + NeedsPin { + attempts_left: Option, + }, /// The device needs on-device user verification to be entered. - NeedsUserVerification { attempts_left: Option }, + NeedsUserVerification { + attempts_left: Option, + }, /// The device needs on-device user verification to be entered. NeedsUserPresence, @@ -587,16 +605,24 @@ pub enum UsbState { // This isn't actually sent from the server. UserCancelled, + + /// Multiple devices found + SelectingDevice, } impl From for UsbState { fn from(val: crate::credential_service::UsbState) -> Self { match val { crate::credential_service::UsbState::Idle => UsbState::NotListening, + crate::credential_service::UsbState::SelectingDevice => UsbState::SelectingDevice, crate::credential_service::UsbState::Waiting => UsbState::Waiting, crate::credential_service::UsbState::Connected => UsbState::Connected, - crate::credential_service::UsbState::NeedsPin { attempts_left }=> UsbState::NeedsPin { attempts_left }, - crate::credential_service::UsbState::NeedsUserVerification { attempts_left }=> UsbState::NeedsUserVerification { attempts_left }, + crate::credential_service::UsbState::NeedsPin { attempts_left } => { + UsbState::NeedsPin { attempts_left } + } + crate::credential_service::UsbState::NeedsUserVerification { attempts_left } => { + UsbState::NeedsUserVerification { attempts_left } + } crate::credential_service::UsbState::NeedsUserPresence => UsbState::NeedsUserPresence, crate::credential_service::UsbState::Completed => UsbState::Completed, crate::credential_service::UsbState::UserCancelled => UsbState::UserCancelled, From 9ab53aac33cdccb5b925e681888b2f0e2f848a11 Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Tue, 20 May 2025 16:10:59 +0200 Subject: [PATCH 2/3] Don't cache devices, but send them around --- .../Cargo.lock | 2 +- .../Cargo.toml | 3 +- .../src/credential_service/mod.rs | 44 +++++++------------ .../src/view_model/mod.rs | 4 +- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock index 3586ad1..3c54b29 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock @@ -1950,7 +1950,7 @@ dependencies = [ [[package]] name = "libwebauthn" version = "0.1.2" -source = "git+https://github.com/linux-credentials/libwebauthn?rev=7efdc9324039ea7776a3a71a79d087f791b1ed91#7efdc9324039ea7776a3a71a79d087f791b1ed91" +source = "git+https://github.com/msirringhaus/xdg-credentials-portal?rev=465b143207e97140371321a4b5bae45d4d211c8f#465b143207e97140371321a4b5bae45d4d211c8f" dependencies = [ "aes", "async-trait", diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml index 1bf2b0b..84f8de7 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml @@ -20,7 +20,8 @@ serde_json = "1.0.140" tracing = "0.1.41" tracing-subscriber = "0.3" zbus = "5.5.0" -libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "7efdc9324039ea7776a3a71a79d087f791b1ed91" } +# libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "7efdc9324039ea7776a3a71a79d087f791b1ed91" } +libwebauthn = { git = "https://github.com/msirringhaus/xdg-credentials-portal", rev = "465b143207e97140371321a4b5bae45d4d211c8f" } async-trait = "0.1.88" tokio = { version = "1", features = ["rt-multi-thread"] } diff --git a/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs b/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs index e49a653..87e9ff6 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs +++ b/xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs @@ -35,8 +35,6 @@ pub struct CredentialService { usb_state: AsyncArc>, usb_uv_handler: UsbUvHandler, - internal_hid_devices: Vec, - chosen_hid_device: Option, internal_device_credentials: Vec, internal_device_state: InternalDeviceState, internal_pin_attempts_left: u32, @@ -83,7 +81,6 @@ impl CredentialService { usb_state: usb_state.clone(), usb_uv_handler: UsbUvHandler::new(), - internal_hid_devices: Vec::new(), internal_device_credentials, internal_device_state: InternalDeviceState::Idle, internal_pin_attempts_left: 5, @@ -91,7 +88,6 @@ impl CredentialService { cred_request, cred_response, - chosen_hid_device: None, } } @@ -101,28 +97,25 @@ impl CredentialService { pub(crate) async fn poll_device_discovery_usb(&mut self) -> Result { debug!("polling for USB status"); - let prev_usb_state = *self.usb_state.lock().await; + let prev_usb_state = self.usb_state.lock().await.clone(); let next_usb_state = match prev_usb_state { UsbState::Idle | UsbState::Waiting => { - self.internal_hid_devices = - libwebauthn::transport::hid::list_devices().await.unwrap(); - if self.internal_hid_devices.is_empty() { + let mut hid_devices = libwebauthn::transport::hid::list_devices().await.unwrap(); + if hid_devices.is_empty() { let state = UsbState::Waiting; - *self.usb_state.lock().await = state; + *self.usb_state.lock().await = state.clone(); return Ok(state); - } else if self.internal_hid_devices.len() == 1 { - self.chosen_hid_device = Some(self.internal_hid_devices.swap_remove(0)); - Ok(UsbState::Connected) + } else if hid_devices.len() == 1 { + Ok(UsbState::Connected(hid_devices.swap_remove(0))) } else { - Ok(UsbState::SelectingDevice) + Ok(UsbState::SelectingDevice(hid_devices)) } } - UsbState::SelectingDevice => { - let (blinking_tx, mut blinking_rx) = tokio::sync::mpsc::channel::>( - self.internal_hid_devices.len(), - ); - let mut expected_answers = self.internal_hid_devices.len(); - for mut device in self.internal_hid_devices.drain(..) { + UsbState::SelectingDevice(hid_devices) => { + let (blinking_tx, mut blinking_rx) = + tokio::sync::mpsc::channel::>(hid_devices.len()); + let mut expected_answers = hid_devices.len(); + for mut device in hid_devices { let tx = blinking_tx.clone(); tokio().spawn(async move { let (mut channel, _state_rx) = device.channel().await.unwrap(); @@ -145,8 +138,7 @@ impl CredentialService { expected_answers -= 1; match msg { Some(device) => { - self.chosen_hid_device = Some(device); - state = UsbState::Connected; + state = UsbState::Connected(device); break; } None => { @@ -160,13 +152,11 @@ impl CredentialService { } Ok(state) } - UsbState::Connected => { + UsbState::Connected(mut device) => { let handler = self.usb_uv_handler.clone(); let cred_request = self.cred_request.clone(); let signal_tx = self.usb_uv_handler.signal_tx.clone(); let pin_rx = self.usb_uv_handler.pin_rx.clone(); - let mut device = self.chosen_hid_device.take().unwrap(); - self.internal_hid_devices.clear(); tokio().spawn(async move { let (mut channel, state_rx) = device.channel().await.unwrap(); tokio().spawn(async move { @@ -447,7 +437,7 @@ impl CredentialService { } } -#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default)] pub enum UsbState { /// Not polling for FIDO USB device. #[default] @@ -457,7 +447,7 @@ pub enum UsbState { Waiting, /// USB device connected, prompt user to tap - Connected, + Connected(HidDevice), /// The device needs the PIN to be entered. NeedsPin { @@ -480,7 +470,7 @@ pub enum UsbState { // When we encounter multiple devices, we let all of them blink and continue // with the one that was tapped. - SelectingDevice, + SelectingDevice(Vec), } #[derive(Clone, Debug, Default, PartialEq)] diff --git a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs index a4a0748..bc31c98 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs +++ b/xyz-iinuwa-credential-manager-portal-gtk/src/view_model/mod.rs @@ -614,9 +614,9 @@ impl From for UsbState { fn from(val: crate::credential_service::UsbState) -> Self { match val { crate::credential_service::UsbState::Idle => UsbState::NotListening, - crate::credential_service::UsbState::SelectingDevice => UsbState::SelectingDevice, + crate::credential_service::UsbState::SelectingDevice(..) => UsbState::SelectingDevice, crate::credential_service::UsbState::Waiting => UsbState::Waiting, - crate::credential_service::UsbState::Connected => UsbState::Connected, + crate::credential_service::UsbState::Connected(..) => UsbState::Connected, crate::credential_service::UsbState::NeedsPin { attempts_left } => { UsbState::NeedsPin { attempts_left } } From 053809392f8b5ed8acb9d3104081883d6c04148b Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Thu, 22 May 2025 13:40:57 +0200 Subject: [PATCH 3/3] Switch back to upstream libwebauthn, which has the fixes now --- xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock | 2 +- xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock index 3c54b29..6aba4ff 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.lock @@ -1950,7 +1950,7 @@ dependencies = [ [[package]] name = "libwebauthn" version = "0.1.2" -source = "git+https://github.com/msirringhaus/xdg-credentials-portal?rev=465b143207e97140371321a4b5bae45d4d211c8f#465b143207e97140371321a4b5bae45d4d211c8f" +source = "git+https://github.com/linux-credentials/libwebauthn?rev=73970627b81ff775fbd80fb70694bef049ac2c85#73970627b81ff775fbd80fb70694bef049ac2c85" dependencies = [ "aes", "async-trait", diff --git a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml index 84f8de7..6056028 100644 --- a/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml +++ b/xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml @@ -20,8 +20,7 @@ serde_json = "1.0.140" tracing = "0.1.41" tracing-subscriber = "0.3" zbus = "5.5.0" -# libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "7efdc9324039ea7776a3a71a79d087f791b1ed91" } -libwebauthn = { git = "https://github.com/msirringhaus/xdg-credentials-portal", rev = "465b143207e97140371321a4b5bae45d4d211c8f" } +libwebauthn = { git = "https://github.com/linux-credentials/libwebauthn", rev = "73970627b81ff775fbd80fb70694bef049ac2c85" } async-trait = "0.1.88" tokio = { version = "1", features = ["rt-multi-thread"] }