Skip to main content

modo/auth/session/
config.rs

1use serde::Deserialize;
2
3fn deserialize_nonzero_usize<'de, D>(deserializer: D) -> Result<usize, D::Error>
4where
5    D: serde::Deserializer<'de>,
6{
7    let value = usize::deserialize(deserializer)?;
8    if value == 0 {
9        return Err(serde::de::Error::custom(
10            "max_sessions_per_user must be > 0; setting it to 0 would lock out all users",
11        ));
12    }
13    Ok(value)
14}
15
16/// Configuration for the session middleware.
17///
18/// Deserialised from the `session` key in the application YAML config.
19/// All fields have defaults, so an empty `session:` block is valid.
20///
21/// # YAML example
22///
23/// ```yaml
24/// session:
25///   session_ttl_secs: 2592000   # 30 days
26///   cookie_name: "_session"
27///   validate_fingerprint: true
28///   touch_interval_secs: 300    # 5 minutes
29///   max_sessions_per_user: 10
30/// ```
31#[non_exhaustive]
32#[derive(Debug, Clone, Deserialize)]
33#[serde(default)]
34pub struct SessionConfig {
35    /// Session lifetime in seconds. Defaults to `2_592_000` (30 days).
36    pub session_ttl_secs: u64,
37    /// Name of the session cookie. Defaults to `"_session"`.
38    pub cookie_name: String,
39    /// When `true`, the middleware rejects requests whose browser fingerprint
40    /// does not match the one recorded at login. Defaults to `true`.
41    pub validate_fingerprint: bool,
42    /// Minimum interval between `last_active_at` updates, in seconds.
43    /// A session is only touched when at least this many seconds have elapsed
44    /// since the last touch. Defaults to `300` (5 minutes).
45    pub touch_interval_secs: u64,
46    /// Maximum number of concurrent active sessions per user. When exceeded,
47    /// the least-recently-used session is evicted. Must be greater than zero.
48    /// Defaults to `10`.
49    #[serde(deserialize_with = "deserialize_nonzero_usize")]
50    pub max_sessions_per_user: usize,
51}
52
53impl Default for SessionConfig {
54    fn default() -> Self {
55        Self {
56            session_ttl_secs: 2_592_000,
57            cookie_name: "_session".to_string(),
58            validate_fingerprint: true,
59            touch_interval_secs: 300,
60            max_sessions_per_user: 10,
61        }
62    }
63}