# PasskeyAuth A minimal FastAPI WebAuthn server with WebSocket support for passkey registration. This project demonstrates WebAuthn registration flow with Resident Keys (discoverable credentials) using modern Python tooling. ## Features - ๐Ÿ” WebAuthn registration with Resident Keys support - ๐Ÿ”Œ WebSocket-based communication for real-time interaction - ๐Ÿš€ Modern Python packaging with `pyproject.toml` - ๐ŸŽจ Clean, responsive HTML interface using @simplewebauthn/browser - ๐Ÿ“ฆ No database required - challenges stored locally per connection - ๐Ÿ› ๏ธ Development tools: `ruff` for linting and formatting - ๐Ÿงน Clean architecture with local challenge management ## Requirements - Python 3.9+ - A WebAuthn-compatible authenticator (security key, biometric device, etc.) ## Quick Start ### Install (editable dev mode) ```fish uv pip install -e .[dev] ``` ### Run (new CLI) `passkey-auth` now provides subcommands: ```text passkey-auth serve [host:port] [--options] passkey-auth dev [--options] ``` Examples (fish shell shown): ```fish # Production style (no reload) passkey-auth serve passkey-auth serve 0.0.0.0:8080 --rp-id example.com --origin https://example.com # Development (auto-reload) passkey-auth dev # localhost:4401 passkey-auth dev :5500 # localhost on port 5500 passkey-auth dev 127.0.0.1 # host only, default port 4401 ``` Available options (both subcommands): ```text --rp-id Relying Party ID (default: localhost) --rp-name Relying Party name (default: same as rp-id) --origin Explicit origin (default: https://) ``` ### Legacy Invocation If you previously used `python -m passkey.fastapi --dev --host ...`, switch to the new form above. The old flags `--host`, `--port`, and `--dev` are replaced by the `[host:port]` positional and the `dev` subcommand. ## Usage (Web) 1. Start the server with one of the commands above 2. Open your browser to `http://localhost:4401/auth/` (or your chosen host/port) 3. Enter a username (or use the default) 4. Click "Register Passkey" 5. Follow your authenticator's prompts Real-time status updates stream over WebSocket. ## Development ### Code Quality ```fish # Run linting and formatting with ruff uv run ruff check . uv run ruff format . # Or with hatch hatch run ruff check . hatch run ruff format . ``` ### Project Structure ``` passkeyauth/ โ”œโ”€โ”€ passkeyauth/ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ””โ”€โ”€ main.py # FastAPI server with WebSocket support โ”œโ”€โ”€ static/ โ”‚ โ””โ”€โ”€ index.html # Frontend interface โ”œโ”€โ”€ pyproject.toml # Modern Python packaging configuration โ””โ”€โ”€ README.md ``` ## Technical Details ### WebAuthn Configuration - **Relying Party ID**: `localhost` (for development) - **Resident Keys**: Required (enables discoverable credentials) - **User Verification**: Preferred - **Supported Algorithms**: ECDSA-SHA256, RSASSA-PKCS1-v1_5-SHA256 ### WebSocket Message Flow 1. Client connects to `/ws/{client_id}` 2. Client sends `registration_challenge` message 3. Server responds with `registration_challenge_response` 4. Client completes WebAuthn ceremony and sends `registration_response` 5. Server verifies and responds with `registration_success` or `error` ### Security Notes - This is a minimal demo - challenges are stored locally per WebSocket connection - For production use, implement proper user storage and session management - Consider using Redis or similar for challenge storage in production with multiple server instances - Ensure HTTPS in production environments ## License MIT License - feel free to use this as a starting point for your own WebAuthn implementations!