use hex; use rand_core::{OsRng, TryRngCore}; use crate::model::config::Config; // We consider that it’s unfeasible to guess a token from 128 bit long (=16 bytes) to 256 bit (=32 bytes) with safe margin. const TOKEN_BYTES: usize = 32; pub fn login(config: &Config, token: &str) -> Result { Ok(cookie(config, &token, 365 * 24 * 60 * 60)) } pub fn logout(config: &Config) -> String { cookie(config, "", 0) } pub fn extract_token(cookie: &str) -> Result { let mut xs = cookie.split('='); if xs.next() != Some("TOKEN") { Err("Error extracting cookie".to_string()) } else { let token = xs.next().ok_or("Error extracting cookie")?; Ok(token.to_string()) } } pub fn generate_token() -> Result { let mut token = [0u8; TOKEN_BYTES]; OsRng .try_fill_bytes(&mut token) .map_err(|_| "Error generating random token")?; Ok(hex::encode(token)) } fn cookie(config: &Config, token: &str, max_age_seconds: i32) -> String { let mut xs = vec![ format!("TOKEN={token}"), "SameSite=Strict".to_string(), "HttpOnly".to_string(), format!("Max-Age={}", max_age_seconds), ]; if config.secure_cookies { xs.push("Secure".to_string()) } xs.join(";") }