Skip to content

Commit c011930

Browse files
refactor(examples): drop related origins from ceremony examples, add dedicated webauthn_related_origins_hid
1 parent fcfce6b commit c011930

7 files changed

Lines changed: 111 additions & 42 deletions

File tree

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ WebAuthn examples consume and emit JSON per the [WebAuthn IDL][webauthn].
7070

7171
| Transport | FIDO U2F | WebAuthn (FIDO2) [^ro] |
7272
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
73-
| **USB (HID)** | `cargo run --example u2f_hid` | `cargo run --features reqwest-related-origins-source --example webauthn_hid` |
74-
| **Bluetooth (BLE)** | `cargo run --example u2f_ble` | `cargo run --features reqwest-related-origins-source --example webauthn_ble` |
75-
| **NFC** [^nfc] | `cargo run --features nfc-backend-pcsc --example u2f_nfc`<br>`cargo run --features nfc-backend-libnfc --example u2f_nfc` | `cargo run --features nfc-backend-pcsc,reqwest-related-origins-source --example webauthn_nfc`<br>`cargo run --features nfc-backend-libnfc,reqwest-related-origins-source --example webauthn_nfc` |
76-
| **Hybrid (caBLE v2 + CTAP 2.3)** || `cargo run --features reqwest-related-origins-source --example webauthn_cable` |
77-
| **Hybrid (caBLE v2)** || `cargo run --features reqwest-related-origins-source --example webauthn_cable_wss` |
73+
| **USB (HID)** | `cargo run --example u2f_hid` | `cargo run --example webauthn_hid` |
74+
| **Bluetooth (BLE)** | `cargo run --example u2f_ble` | `cargo run --example webauthn_ble` |
75+
| **NFC** [^nfc] | `cargo run --features nfc-backend-pcsc --example u2f_nfc`<br>`cargo run --features nfc-backend-libnfc --example u2f_nfc` | `cargo run --features nfc-backend-pcsc --example webauthn_nfc`<br>`cargo run --features nfc-backend-libnfc --example webauthn_nfc` |
76+
| **Hybrid (caBLE v2 + CTAP 2.3)** || `cargo run --example webauthn_cable` |
77+
| **Hybrid (caBLE v2)** || `cargo run --example webauthn_cable_wss` |
7878

7979
[^nfc]: `nfc-backend-pcsc` is pure userspace and recommended on most systems. `nfc-backend-libnfc` requires the `libnfc` system library. Both can be enabled together; the first FIDO device found by either backend is used.
8080

