Skip to content

Commit 26326d0

Browse files
fix(nfc): require backend feature; rename to nfc-backend-{pcsc,libnfc} (#193)
Stacked on top of #186. ## Summary - Fix build failure when only the `nfc` umbrella feature is enabled (no backend). - Gate `transport::nfc` on `any(nfc-backend-pcsc, nfc-backend-libnfc)` so the broken code never compiles in the bad combo. - Emit a single clear `compile_error!` from `lib.rs` instead of three cascade errors out of `transport/nfc/device.rs`. - Rename backend features to `nfc-backend-pcsc` and `nfc-backend-libnfc` to make the umbrella relationship explicit. - Restructure the example list in the top-level README into a transport × protocol table. - NFC cells show both backend variants (`nfc-backend-pcsc`, `nfc-backend-libnfc`). - Extend CI with per-backend coverage so this can't regress. - Build `libwebauthn` with only `nfc-backend-pcsc` enabled. - Build `libwebauthn` with only `nfc-backend-libnfc` enabled. ## Build matrix verified locally | Command | Behavior | | ------------------------------------------- | --------------------------------------- | | `cargo build` (no features) | Builds; NFC examples auto-skipped. | | `cargo build --features nfc` | Single clear `compile_error!`. | | `cargo build --features nfc-backend-pcsc` | Builds NFC examples. | | `cargo build --features nfc-backend-libnfc` | Checks pass (link needs `libnfc`). | ## Test plan - [x] `cargo build` (default features) succeeds, NFC examples skipped. - [x] `cargo build --features nfc` produces a single `compile_error!` with the helpful message. - [x] `cargo build --example webauthn_nfc --features nfc-backend-pcsc` builds. - [x] On a CI/dev machine with `libnfc` installed, `--features nfc-backend-libnfc` links successfully. - [x] New CI steps run green on this PR.
1 parent 2d195d1 commit 26326d0

7 files changed

Lines changed: 55 additions & 23 deletions

File tree

.github/workflows/rust.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ jobs:
2121
run: cargo fmt --all -- --check
2222
- name: Build
2323
run: cargo build --workspace --all-targets --all-features
24+
- name: Build with only nfc-backend-pcsc
25+
run: cargo build -p libwebauthn --examples --features nfc-backend-pcsc
26+
- name: Build with only nfc-backend-libnfc
27+
run: cargo build -p libwebauthn --examples --features nfc-backend-libnfc
2428
- name: Run tests
2529
run: cargo test --workspace --verbose
2630
- name: Verify libwebauthn publishes cleanly

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,33 @@ Validating the relying party ID against the calling origin requires the [Public
5555
## Example programs
5656

5757
After cloning, you can try out [one of the libwebauthn examples](libwebauthn/examples):
58+
5859
```
5960
$ cd libwebauthn
6061
$ git submodule update --init
61-
$ cargo run --example webauthn_hid
62-
$ cargo run --example webauthn_nfc
63-
$ cargo run --example webauthn_cable
64-
$ cargo run --example u2f_hid
62+
```
63+
64+
| Transport | FIDO U2F | WebAuthn (FIDO2) |
65+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
66+
| **USB (HID)** | `cargo run --example u2f_hid` | `cargo run --example webauthn_hid`<br>`cargo run --example webauthn_json_hid` |
67+
| **Bluetooth (BLE)** | `cargo run --example u2f_ble` ||
68+
| **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` |
69+
| **Hybrid (caBLE v2)** || `cargo run --example webauthn_cable` |
70+
71+
[^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.
72+
73+
Additional HID-only examples cover specific FIDO2 features and authenticator management:
74+
75+
```
76+
$ cargo run --example webauthn_extensions_hid
77+
$ cargo run --example webauthn_preflight_hid
78+
$ cargo run --example webauthn_prf_hid
79+
$ cargo run --example prf_test
80+
$ cargo run --example hid_device_selection
81+
$ cargo run --example change_pin_hid
82+
$ cargo run --example bio_enrollment_hid
83+
$ cargo run --example authenticator_config_hid
84+
$ cargo run --example cred_management
6585
```
6686

6787
## Contributing

libwebauthn/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ path = "src/lib.rs"
1616
[features]
1717
default = []
1818
nfc = ["apdu-core", "apdu"]
19-
pcsc = [ "nfc", "dep:pcsc" ]
20-
libnfc = [
19+
nfc-backend-pcsc = ["nfc", "dep:pcsc"]
20+
nfc-backend-libnfc = [
2121
"nfc",
2222
"nfc1-sys",
2323
"nfc1",

libwebauthn/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::todo))]
77
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::unreachable))]
88

9+
#[cfg(all(
10+
feature = "nfc",
11+
not(any(feature = "nfc-backend-pcsc", feature = "nfc-backend-libnfc"))
12+
))]
13+
compile_error!(
14+
"the `nfc` feature is an umbrella that requires at least one backend; enable `nfc-backend-pcsc` and/or `nfc-backend-libnfc`"
15+
);
16+
917
pub mod fido;
1018
pub mod management;
1119
pub mod ops;

libwebauthn/src/transport/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub mod hid;
88
/// A mock channel that can be used in tests to
99
/// queue expected requests and responses in unittests
1010
pub mod mock;
11-
#[cfg(feature = "nfc")]
11+
#[cfg(any(feature = "nfc-backend-pcsc", feature = "nfc-backend-libnfc"))]
1212
pub mod nfc;
1313

1414
mod channel;

libwebauthn/src/transport/nfc/device.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ use crate::{
99
};
1010

1111
use super::channel::NfcChannel;
12-
#[cfg(feature = "libnfc")]
12+
#[cfg(feature = "nfc-backend-libnfc")]
1313
use super::libnfc;
14-
#[cfg(feature = "pcsc")]
14+
#[cfg(feature = "nfc-backend-pcsc")]
1515
use super::pcsc;
1616
use super::{Context, Nfc};
1717

1818
#[derive(Clone, Debug)]
1919
enum DeviceInfo {
20-
#[cfg(feature = "libnfc")]
20+
#[cfg(feature = "nfc-backend-libnfc")]
2121
LibNfc(libnfc::Info),
22-
#[cfg(feature = "pcsc")]
22+
#[cfg(feature = "nfc-backend-pcsc")]
2323
Pcsc(pcsc::Info),
2424
}
2525

@@ -31,9 +31,9 @@ pub struct NfcDevice {
3131
impl fmt::Display for DeviceInfo {
3232
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3333
match &self {
34-
#[cfg(feature = "libnfc")]
34+
#[cfg(feature = "nfc-backend-libnfc")]
3535
DeviceInfo::LibNfc(info) => write!(f, "{}", info),
36-
#[cfg(feature = "pcsc")]
36+
#[cfg(feature = "nfc-backend-pcsc")]
3737
DeviceInfo::Pcsc(info) => write!(f, "{}", info),
3838
}
3939
}
@@ -46,14 +46,14 @@ impl fmt::Display for NfcDevice {
4646
}
4747

4848
impl NfcDevice {
49-
#[cfg(feature = "libnfc")]
49+
#[cfg(feature = "nfc-backend-libnfc")]
5050
pub fn new_libnfc(info: libnfc::Info) -> Self {
5151
NfcDevice {
5252
info: DeviceInfo::LibNfc(info),
5353
}
5454
}
5555

56-
#[cfg(feature = "pcsc")]
56+
#[cfg(feature = "nfc-backend-pcsc")]
5757
pub fn new_pcsc(info: pcsc::Info) -> Self {
5858
NfcDevice {
5959
info: DeviceInfo::Pcsc(info),
@@ -63,9 +63,9 @@ impl NfcDevice {
6363
async fn channel_sync(&self) -> Result<NfcChannel<Context>, Error> {
6464
trace!("nfc channel {:?}", self);
6565
let mut channel: NfcChannel<Context> = match &self.info {
66-
#[cfg(feature = "libnfc")]
66+
#[cfg(feature = "nfc-backend-libnfc")]
6767
DeviceInfo::LibNfc(info) => info.channel(),
68-
#[cfg(feature = "pcsc")]
68+
#[cfg(feature = "nfc-backend-pcsc")]
6969
DeviceInfo::Pcsc(info) => info.channel(),
7070
}?;
7171

@@ -101,9 +101,9 @@ pub async fn get_nfc_device() -> Result<Option<NfcDevice>, Error> {
101101
// we'll potentially have the same device discovered by
102102
// both backends and thus added multiple times to the list.
103103
let list_devices_fns = [
104-
#[cfg(feature = "libnfc")]
104+
#[cfg(feature = "nfc-backend-libnfc")]
105105
libnfc::list_devices,
106-
#[cfg(feature = "pcsc")]
106+
#[cfg(feature = "nfc-backend-pcsc")]
107107
pcsc::list_devices,
108108
];
109109

@@ -121,11 +121,11 @@ pub async fn get_nfc_device() -> Result<Option<NfcDevice>, Error> {
121121
#[instrument]
122122
pub fn is_nfc_available() -> bool {
123123
let mut available = false;
124-
#[cfg(feature = "libnfc")]
124+
#[cfg(feature = "nfc-backend-libnfc")]
125125
{
126126
available |= libnfc::is_nfc_available();
127127
}
128-
#[cfg(feature = "pcsc")]
128+
#[cfg(feature = "nfc-backend-pcsc")]
129129
{
130130
available |= pcsc::is_nfc_available();
131131
}

libwebauthn/src/transport/nfc/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use std::fmt::{Display, Formatter};
33
pub mod channel;
44
pub mod commands;
55
pub mod device;
6-
#[cfg(feature = "libnfc")]
6+
#[cfg(feature = "nfc-backend-libnfc")]
77
pub mod libnfc;
8-
#[cfg(feature = "pcsc")]
8+
#[cfg(feature = "nfc-backend-pcsc")]
99
pub mod pcsc;
1010

1111
pub use device::{get_nfc_device, is_nfc_available};

0 commit comments

Comments
 (0)