Skip to content

Commit 856097d

Browse files
test(ctap1): cover u2f downgrade exclude-list preflight (#295)
Adds coverage for the U2F downgrade exclude-list preflight path, which had no tests. This is a focused first step toward broader coverage of the U2F downgrade flow. Tests only.
1 parent a6cb914 commit 856097d

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

libwebauthn-tests/tests/basic_ctap1.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::time::Duration;
33
use libwebauthn::ops::u2f::{RegisterRequest, SignRequest};
44
use libwebauthn::transport::{Channel, ChannelSettings, Device};
55
use libwebauthn::u2f::U2F;
6+
use libwebauthn::webauthn::{CtapError, Error};
67
use libwebauthn::UvUpdate;
78
use libwebauthn_tests::virt::get_virtual_device;
89
use tokio::sync::broadcast::Receiver;
@@ -51,3 +52,40 @@ async fn test_webauthn_basic_ctap1() {
5152
// Keeping the update-recv alive until the end to check all updates
5253
update_handle.await.unwrap();
5354
}
55+
56+
async fn drain_updates(mut state_recv: Receiver<UvUpdate>) {
57+
while state_recv.recv().await.is_ok() {}
58+
}
59+
60+
#[tokio::test]
61+
async fn test_webauthn_ctap1_exclude_list() {
62+
let mut device = get_virtual_device();
63+
let mut channel = device.channel(ChannelSettings::default()).await.unwrap();
64+
65+
const APP_ID: &str = "https://foo.example.org";
66+
let challenge: &[u8] =
67+
&base64_url::decode("1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70").unwrap();
68+
69+
let drain_handle = tokio::spawn(drain_updates(channel.get_ux_update_receiver()));
70+
71+
let register_request = RegisterRequest::new_u2f_v2(APP_ID, challenge, vec![], TIMEOUT, false);
72+
let response = channel
73+
.u2f_register(&register_request)
74+
.await
75+
.expect("Failed to register credential");
76+
let registered_key = response
77+
.as_registered_key()
78+
.expect("Failed to get credential ID from register response");
79+
80+
// Preflight must reject an excluded credential.
81+
let excluded_request =
82+
RegisterRequest::new_u2f_v2(APP_ID, challenge, vec![registered_key], TIMEOUT, false);
83+
let result = channel.u2f_register(&excluded_request).await;
84+
assert!(
85+
matches!(result, Err(Error::Ctap(CtapError::CredentialExcluded))),
86+
"expected CredentialExcluded, got {:?}",
87+
result
88+
);
89+
90+
drain_handle.abort();
91+
}

0 commit comments

Comments
 (0)