Install & Compatibility
Where this runs
tested against v2.2.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.140s · 36.3MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.5s · import 0.128s · 37MB
34MB installed
● package 34MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
AttestationObject
✓ from fido2.webauthn import AttestationObject
CollectedClientData
✓ from fido2.webauthn import CollectedClientData
verify_registration_response
✓ from fido2.webauthn import verify_registration_response
✗ from fido2.webauthn import RegistrationResponse, AttestationStatement.verify(...)
The primary verification functions are now top-level in `fido2.webauthn` for clarity.
Fido2Client
✓ from fido2.client import Fido2Client
cbor
✓ from fido2 import cbor
This quickstart demonstrates how to verify a FIDO2 WebAuthn registration response on the server-side. It simulates receiving `clientDataJSON` and `attestationObject` from a browser and uses `fido2.webauthn.verify_registration_response` to validate them against server-generated challenge and Relying Party (RP) configuration. The example uses minimal mock data for demonstration purposes.
import os
import json
import base64
from fido2.webauthn import (
AttestationObject,
CollectedClientData,
verify_registration_response,
)
from fido2 import cbor
# --- Server-side configuration and stored data ---
# In a real application, these would be generated and stored securely.
RP_ID = os.environ.get("FIDO2_RP_ID", "example.com")
RP_ORIGIN = f"https://{RP_ID}"
# A challenge issued previously by the server to the client for this registration attempt
# This must be a cryptographically secure random 32-byte value.
CHALLENGE = base64.urlsafe_b64decode(b"uKz0s4zP6T3o-J2V-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3y=") # Example base64url-encoded bytes for a 32-byte challenge
USER_ID = b"some_unique_user_id_bytes" # The user ID for whom registration was requested
EXPECTED_RP_ID = RP_ID
EXPECTED_ORIGINS = {RP_ORIGIN}
# --- Simulate client-provided data (in a real app, these come from the browser) ---
# Example: clientDataJSON received from the browser as a string
client_data_json_str = f'''
{{
"type": "webauthn.create",
"challenge": "{base64.urlsafe_b64encode(CHALLENGE).rstrip(b'=').decode('utf-8')}",
"origin": "{RP_ORIGIN}",
"crossOrigin": false
}}
'''
# Example: AttestationObject received from the browser as base64url-encoded CBOR bytes
# This is a minimal 'none' attestation for demonstration purposes.
# Real attestations are more complex.
attestation_object_b64url = "o2NmbXRoZJpvbmVhdHRTdG10oGhhdXRoRGF0YVjLp_hNq_D0D8x4jL17w2-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3yFkQAAAAAAAAAAAAAAAAAAAAAAwIAIAxM0k3Kz-k_D0x4jL17w2-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3yBoAAAAAAAAAAAAAAAAAAAAAADAAAAAQAg"
# --- Server-side verification using fido2 library ---
try:
# Parse the client data and attestation object
client_data = CollectedClientData(json.loads(client_data_json_str))
attestation_object = AttestationObject(base64.urlsafe_b64decode(attestation_object_b64url + "==")) # Add padding back for base64
# Verify the registration response
auth_data = verify_registration_response(
client_data=client_data,
attestation_object=attestation_object,
challenge=CHALLENGE,
rp_id=EXPECTED_RP_ID,
origins=EXPECTED_ORIGINS,
user_id=USER_ID
# In production, you would pass `trusted_attestation_public_keys`
# or `attestation_callback` to validate attestation certificates.
)
print("Registration successful!")
print(f"Credential ID: {base64.urlsafe_b64encode(auth_data.credential_id).decode('utf-8')}")
print(f"Public Key: {base64.urlsafe_b64encode(auth_data.credential_public_key).decode('utf-8')}")
print(f"Signature Count: {auth_data.sign_count}")
# In a real application, you would store auth_data.credential_id,
# auth_data.credential_public_key, and auth_data.sign_count
# associated with the user for future authentication.
except Exception as e:
print(f"Registration failed: {e}")
fido2 --version
Errors
Common errors & fixes
AttributeError: module 'fido2.features' has no attribute 'webauthn_json_mapping'
This error typically occurs when code written for an older version of `fido2` attempts to access features or attributes that have been removed or changed in newer versions (e.g., `fido2` v2.0+), where the `webauthn_json_mapping` flag was removed as its behavior became default.
fixUpgrade `fido2` to the latest version and remove references to the deprecated `fido2.features.webauthn_json_mapping.enabled = True` line, as its functionality is now default or handled automatically. Refer to the library's migration guide for version 1.x to 2.x for other potential breaking changes.
Signature verification failed
This error indicates that the cryptographic signature generated by the authenticator during WebAuthn registration or authentication could not be successfully verified by the relying party server, often due to an incorrect public key, malformed data, or potential tampering.
fixEnsure the public key stored on the server for the credential matches the key used by the authenticator. Verify that all components of the attestation or assertion object (e.g., clientDataJSON, authenticatorData) are correctly parsed and that the cryptographic verification algorithm and parameters are correctly applied according to the WebAuthn specification.
ImportError: cannot import name 'WindowsClient' from 'fido2.client.windows'
The `WindowsClient` class is specifically designed for interacting with the WebAuthn API on Windows operating systems and will raise an `ImportError` if imported or used on non-Windows platforms.
fixImplement platform-specific logic to ensure that `WindowsClient` is only imported and utilized when the application is running on a Windows environment. For cross-platform support, use the generic `Fido2Client` or other appropriate client implementations.
Incorrect RP ID
This error occurs when the `rpIdHash` (relying party ID hash) contained within the authenticator data sent by the FIDO2 authenticator does not match the SHA256 hash of the `rp_id` (domain) that the relying party server expects during validation, which is a critical security check.
fixEnsure that the `rp_id` (relying party identifier) provided by the client-side WebAuthn API during credential creation or assertion requests precisely matches the `rp_id` configured and expected by the server-side `fido2` validation logic. The `rp_id` should typically be the effective domain of the relying party.
Upgrade
Version history
2.2.1latest on PyPI · released Jun 29, 2026
Audit
Dependencies
cbor2requiredRequired for CBOR (Concise Binary Object Representation) encoding and decoding, which is fundamental to the FIDO2 protocol.
cryptographyrequiredEssential for cryptographic operations, including key generation, signature verification, and handling secure elements.
monotonicrequiredProvides a monotonic clock source, used for timing-sensitive operations and preventing time-based attacks.
PyYAMLrequiredUsed for YAML parsing, potentially for configuration files, metadata, or specific utility functions.