Skip to main content

oauth2_passkey/
config.rs

1//! Central configuration for the oauth2_passkey crate
2
3use std::sync::LazyLock;
4
5/// Route prefix for all oauth2_passkey endpoints
6///
7/// This is the main prefix under which all authentication endpoints will be mounted.
8/// Default: "/o2p"
9pub static O2P_ROUTE_PREFIX: LazyLock<String> =
10    LazyLock::new(|| std::env::var("O2P_ROUTE_PREFIX").unwrap_or_else(|_| "/o2p".to_string()));
11
12/// Signal API mode for credential synchronization with authenticators.
13///
14/// Controls which WebAuthn Signal APIs are called for credential deletion and login sync:
15/// - `"direct"`: Use `signalUnknownCredential` only (default, currently the only working API
16///   with Google Password Manager)
17/// - `"sync"`: Use `signalAllAcceptedCredentials` only (currently no effect on Chrome,
18///   may work with other authenticators)
19/// - `"direct+sync"`: Use both APIs for maximum compatibility
20///
21/// Default: "direct"
22pub static PASSKEY_SIGNAL_API_MODE: LazyLock<String> = LazyLock::new(|| {
23    let mode = std::env::var("PASSKEY_SIGNAL_API_MODE").unwrap_or_else(|_| "direct".to_string());
24    let valid_modes = ["direct", "sync", "direct+sync"];
25    if !valid_modes.contains(&mode.as_str()) {
26        tracing::warn!(
27            "Invalid PASSKEY_SIGNAL_API_MODE '{}', valid values are: {:?}. Using 'direct'.",
28            mode,
29            valid_modes
30        );
31        "direct".to_string()
32    } else {
33        mode
34    }
35});
36
37/// Demo mode flag for public demo sites
38///
39/// When enabled (`O2P_DEMO_MODE=true`):
40/// - All new users are created with admin privileges by default
41/// - Admin views mask other users' sensitive data (emails, IPs, credentials)
42/// - A placeholder user with sequence_number=1 is created at init, so all
43///   real users start from sequence_number=2 (no first-user special treatment)
44///
45/// This is a single toggle that activates all demo-specific behavior,
46/// preventing accidental misconfiguration (e.g., granting admin to all
47/// users without also enabling data masking).
48///
49/// Default: false
50pub static O2P_DEMO_MODE: LazyLock<bool> = LazyLock::new(|| {
51    std::env::var("O2P_DEMO_MODE")
52        .map(|val| val.to_lowercase() == "true")
53        .unwrap_or(false)
54});
55
56/// User ID for the demo mode placeholder user (sequence_number=1)
57///
58/// This placeholder occupies sequence_number=1 so that no real user gets
59/// the first-user special protections (immutable admin, undeletable).
60/// It is filtered from admin views and has no credentials or sessions.
61pub const DEMO_PLACEHOLDER_USER_ID: &str = "__demo_placeholder__";
62
63#[cfg(test)]
64mod tests;