WebAuthn API FIDO2 client implementation in Python.
A Python library for authenticating against WebAuthn/FIDO2 servers. Handles FIDO2 device discovery, assertion retrieval over CTAP HID, and server communication.
Tested against the python-fido2 server example.
- Python 3.9+
- A FIDO2-compatible USB authenticator (e.g. YubiKey)
- A WebAuthn server implementing the begin/complete authentication flow using CBOR encoding
pip install fido2clientimport fido2client
with fido2client.Fido2HttpClient() as client:
authenticated = client.authenticate_to(
'https://your-server.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
)
if authenticated:
print('Authenticated!')from fido2client import Fido2HttpClient
client = Fido2HttpClient()
result = client.authenticate_to(
'https://example.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
)client = Fido2HttpClient()
result = client.authenticate_to(
'https://example.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
extra_headers={'Authorization': 'Bearer <token>'},
extra_data={'session_id': 'abc123'},
)import requests
from fido2client import Fido2HttpClient
session = requests.Session()
session.cookies.set('csrf_token', '...')
client = Fido2HttpClient()
result = client.authenticate_to(
'https://example.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
session=session,
)The context manager ensures the HTTP session is closed when done:
from fido2client import Fido2HttpClient
with Fido2HttpClient() as client:
result = client.authenticate_to(
'https://example.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
)from fido2client import Fido2HttpClient
from fido2client.exceptions import FidoDeviceNotFoundError, FidoServerError
import requests
try:
with Fido2HttpClient() as client:
result = client.authenticate_to(
'https://example.com',
'/api/authenticate/begin',
'/api/authenticate/complete',
)
except FidoDeviceNotFoundError:
print('No FIDO2 device found. Connect your authenticator and try again.')
except FidoServerError as e:
print(f'Server communication failed: {e}')
except requests.exceptions.RequestException as e:
print(f'Network error: {e}')client = Fido2HttpClient(
ssl_verify=True, # Verify TLS certificates (default: True, always use in production)
timeout=30, # HTTP request timeout in seconds (default: 30)
verbose=False, # Shortcut to enable DEBUG logging (default: False)
)Security note:
ssl_verify=Falsedisables TLS certificate verification entirely. Never use this in production — it makes the connection vulnerable to man-in-the-middle attacks. It is only appropriate for local development environments using self-signed certificates.
Rather than using the verbose flag, you can configure the standard Python logging module:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('fido2client').setLevel(logging.DEBUG)For local testing against a server using a self-signed certificate:
import fido2client
# WARNING: ssl_verify=False is for local development only.
# Never use in production.
c = fido2client.Fido2HttpClient(ssl_verify=False, verbose=True)
c.authenticate_to(
'https://localhost:5000',
'/api/authenticate/begin',
'/api/authenticate/complete',
)pip install -e ".[dev]"
pytest| Exception | Raised when |
|---|---|
Fido2ClientError |
Base class for all fido2client errors |
FidoDeviceNotFoundError |
No FIDO2 device is connected |
FidoServerError |
Server returns an unreadable or unexpected response |
FidoAuthenticationError |
The authentication ceremony cannot proceed |
MIT
TODO
- define details of the state machine for interactive and programmatical use cases
- support for credential registration