Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ indent_size = 4
indent_size = 2
max_line_length = 80

[*.{blp}]
indent_size = 2
max_line_length = 80

[NEWS]
indent_size = 2
max_line_length = 72
6 changes: 3 additions & 3 deletions credentialsd-ui/data/resources/ui/window.blp
Comment thread
msirringhaus marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ template $CredentialsUiWindow: ApplicationWindow {
child: Box {
orientation: vertical;
margin-start: 8;

Box {
orientation: vertical;
halign: start;
visible: bind template.view-model as <$CredentialManagerViewModel>.hybrid_transport_available;

styles [
"cred-source-header",
Expand Down Expand Up @@ -120,9 +120,9 @@ template $CredentialsUiWindow: ApplicationWindow {
}
}
}
}

Separator {}
Separator {}
}

Box {
orientation: vertical;
Expand Down
16 changes: 8 additions & 8 deletions credentialsd-ui/src/gui/view_model/gtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ mod imp {
pub activate_usb_prompt: RefCell<String>,

#[property(get, set)]
pub devices: RefCell<gtk::ListBox>,
pub hybrid_transport_available: RefCell<bool>,

#[property(get, set)]
pub credentials: RefCell<gtk::ListBox>,
Expand Down Expand Up @@ -265,15 +265,15 @@ impl ViewModel {
));
}

fn update_devices(&self, _devices: &[Device]) {
// TODO: This This is called when a new credential source is available to show it in the UI.
// At this time, the list is static, and the UI templates do not read this value.
// Eventually, the UI template will need to read the value, when
// pre-known credentials (like hybrid linked devices, or passkey
// autofill). However, I believe in the current paradigm, we will know all available
fn update_devices(&self, devices: &[Device]) {
let hybrid_available = devices.iter().any(|dev| {
dev.transport == Transport::HybridLinked || dev.transport == Transport::HybridQr
});
self.set_hybrid_transport_available(hybrid_available);
// TODO: This is called when a new credential source is available to show it in the UI.
// However, I believe in the current paradigm, we will know all available
// credential sources at the beginning of the request, so we won't need
// to update these during the request. We may be able to reomve this method altogether.
// for now, we're ignoring this value.
}

fn update_credentials(&self, credentials: &[Credential]) {
Expand Down
64 changes: 39 additions & 25 deletions credentialsd/src/credential_service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ use std::{

use async_trait::async_trait;
use futures_lite::{FutureExt, Stream, StreamExt};
use libwebauthn::pin::persistent_token::{MemoryPersistentTokenStore, PersistentTokenStore};
use libwebauthn::{
self,
ops::webauthn::{GetAssertionResponse, MakeCredentialResponse},
};
use libwebauthn::{
available_transports,
pin::persistent_token::{MemoryPersistentTokenStore, PersistentTokenStore},
};
use nfc::{NfcEvent, NfcHandler, NfcState, NfcStateInternal};
use tokio::sync::oneshot;

Expand Down Expand Up @@ -199,16 +202,16 @@ impl<H: HybridHandler + Send, N: NfcHandler + Send, U: UsbHandler + Send> Manage
async fn get_available_public_key_devices(&self) -> Result<Vec<Device>, ()> {
// We create the list new for each call, in case someone plugs in
// an NFC-reader in the middle of an auth-flow
let mut devices = vec![
Device {
id: String::from("0"),
transport: Transport::Usb,
},
Device {
let mut devices = vec![Device {
id: String::from("0"),
transport: Transport::Usb,
}];
if libwebauthn::transport::cable::is_available().await {
devices.push(Device {
id: String::from("1"),
transport: Transport::HybridQr,
},
];
});
}
if libwebauthn::transport::nfc::is_nfc_available() {
devices.push(Device {
id: String::from("2"),
Expand All @@ -221,11 +224,16 @@ impl<H: HybridHandler + Send, N: NfcHandler + Send, U: UsbHandler + Send> Manage
async fn start_discovery(
&self,
) -> Pin<Box<dyn Stream<Item = DeviceStateUpdate> + Send + 'static>> {
let usb = self
.get_usb_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
let available_transports = available_transports().await;
let mut selected_transports = Vec::new();
if available_transports.contains(&libwebauthn::Transport::Usb) {
let usb = self
.get_usb_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
selected_transports.push(usb);
}
/*
TODO: Some cards that support NFC but not CCID (SoloKey Solo 2 NFC)
cause a framing error immediately after establishing a libwebauthn
Expand All @@ -234,18 +242,24 @@ impl<H: HybridHandler + Send, N: NfcHandler + Send, U: UsbHandler + Send> Manage
security keys, while at the same time supporting actual NFC cards and CCID.
Maybe we can defer sending "Connected" to the UI until a user presence
or verification message is sent.
let nfc = self
.get_nfc_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
if available_transports.contains(&libwebauthn::Transport::Nfc) {
let nfc = self
.get_nfc_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
selected_transports.push(nfc);
}
*/
let hybrid = self
.get_hybrid_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
futures::stream::select_all([usb, /* nfc, */ hybrid]).boxed()
if available_transports.contains(&libwebauthn::Transport::Hybrid) {
let hybrid = self
.get_hybrid_credential()
.await
.map(DeviceStateUpdate::from)
.boxed();
selected_transports.push(hybrid);
}
futures::stream::select_all(selected_transports).boxed()
}
}

Expand Down