{"id":4002,"library":"fido2","title":"FIDO2 WebAuthn Library","description":"The `fido2` Python library provides comprehensive tools for implementing both client-side and server-side FIDO2/WebAuthn functionality. Currently at version 2.1.1, it maintains an active development pace with feature releases every few months and major versions approximately annually, ensuring compliance with the latest WebAuthn specifications (Level 3 working draft) and CTAP protocols.","status":"active","version":"2.1.1","language":"en","source_language":"en","source_url":"https://github.com/Yubico/python-fido2","tags":["fido2","webauthn","authentication","security","fido","yubico"],"install":[{"cmd":"pip install fido2","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Required for CBOR (Concise Binary Object Representation) encoding and decoding, which is fundamental to the FIDO2 protocol.","package":"cbor2","optional":false},{"reason":"Essential for cryptographic operations, including key generation, signature verification, and handling secure elements.","package":"cryptography","optional":false},{"reason":"Provides a monotonic clock source, used for timing-sensitive operations and preventing time-based attacks.","package":"monotonic","optional":false},{"reason":"Used for YAML parsing, potentially for configuration files, metadata, or specific utility functions.","package":"PyYAML","optional":false}],"imports":[{"symbol":"AttestationObject","correct":"from fido2.webauthn import AttestationObject"},{"symbol":"CollectedClientData","correct":"from fido2.webauthn import CollectedClientData"},{"note":"The primary verification functions are now top-level in `fido2.webauthn` for clarity.","wrong":"from fido2.webauthn import RegistrationResponse, AttestationStatement.verify(...)","symbol":"verify_registration_response","correct":"from fido2.webauthn import verify_registration_response"},{"symbol":"Fido2Client","correct":"from fido2.client import Fido2Client"},{"symbol":"cbor","correct":"from fido2 import cbor"}],"quickstart":{"code":"import os\nimport json\nimport base64\nfrom fido2.webauthn import (\n    AttestationObject,\n    CollectedClientData,\n    verify_registration_response,\n)\nfrom fido2 import cbor\n\n# --- Server-side configuration and stored data ---\n# In a real application, these would be generated and stored securely.\nRP_ID = os.environ.get(\"FIDO2_RP_ID\", \"example.com\")\nRP_ORIGIN = f\"https://{RP_ID}\"\n\n# A challenge issued previously by the server to the client for this registration attempt\n# This must be a cryptographically secure random 32-byte value.\nCHALLENGE = base64.urlsafe_b64decode(b\"uKz0s4zP6T3o-J2V-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3y=\") # Example base64url-encoded bytes for a 32-byte challenge\nUSER_ID = b\"some_unique_user_id_bytes\" # The user ID for whom registration was requested\nEXPECTED_RP_ID = RP_ID\nEXPECTED_ORIGINS = {RP_ORIGIN}\n\n# --- Simulate client-provided data (in a real app, these come from the browser) ---\n# Example: clientDataJSON received from the browser as a string\nclient_data_json_str = f'''\n{{\n    \"type\": \"webauthn.create\",\n    \"challenge\": \"{base64.urlsafe_b64encode(CHALLENGE).rstrip(b'=').decode('utf-8')}\",\n    \"origin\": \"{RP_ORIGIN}\",\n    \"crossOrigin\": false\n}}\n'''\n\n# Example: AttestationObject received from the browser as base64url-encoded CBOR bytes\n# This is a minimal 'none' attestation for demonstration purposes. \n# Real attestations are more complex.\nattestation_object_b64url = \"o2NmbXRoZJpvbmVhdHRTdG10oGhhdXRoRGF0YVjLp_hNq_D0D8x4jL17w2-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3yFkQAAAAAAAAAAAAAAAAAAAAAAwIAIAxM0k3Kz-k_D0x4jL17w2-5rX_s_L4l6m-c7C8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3yBoAAAAAAAAAAAAAAAAAAAAAADAAAAAQAg\"\n\n\n# --- Server-side verification using fido2 library ---\ntry:\n    # Parse the client data and attestation object\n    client_data = CollectedClientData(json.loads(client_data_json_str))\n    attestation_object = AttestationObject(base64.urlsafe_b64decode(attestation_object_b64url + \"==\")) # Add padding back for base64\n\n    # Verify the registration response\n    auth_data = verify_registration_response(\n        client_data=client_data,\n        attestation_object=attestation_object,\n        challenge=CHALLENGE,\n        rp_id=EXPECTED_RP_ID,\n        origins=EXPECTED_ORIGINS,\n        user_id=USER_ID\n        # In production, you would pass `trusted_attestation_public_keys`\n        # or `attestation_callback` to validate attestation certificates.\n    )\n\n    print(\"Registration successful!\")\n    print(f\"Credential ID: {base64.urlsafe_b64encode(auth_data.credential_id).decode('utf-8')}\")\n    print(f\"Public Key: {base64.urlsafe_b64encode(auth_data.credential_public_key).decode('utf-8')}\")\n    print(f\"Signature Count: {auth_data.sign_count}\")\n\n    # In a real application, you would store auth_data.credential_id, \n    # auth_data.credential_public_key, and auth_data.sign_count\n    # associated with the user for future authentication.\n\nexcept Exception as e:\n    print(f\"Registration failed: {e}\")","lang":"python","description":"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."},"warnings":[{"fix":"Ensure your environment runs Python 3.10 or newer before upgrading to fido2>=2.0.0.","message":"Version 2.0.0 introduced a minimum Python version requirement of 3.10 or later.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Update your code to pass all arguments to dataclass constructors as keyword arguments (e.g., `CollectedClientData(d=data)` instead of `CollectedClientData(data)`). Review the migration guide (doc/Migration_1-2.adoc) for detailed changes.","message":"WebAuthn dataclasses (e.g., `PublicKeyCredentialRpEntity`, `AttestationObject`, `CollectedClientData`) were significantly updated in v2.0.0. Constructors now require keyword arguments only, aligning with WebAuthn Level 3. Serialization to/from dictionaries is now compatible with standardized JSON formats.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Remove any explicit usage or checks for `features.webauthn_json_mapping`.","message":"The `features.webauthn_json_mapping` flag was removed in v2.0.0. Its behavior, which enabled standardized JSON formats for WebAuthn data structures, is now the default.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Migrate to the redesigned extension APIs introduced in fido2 version 1.2.0. Refer to the documentation for the new extension handling patterns.","message":"Old extension APIs, which were deprecated in version 1.2.0, have been removed entirely in version 2.0.0.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure that arguments passed to `websafe_decode` are always `str`. If you have `bytes`, decode them to `str` first (e.g., `my_bytes.decode('utf-8')`).","message":"The `websafe_decode` utility function (e.g., in `fido2.utils`) expects a `str` argument. Passing `bytes` was deprecated in 1.1.3 and will raise a `TypeError` in versions 2.0.0 and above.","severity":"gotcha","affected_versions":">=1.1.3"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}