passkey_server/store.rs
1use crate::error::Result;
2use crate::types::{PasskeyState, StoredPasskey};
3use async_trait::async_trait;
4
5/// A trait for managing the persistence of passkeys and authentication state.
6///
7/// Implement this trait to connect the `passkey` library to your chosen database.
8/// All methods are `async` and use `async_trait(?Send)` for compatibility with WASM.
9#[cfg_attr(not(feature = "send"), async_trait(?Send))]
10#[cfg_attr(feature = "send", async_trait)]
11pub trait PasskeyStore {
12 /// Save a new passkey credential to the database.
13 ///
14 /// - `user_id`: The ID of the owner.
15 /// - `cred_id`: The unique identifier for this credential (Base64url).
16 /// - `public_key`: The public key material (Base64url-encoded COSE key).
17 /// - `name`: A human-readable name for the passkey.
18 /// - `counter`: The initial signature counter.
19 /// - `created_at`: Creation timestamp in milliseconds.
20 async fn create_passkey(
21 &self,
22 user_id: String,
23 cred_id: &str,
24 public_key: &str,
25 name: &str,
26 counter: i64,
27 created_at: i64,
28 ) -> Result<()>;
29
30 /// Retrieve a passkey by its credential ID.
31 async fn get_passkey(&self, cred_id: &str) -> Result<Option<StoredPasskey>>;
32
33 /// List all passkeys associated with a specific user.
34 async fn list_passkeys(&self, user_id: String) -> Result<Vec<StoredPasskey>>;
35
36 /// Delete a passkey. Implementations should verify that `user_id` owns the `cred_id`.
37 async fn delete_passkey(&self, user_id: String, cred_id: &str) -> Result<()>;
38
39 /// Update the signature counter and last-used timestamp after a successful login.
40 async fn update_passkey_counter(
41 &self,
42 cred_id: &str,
43 new_counter: i64,
44 last_used_at: i64,
45 ) -> Result<()>;
46
47 /// Rename an existing passkey.
48 async fn update_passkey_name(&self, cred_id: &str, new_name: &str) -> Result<()>;
49
50 /// Save ephemeral registration or login state (challenges).
51 ///
52 /// The `state_json` contains internal session data and should be retrievable by `id`.
53 /// `expires_at` is the expiration timestamp in milliseconds.
54 async fn save_state(&self, id: &str, state_json: &str, expires_at: i64) -> Result<()>;
55
56 /// Retrieve ephemeral state by its ID. It should return `None` if expired.
57 async fn get_state(&self, id: &str) -> Result<Option<PasskeyState>>;
58
59 /// Delete ephemeral state (e.g., after the session is finished or fails).
60 async fn delete_state(&self, id: &str) -> Result<()>;
61}