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        panic!("PASSKEY_SIGNAL_API_MODE='{mode}' is invalid. Valid values: {valid_modes:?}");
27    }
28    mode
29});
30
31/// Demo mode flag for public demo sites
32///
33/// When enabled (`O2P_DEMO_MODE=true`):
34/// - All new users are created with admin privileges by default
35/// - Admin views mask other users' sensitive data (emails, IPs, credentials)
36/// - A placeholder user with sequence_number=1 is created at init, so all
37///   real users start from sequence_number=2 (no first-user special treatment)
38///
39/// This is a single toggle that activates all demo-specific behavior,
40/// preventing accidental misconfiguration (e.g., granting admin to all
41/// users without also enabling data masking).
42///
43/// Default: false
44pub static O2P_DEMO_MODE: LazyLock<bool> = LazyLock::new(|| match std::env::var("O2P_DEMO_MODE") {
45    Err(_) => false,
46    Ok(val) => match val.to_lowercase().as_str() {
47        "true" => true,
48        "false" => false,
49        _ => panic!("O2P_DEMO_MODE='{val}' is invalid. Valid values: true, false"),
50    },
51});
52
53/// User ID for the demo mode placeholder user (sequence_number=1)
54///
55/// This placeholder occupies sequence_number=1 so that no real user gets
56/// the first-user special protections (immutable admin, undeletable).
57/// It is filtered from admin views and has no credentials or sessions.
58pub const DEMO_PLACEHOLDER_USER_ID: &str = "__demo_placeholder__";
59
60#[cfg(test)]
61mod tests;