81-
[^ro]: The WebAuthn ceremony examples wire up the bundled reqwest-backed [related-origins](https://www.w3.org/TR/webauthn-3/#sctn-related-origins) source, which lives behind the optional `reqwest-related-origins-source` feature. Consumers that already ship their own HTTP stack can implement `HttpClient` or `RelatedOriginsSource` directly and omit the feature.
81+
[^ro]: The ceremony examples run with related origins disabled (they are same-origin, so it never applies). The bundled reqwest-backed [related-origins](https://www.w3.org/TR/webauthn-3/#sctn-related-origins) source is shown in the `webauthn_related_origins_hid` example below, behind the optional `reqwest-related-origins-source` feature. Consumers that ship their own HTTP stack can implement `HttpClient` or `RelatedOriginsSource` directly.
8282

8383
Additional HID-only examples cover specific FIDO2 features and authenticator management:
8484

@@ -90,6 +90,9 @@ $ cargo run --example webauthn_prf_hid
9090
$ cargo run --example prf_replay -- CREDENTIAL_ID FIRST_PRF_INPUT
9191
$ cargo run --example device_selection_hid
9292
93+
# Related origins (reqwest-backed well-known fetch)
94+
$ cargo run --features reqwest-related-origins-source --example webauthn_related_origins_hid
95+
9396
# CTAP2 authenticator management
9497
$ cargo run --example change_pin_hid
9598
$ cargo run --example bio_enrollment_hid

libwebauthn/Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,27 +142,23 @@ required-features = ["nfc"]
142142
[[example]]
143143
name = "webauthn_hid"
144144
path = "examples/ceremony/webauthn_hid.rs"
145-
required-features = ["reqwest-related-origins-source"]
146145

147146
[[example]]
148147
name = "webauthn_ble"
149148
path = "examples/ceremony/webauthn_ble.rs"
150-
required-features = ["reqwest-related-origins-source"]
151149

152150
[[example]]
153151
name = "webauthn_nfc"
154152
path = "examples/ceremony/webauthn_nfc.rs"
155-
required-features = ["nfc", "reqwest-related-origins-source"]
153+
required-features = ["nfc"]
156154

157155
[[example]]
158156
name = "webauthn_cable"
159157
path = "examples/ceremony/webauthn_cable.rs"
160-
required-features = ["reqwest-related-origins-source"]
161158

162159
[[example]]
163160
name = "webauthn_cable_wss"
164161
path = "examples/ceremony/webauthn_cable_wss.rs"
165-
required-features = ["reqwest-related-origins-source"]
166162

167163
[[example]]
168164
name = "webauthn_extensions_hid"
@@ -176,6 +172,11 @@ path = "examples/features/webauthn_preflight_hid.rs"
176172
name = "webauthn_prf_hid"
177173
path = "examples/features/webauthn_prf_hid.rs"
178174

175+
[[example]]
176+
name = "webauthn_related_origins_hid"
177+
path = "examples/features/webauthn_related_origins_hid.rs"
178+
required-features = ["reqwest-related-origins-source"]
179+
179180
[[example]]
180181
name = "prf_replay"
181182
path = "examples/features/prf_replay.rs"

libwebauthn/examples/ceremony/webauthn_ble.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use std::error::Error;
22

33
use libwebauthn::ops::webauthn::{
44
DatFilePublicSuffixList, GetAssertionRequest, JsonFormat, MakeCredentialRequest,
5-
MaxRegistrableLabels, OriginValidation, RelatedOrigins, RequestOrigin, RequestSettings,
6-
ReqwestRelatedOriginsSource, WebAuthnIDLResponse as _,
5+
OriginValidation, RelatedOrigins, RequestOrigin, RequestSettings, WebAuthnIDLResponse as _,
76
};
87
use libwebauthn::proto::ctap2::Ctap2PublicKeyCredentialDescriptor;
98
use libwebauthn::transport::ble::list_devices;
@@ -53,14 +52,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
5352
"attestation": "none"
5453
}
5554
"#;
56-
let related_origins = ReqwestRelatedOriginsSource::new()?;
5755
let settings = RequestSettings {
5856
origin: OriginValidation::Validate {
5957
public_suffix_list: &psl,
60-
related_origins: RelatedOrigins::Enabled {
61-
source: &related_origins,
62-
max_labels: MaxRegistrableLabels::default(),
63-
},
58+
related_origins: RelatedOrigins::Disabled,
6459
},
6560
};
6661
let make_credentials_request: MakeCredentialRequest =

libwebauthn/examples/ceremony/webauthn_cable.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use qrcode::render::unicode;
1111
use qrcode::QrCode;
1212

1313
use libwebauthn::ops::webauthn::{
14-
DatFilePublicSuffixList, JsonFormat, MakeCredentialRequest, MaxRegistrableLabels,
15-
OriginValidation, RelatedOrigins, RequestOrigin, RequestSettings, ReqwestRelatedOriginsSource,
16-
WebAuthnIDLResponse as _,
14+
DatFilePublicSuffixList, JsonFormat, MakeCredentialRequest, OriginValidation, RelatedOrigins,
15+
RequestOrigin, RequestSettings, WebAuthnIDLResponse as _,
1716
};
1817
use libwebauthn::transport::{Channel as _, Device};
1918
use libwebauthn::webauthn::WebAuthn;
@@ -59,14 +58,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
5958
let psl = DatFilePublicSuffixList::from_system_file().expect(
6059
"PSL not available; install the publicsuffix-list package or pass an explicit path",
6160
);
62-
let related_origins = ReqwestRelatedOriginsSource::new()?;
6361
let settings = RequestSettings {
6462
origin: OriginValidation::Validate {
6563
public_suffix_list: &psl,
66-
related_origins: RelatedOrigins::Enabled {
67-
source: &related_origins,
68-
max_labels: MaxRegistrableLabels::default(),
69-
},
64+
related_origins: RelatedOrigins::Disabled,
7065
},
7166
};
7267

libwebauthn/examples/ceremony/webauthn_hid.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use std::error::Error;
22
use std::time::Duration;
33

44
use libwebauthn::ops::webauthn::{
5-
GetAssertionRequest, JsonFormat, MakeCredentialRequest, MaxRegistrableLabels, OriginValidation,
6-
RelatedOrigins, RequestOrigin, RequestSettings, ReqwestRelatedOriginsSource,
7-
SystemPublicSuffixList, WebAuthnIDLResponse as _,
5+
GetAssertionRequest, JsonFormat, MakeCredentialRequest, OriginValidation, RelatedOrigins,
6+
RequestOrigin, RequestSettings, SystemPublicSuffixList, WebAuthnIDLResponse as _,
87
};
98
use libwebauthn::proto::ctap2::Ctap2PublicKeyCredentialDescriptor;
109
use libwebauthn::transport::hid::list_devices;
@@ -33,14 +32,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
3332
let psl = SystemPublicSuffixList::auto().expect(
3433
"PSL not available; install the publicsuffix-list (or publicsuffix-list-dafsa) package, or pass an explicit path",
3534
);
36-
let related_origins = ReqwestRelatedOriginsSource::new()?;
3735
let settings = RequestSettings {
3836
origin: OriginValidation::Validate {
3937
public_suffix_list: &psl,
40-
related_origins: RelatedOrigins::Enabled {
41-
source: &related_origins,
42-
max_labels: MaxRegistrableLabels::default(),
43-
},
38+
related_origins: RelatedOrigins::Disabled,
4439
},
4540
};
4641
let request_json = r#"

libwebauthn/examples/ceremony/webauthn_nfc.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::error::Error;
22

33
use libwebauthn::ops::webauthn::{
4-
GetAssertionRequest, JsonFormat, MakeCredentialRequest, MaxRegistrableLabels, OriginValidation,
5-
RelatedOrigins, RequestOrigin, RequestSettings, ReqwestRelatedOriginsSource,
6-
SystemPublicSuffixList, WebAuthnIDLResponse as _,
4+
GetAssertionRequest, JsonFormat, MakeCredentialRequest, OriginValidation, RelatedOrigins,
5+
RequestOrigin, RequestSettings, SystemPublicSuffixList, WebAuthnIDLResponse as _,
76
};
87
use libwebauthn::transport::nfc::{get_nfc_device, is_nfc_available};
98
use libwebauthn::transport::{Channel as _, Device};
@@ -31,14 +30,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
3130
let psl = SystemPublicSuffixList::auto().expect(
3231
"PSL not available; install the publicsuffix-list (or publicsuffix-list-dafsa) package, or pass an explicit path",
3332
);
34-
let related_origins = ReqwestRelatedOriginsSource::new()?;
3533
let settings = RequestSettings {
3634
origin: OriginValidation::Validate {
3735
public_suffix_list: &psl,
38-
related_origins: RelatedOrigins::Enabled {
39-
source: &related_origins,
40-
max_labels: MaxRegistrableLabels::default(),
41-
},
36+
related_origins: RelatedOrigins::Disabled,
4237
},
4338
};
4439
let make_credentials_request = MakeCredentialRequest::prepare(
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//! HID make-credential with related origins enabled.
2+
//!
3+
//! The bundled reqwest-backed [`ReqwestRelatedOriginsSource`] fetches
4+
//! `https://<rp.id>/.well-known/webauthn` when the request's rp.id is not a
5+
//! registrable suffix of the caller origin. This demo is same-origin
6+
//! (`example.org`), so the source is wired but the fetch is not triggered. It
7+
//! fires when rp.id and the origin sit on different registrable domains, with
8+
//! the RP listing the caller origin in its well-known document.
9+
10+
use std::error::Error;
11+
use std::time::Duration;
12+
13+
use libwebauthn::ops::webauthn::{
14+
JsonFormat, MakeCredentialRequest, MaxRegistrableLabels, OriginValidation, RelatedOrigins,
15+
RequestOrigin, RequestSettings, ReqwestRelatedOriginsSource, SystemPublicSuffixList,
16+
WebAuthnIDLResponse as _,
17+
};
18+
use libwebauthn::transport::hid::list_devices;
19+
use libwebauthn::transport::{Channel as _, Device};
20+
use libwebauthn::webauthn::WebAuthn;
21+
22+
#[path = "../common/mod.rs"]
23+
mod common;
24+
25+
const TIMEOUT: Duration = Duration::from_secs(10);
26+
27+
#[tokio::main]
28+
pub async fn main() -> Result<(), Box<dyn Error>> {
29+
common::setup_logging();
30+
31+
let devices = list_devices().await.unwrap();
32+
println!("Devices found: {:?}", devices);
33+
34+
for mut device in devices {
35+
println!("Selected HID authenticator: {}", &device);
36+
let mut channel = device.channel().await?;
37+
channel.wink(TIMEOUT).await?;
38+
39+
let request_origin: RequestOrigin =
40+
"https://example.org".try_into().expect("Invalid origin");
41+
let psl = SystemPublicSuffixList::auto().expect(
42+
"PSL not available; install the publicsuffix-list (or publicsuffix-list-dafsa) package, or pass an explicit path",
43+
);
44+
let related_origins = ReqwestRelatedOriginsSource::new()?;
45+
let settings = RequestSettings {
46+
origin: OriginValidation::Validate {
47+
public_suffix_list: &psl,
48+
related_origins: RelatedOrigins::Enabled {
49+
source: &related_origins,
50+
max_labels: MaxRegistrableLabels::default(),
51+
},
52+
},
53+
};
54+
let request_json = r#"
55+
{
56+
"rp": { "id": "example.org", "name": "Example Relying Party" },
57+
"user": {
58+
"id": "MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4MTIzNDU2Nzg",
59+
"name": "alice",
60+
"displayName": "Alice"
61+
},
62+
"challenge": "MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4MTIzNDU2Nzg",
63+
"pubKeyCredParams": [{"type": "public-key", "alg": -7}],
64+
"timeout": 60000,
65+
"excludeCredentials": [],
66+
"authenticatorSelection": { "residentKey": "discouraged", "userVerification": "preferred" },
67+
"attestation": "none"
68+
}
69+
"#;
70+
let request = MakeCredentialRequest::prepare(&request_origin, request_json, &settings)
71+
.await
72+
.expect("Failed to parse request JSON");
73+
74+
let state_recv = channel.get_ux_update_receiver();
75+
tokio::spawn(common::handle_uv_updates(state_recv));
76+
77+
let response = retry_user_errors!(channel.webauthn_make_credential(&request)).unwrap();
78+
let response_json = response
79+
.to_json_string(&request, JsonFormat::Prettified)
80+
.expect("Failed to serialize MakeCredential response");
81+
println!("WebAuthn MakeCredential response (JSON):\n{response_json}");
82+
}
83+
84+
Ok(())
85+
}

0 commit comments

Comments
 (0)