Skip to main content

passkey_server/
lib.rs

1//! # Passkey
2//!
3//! A generic Rust implementation of the WebAuthn (Passkey) protocol, designed to be
4//! storage-agnostic and easy to integrate into any backend.
5//!
6//! ## Features
7//!
8//! - **Generic Storage**: Implement the [`PasskeyStore`] trait to use your own database.
9//! - **WASM Friendly**: Works well in WASM environments like Cloudflare Workers.
10//! - **Simple Protocol Handlers**: Provides high-level functions for the standard WebAuthn registration and login flows.
11//!
12//! ## Example usage
13//!
14//! For a complete, runnable example using Axum and an in-memory store, see [`examples/basic.rs`](https://github.com/Asutorufa/housou/blob/main/crates/passkey/examples/basic.rs).
15//!
16//! ```rust,no_run
17//! use passkey_server::{PasskeyConfig, PasskeyStore, start_registration, types::{StoredPasskey, PasskeyState}, error::Result};
18//! use async_trait::async_trait;
19//!
20//! // Example usage requires implementing the PasskeyStore trait
21//! struct MyDatabase;
22//!
23//! #[async_trait(?Send)]
24//! impl PasskeyStore for MyDatabase {
25//!     async fn create_passkey(&self, _: String, _: &str, _: &str, _: &str, _: i64, _: i64) -> Result<()> { Ok(()) }
26//!     async fn get_passkey(&self, _: &str) -> Result<Option<StoredPasskey>> { Ok(None) }
27//!     async fn list_passkeys(&self, _: String) -> Result<Vec<StoredPasskey>> { Ok(vec![]) }
28//!     async fn delete_passkey(&self, _: String, _: &str) -> Result<()> { Ok(()) }
29//!     async fn update_passkey_counter(&self, _: &str, _: i64, _: i64) -> Result<()> { Ok(()) }
30//!     async fn update_passkey_name(&self, _: &str, _: &str) -> Result<()> { Ok(()) }
31//!     async fn save_state(&self, _: &str, _: &str, _: i64) -> Result<()> { Ok(()) }
32//!     async fn get_state(&self, _: &str) -> Result<Option<PasskeyState>> { Ok(None) }
33//!     async fn delete_state(&self, _: &str) -> Result<()> { Ok(()) }
34//! }
35//!
36//! #[tokio::main]
37//! async fn main() {
38//!     let config = PasskeyConfig {
39//!         rp_id: "example.com".to_string(),
40//!         rp_name: "My App".to_string(),
41//!         origin: "https://example.com".to_string(),
42//!         state_ttl: 300,
43//!     };
44//!
45//!     let store = MyDatabase;
46//!     let user_id = "123";
47//!     let now_ms = 1708358400000;
48//!
49//!     // 1. Start registration
50//!     let options = start_registration(
51//!         &store,
52//!         user_id,
53//!         "alice",
54//!         "Alice Doe",
55//!         &config,
56//!         now_ms
57//!     ).await.unwrap();
58//!
59//!     println!("Send these options to the frontend: {:?}", options);
60//! }
61//! ```
62
63pub mod error;
64pub mod protocol;
65pub mod store;
66pub mod types;
67
68pub use error::{PasskeyError, Result};
69pub use protocol::{finish_login, finish_registration, start_login, start_registration};
70pub use store::PasskeyStore;
71pub use types::PasskeyConfig;
72
73#[cfg(test)]
74mod tests;