WebAuthn Compliance
The extension implements the W3C WebAuthn Level 2 specification and the FIDO2 Client-to-Authenticator Protocol (CTAP2).
Implemented ceremonies
- Registration (attestation)
- The full attestation verification ceremony. Supported formats:
none, packed, FIDO-U2F, Apple, TPM, and Android SafetyNet.
The extension uses
web-auth/webauthn-libv5.x for all cryptographic verification. - Authentication (assertion)
- Full assertion verification including signature counter checks for authenticator clone detection.
Relying Party configuration
- rpId: Domain-only (no scheme/port). Per-site configurable.
- Origin: Full URL including scheme. Verified against registered origins during ceremonies.
- User verification: Configurable (
required/preferred/discouraged). Defaults torequired.
Challenge handling
Challenges are generated as 32-byte cryptographically random values
(random_bytes(32)), then wrapped in an HMAC-SHA256 signed token:
challengeToken = base64url(nonce || HMAC-SHA256(encryptionKey, nonce || challenge || timestamp))
The token includes:
- A nonce (replay protection -- each token can be used once)
- A timestamp (challenge TTL enforcement)
- HMAC signature (tampering detection)
The plaintext challenge is sent to the browser; the HMAC-signed token is included in the eID response and must be returned verbatim during verification.
Credential storage
Frontend credentials are stored in tx_nrpasskeysfe_credential:
credential_id-- WebAuthn credential ID (binary, indexed)public_key_cose-- COSE-encoded public key (binary blob)sign_count-- Usage counter for clone detectionuser_handle-- SHA-256(uid || encryptionKey) -- not the UID itselfaaguid-- Authenticator AAGUID for device identificationtransports-- JSON transport hints
The user_handle is a one-way hash to prevent user enumeration
from credential lookups.
Recovery codes
Recovery codes are stored as bcrypt hashes (cost factor 12). Plain text is generated server-side, displayed once to the user, then immediately discarded. The bcrypt hash is stored. On verification, the submitted code is compared against the hash in constant time.
See adr-010 for the design decision.