Skip to main content

rustauth_passkey/
lib.rs

1//! Server-side passkey plugin for RustAuth.
2//!
3//! The plugin is server-only. It exposes Better Auth-inspired HTTP endpoints
4//! under `/passkey/*`, contributes a `passkeys` table to the RustAuth schema,
5//! and uses `webauthn-rs` for WebAuthn ceremony generation and verification.
6//!
7//! ```rust,no_run
8//! use rustauth_core::options::RustAuthOptions;
9//! use rustauth_passkey::{passkey, PasskeyOptions};
10//!
11//! let options = RustAuthOptions::new()
12//!     .secret("secret-a-at-least-32-chars-long!!")
13//!     .base_url("https://app.example.com")
14//!     .plugin(passkey(PasskeyOptions::default()));
15//! ```
16//!
17//! WebAuthn registration and authentication state is persisted server-side in
18//! RustAuth's `verification` storage and keyed by a signed short-lived cookie.
19//! This is why the crate enables `webauthn-rs` state serialization: the state is
20//! not trusted from the client and is deleted after successful verification.
21
22mod challenge;
23mod challenge_rate_limit;
24mod cookies;
25mod errors;
26mod openapi;
27mod options;
28mod response;
29mod routes;
30mod schema;
31mod session;
32mod store;
33mod webauthn;
34
35pub use errors::PASSKEY_ERROR_CODES;
36pub use options::{
37    AfterAuthenticationVerificationInput, AfterRegistrationVerificationInput,
38    AuthenticatorAttachment, AuthenticatorSelection, PasskeyAdvancedOptions,
39    PasskeyAuthenticationOptions, PasskeyAuthenticationRejected, PasskeyChallengeRateLimit,
40    PasskeyExtensionsInput, PasskeyManagementOptions, PasskeyOptions, PasskeyRateLimit,
41    PasskeyRegistrationOptions, PasskeyRegistrationUser, PasskeySchemaOptions,
42    RegistrationWebAuthnOptions, ResidentKeyRequirement, ResolveRegistrationUserInput,
43    UserVerificationRequirement,
44};
45pub use store::Passkey;
46pub use webauthn::{
47    PasskeyAuthenticationStart, PasskeyRegistrationStart, VerifiedAuthentication,
48    VerifiedPasskeyCredential, WebAuthnConfig,
49};
50
51#[cfg(feature = "test-util")]
52pub use webauthn::{PasskeyWebAuthnBackend, RealPasskeyWebAuthnBackend};
53
54use rustauth_core::plugin::{AuthPlugin, PluginRateLimitRule};
55
56pub const UPSTREAM_PLUGIN_ID: &str = "passkey";
57
58/// Ceremony endpoints that mint or consume WebAuthn challenges.
59pub const RATE_LIMITED_CEREMONY_PATHS: &[&str] = &[
60    "/passkey/generate-authenticate-options",
61    "/passkey/verify-authentication",
62    "/passkey/generate-register-options",
63    "/passkey/verify-registration",
64];
65
66/// Build the server-side passkey plugin.
67#[must_use]
68pub fn passkey(options: PasskeyOptions) -> AuthPlugin {
69    let rate_limit_rule = options.rate_limit_rule();
70    let options = std::sync::Arc::new(options);
71    let mut plugin = AuthPlugin::new(UPSTREAM_PLUGIN_ID).with_version(env!("CARGO_PKG_VERSION"));
72    for path in RATE_LIMITED_CEREMONY_PATHS {
73        plugin = plugin.with_rate_limit(PluginRateLimitRule::new(*path, rate_limit_rule.clone()));
74    }
75    for contribution in schema::contributions(&options) {
76        plugin = plugin.with_schema(contribution);
77    }
78    for code in errors::plugin_error_codes() {
79        plugin = plugin.with_error_code(code);
80    }
81    for endpoint in routes::endpoints(options) {
82        plugin = plugin.with_endpoint(endpoint);
83    }
84    plugin
85}