Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/nornir-auth-webauthn/Cargo.toml

[package]
name = "nornir-auth-webauthn"
version = "0.2.3" # RA5-34 client-key: the one partition rule, no dependencies
edition = "2021"
authors = ["Ignalina ApS"]
description = "WebAuthn / FIDO2 / passkey auth PROVIDER for the nordisk servers. RP-side verification of a passkey authentication assertion: verifies the signature against the stored credential public key, checks the challenge, origin and relying-party ID hash, enforces the user-present and user-verified flags, and rejects a replayed or rolled-back signature counter. Registration (attestation) parsing included. No password path, no session issuing — it answers whether one assertion is genuine, and the caller decides what that grants."
license = "MIT OR Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/edda"
keywords = ["auth", "webauthn", "fido2", "passkey", "passwordless"]
categories = ["authentication"]

[lib]
name = "nornir_auth_webauthn"

[features]
# The PURE-RUST backend is the DEFAULT: `p256` + `ciborium`, no FFI, no C
# toolchain, no system libssl. Measured against holger's `full` tier it adds 24
# crates where `webauthn-rs` adds 41 *including* `openssl-sys` — and THE LAW
# permits FFI only when no Rust library exists, which is not the case here. Note
# what is not the argument: holger's `deny.toml` does allow MPL-2.0, so the
# licence is not the disqualifier; a C build-time dependency in an artifact whose
# purpose is to ship into a sealed environment is.
default = ["webauthn-pure"]
# `webauthn-pure` — the pure-Rust RP-side ceremony (ES256/P-256 only, attestation
# parsed but not chain-verified) plus the MAC'd session token a verified ceremony
# mints. This is the backend an airgapped appliance links.
webauthn-pure = ["dep:nornir-service", "dep:tonic", "dep:p256", "dep:ciborium", "dep:sha2", "dep:base64", "dep:blake3", "dep:serde", "dep:serde_json"]
# `ceremony` — the SERVER SIDE of a ceremony over raw relayed fields (A34 M-3):
# the per-client challenge store (`CeremonyStore`, `ClientKey`: IPv4 by address,
# IPv6 by /64), the relying-party and origin rules, `clientDataJSON`, and the
# assertion and attestation checks Gunnar used to keep in its own webauthn.rs.
# Off by default. Deliberately WITHOUT ciborium (its attestation reader is a small
# definite-length CBOR reader of its own), so a product moving onto it links
# nothing it did not already link; the ES256 crypto is the same `es256` module
# the pure backend uses.
ceremony = ["client-key", "dep:p256", "dep:sha2", "dep:base64", "dep:serde_json", "dep:getrandom"]
# `client-key` — the one partition rule (`ClientKey`: IPv4 by address, IPv6 by its /64, an
# IPv4-mapped address as its IPv4), with no dependency at all (RA5-34): the SCIM bearer's flood
# guard and the estate front's buckets take it from here.
client-key = []
# `test-support` — the SOFT AUTHENTICATOR (`softkey`), a passkey in software so a
# CONSUMER can drive a whole register->login round trip against its own running
# server. Dev-only, never in a shipped closure; same shape as nornir-auth-oidc's
# `test-support` throwaway-keypair JWT minter. It needs the pure backend's own
# crypto deps and nothing else -- deliberately NOT webauthn-authenticator-rs,
# which would drag openssl into `cargo test` on a tree whose whole point is that
# `cargo build` needs no C toolchain.
test-support = ["webauthn-pure", "dep:p256", "dep:ciborium", "dep:sha2", "dep:base64", "dep:serde_json"]
# (The `webauthn` feature over `webauthn-rs` is gone, A34-32: its state carried the
# subject and it dropped the counter; it linked OpenSSL; nothing enabled it.)

[dependencies]
# The ONE shared auth-provider seam (`pure::PurePasskeyProvider`) — `webauthn-pure`
# only, so a `ceremony`-only build links neither it nor tonic.
nornir-service = { version = "0.1.11", path = "../nornir-service", features = ["auth-provider"], optional = true }
tonic = { version = "0.14", default-features = false, optional = true }
# (De)serialize the session token and the JSON fields at the seam boundary.
serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }

# ── The PURE-RUST backend's closure (feature `webauthn-pure`). Every one of these
#    is pure Rust with no build-time system dependency, which is the entire point:
#    an airgap appliance image must build from vendored crates on a host that has
#    no libssl-dev and no C compiler for a crypto stack.
# ES256 / P-256 signature verification (RustCrypto). Already a sibling dependency
# inside nordisk — znippy-common links the same version.
p256 = { version = "0.14", features = ["ecdsa"], optional = true }
# CBOR: the attestationObject and the COSE public key inside it.
ciborium = { version = "0.2", optional = true }
# SHA-256: the rpIdHash and the clientDataJSON hash the assertion signs over.
sha2 = { version = "0.11", optional = true }
# base64url (no padding) — the encoding WebAuthn uses for every binary JSON field.
base64 = { version = "0.23", optional = true }
# Keyed hash for the session-token MAC. `blake3::Hash` compares in CONSTANT TIME,
# which is why the comparison goes through it rather than through a byte slice.
blake3 = { version = "1", optional = true }
# `ceremony` only: the challenge bytes, from the operating system.
getrandom = { version = "0.4", optional = true }