auth_framework/
config.rs

1//! Configuration types for the authentication framework.
2
3use crate::errors::{AuthError, Result};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::time::Duration;
7
8/// Main configuration for the authentication framework.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct AuthConfig {
11    /// Default token lifetime
12    pub token_lifetime: Duration,
13    
14    /// Refresh token lifetime
15    pub refresh_token_lifetime: Duration,
16    
17    /// Whether multi-factor authentication is enabled
18    pub enable_multi_factor: bool,
19    
20    /// Storage configuration
21    pub storage: StorageConfig,
22    
23    /// Rate limiting configuration
24    pub rate_limiting: RateLimitConfig,
25    
26    /// Security configuration
27    pub security: SecurityConfig,
28    
29    /// Audit logging configuration
30    pub audit: AuditConfig,
31    
32    /// Custom settings for different auth methods
33    pub method_configs: HashMap<String, serde_json::Value>,
34}
35
36/// Storage configuration options.
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub enum StorageConfig {
39    /// In-memory storage (not recommended for production)
40    Memory,
41    
42    /// Redis storage
43    #[cfg(feature = "redis-storage")]
44    Redis {
45        url: String,
46        key_prefix: String,
47    },
48    
49    /// PostgreSQL storage
50    #[cfg(feature = "postgres-storage")]
51    Postgres {
52        connection_string: String,
53        table_prefix: String,
54    },
55    
56    /// MySQL storage
57    #[cfg(feature = "mysql-storage")]
58    MySQL {
59        connection_string: String,
60        table_prefix: String,
61    },
62    
63    /// Custom storage backend
64    Custom(String),
65}
66
67/// Rate limiting configuration.
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct RateLimitConfig {
70    /// Enable rate limiting
71    pub enabled: bool,
72    
73    /// Maximum requests per window
74    pub max_requests: u32,
75    
76    /// Time window for rate limiting
77    pub window: Duration,
78    
79    /// Burst allowance
80    pub burst: u32,
81}
82
83/// Security configuration options.
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct SecurityConfig {
86    /// Minimum password length
87    pub min_password_length: usize,
88    
89    /// Require password complexity
90    pub require_password_complexity: bool,
91    
92    /// Password hash algorithm
93    pub password_hash_algorithm: PasswordHashAlgorithm,
94    
95    /// JWT signing algorithm
96    pub jwt_algorithm: JwtAlgorithm,
97    
98    /// Secret key for signing (should be loaded from environment)
99    pub secret_key: Option<String>,
100    
101    /// Enable secure cookies
102    pub secure_cookies: bool,
103    
104    /// Cookie SameSite policy
105    pub cookie_same_site: CookieSameSite,
106    
107    /// CSRF protection
108    pub csrf_protection: bool,
109    
110    /// Session timeout
111    pub session_timeout: Duration,
112}
113
114/// Password hashing algorithms.
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub enum PasswordHashAlgorithm {
117    Argon2,
118    Bcrypt,
119    Scrypt,
120}
121
122/// JWT signing algorithms.
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub enum JwtAlgorithm {
125    HS256,
126    HS384,
127    HS512,
128    RS256,
129    RS384,
130    RS512,
131    ES256,
132    ES384,
133}
134
135/// Cookie SameSite policies.
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub enum CookieSameSite {
138    Strict,
139    Lax,
140    None,
141}
142
143/// Audit logging configuration.
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct AuditConfig {
146    /// Enable audit logging
147    pub enabled: bool,
148    
149    /// Log successful authentications
150    pub log_success: bool,
151    
152    /// Log failed authentications
153    pub log_failures: bool,
154    
155    /// Log permission checks
156    pub log_permissions: bool,
157    
158    /// Log token operations
159    pub log_tokens: bool,
160    
161    /// Audit log storage
162    pub storage: AuditStorage,
163}
164
165/// Audit log storage options.
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub enum AuditStorage {
168    /// Standard logging (via tracing)
169    Tracing,
170    
171    /// File-based storage
172    File { path: String },
173    
174    /// Database storage
175    Database { connection_string: String },
176    
177    /// External service
178    External { endpoint: String, api_key: String },
179}
180
181impl Default for AuthConfig {
182    fn default() -> Self {
183        Self {
184            token_lifetime: Duration::from_secs(3600), // 1 hour
185            refresh_token_lifetime: Duration::from_secs(86400 * 7), // 7 days
186            enable_multi_factor: false,
187            storage: StorageConfig::Memory,
188            rate_limiting: RateLimitConfig::default(),
189            security: SecurityConfig::default(),
190            audit: AuditConfig::default(),
191            method_configs: HashMap::new(),
192        }
193    }
194}
195
196impl Default for RateLimitConfig {
197    fn default() -> Self {
198        Self {
199            enabled: true,
200            max_requests: 100,
201            window: Duration::from_secs(60), // 1 minute
202            burst: 10,
203        }
204    }
205}
206
207impl Default for SecurityConfig {
208    fn default() -> Self {
209        Self {
210            min_password_length: 8,
211            require_password_complexity: true,
212            password_hash_algorithm: PasswordHashAlgorithm::Argon2,
213            jwt_algorithm: JwtAlgorithm::HS256,
214            secret_key: None,
215            secure_cookies: true,
216            cookie_same_site: CookieSameSite::Lax,
217            csrf_protection: true,
218            session_timeout: Duration::from_secs(3600 * 24), // 24 hours
219        }
220    }
221}
222
223impl Default for AuditConfig {
224    fn default() -> Self {
225        Self {
226            enabled: true,
227            log_success: true,
228            log_failures: true,
229            log_permissions: true,
230            log_tokens: false, // Tokens can be sensitive
231            storage: AuditStorage::Tracing,
232        }
233    }
234}
235
236impl AuthConfig {
237    /// Create a new configuration with default values.
238    pub fn new() -> Self {
239        Self::default()
240    }
241
242    /// Set the token lifetime.
243    pub fn token_lifetime(mut self, lifetime: Duration) -> Self {
244        self.token_lifetime = lifetime;
245        self
246    }
247
248    /// Set the refresh token lifetime.
249    pub fn refresh_token_lifetime(mut self, lifetime: Duration) -> Self {
250        self.refresh_token_lifetime = lifetime;
251        self
252    }
253
254    /// Enable or disable multi-factor authentication.
255    pub fn enable_multi_factor(mut self, enabled: bool) -> Self {
256        self.enable_multi_factor = enabled;
257        self
258    }
259
260    /// Set the storage configuration.
261    pub fn storage(mut self, storage: StorageConfig) -> Self {
262        self.storage = storage;
263        self
264    }
265
266    /// Configure Redis storage.
267    #[cfg(feature = "redis-storage")]
268    pub fn redis_storage(mut self, url: impl Into<String>) -> Self {
269        self.storage = StorageConfig::Redis {
270            url: url.into(),
271            key_prefix: "auth:".to_string(),
272        };
273        self
274    }
275
276    /// Set rate limiting configuration.
277    pub fn rate_limiting(mut self, config: RateLimitConfig) -> Self {
278        self.rate_limiting = config;
279        self
280    }
281
282    /// Set security configuration.
283    pub fn security(mut self, config: SecurityConfig) -> Self {
284        self.security = config;
285        self
286    }
287
288    /// Set audit configuration.
289    pub fn audit(mut self, config: AuditConfig) -> Self {
290        self.audit = config;
291        self
292    }
293
294    /// Add configuration for a specific auth method.
295    pub fn method_config(
296        mut self,
297        method_name: impl Into<String>,
298        config: impl Serialize,
299    ) -> Result<Self> {
300        let value = serde_json::to_value(config)
301            .map_err(|e| AuthError::config(format!("Failed to serialize method config: {e}")))?;
302        
303        self.method_configs.insert(method_name.into(), value);
304        Ok(self)
305    }
306
307    /// Get configuration for a specific auth method.
308    pub fn get_method_config<T>(&self, method_name: &str) -> Result<Option<T>>
309    where
310        T: for<'de> Deserialize<'de>,
311    {
312        if let Some(value) = self.method_configs.get(method_name) {
313            let config = serde_json::from_value(value.clone())
314                .map_err(|e| AuthError::config(format!("Failed to deserialize method config: {e}")))?;
315            Ok(Some(config))
316        } else {
317            Ok(None)
318        }
319    }
320
321    /// Validate the configuration.
322    pub fn validate(&self) -> Result<()> {
323        // Validate token lifetimes
324        if self.token_lifetime.as_secs() == 0 {
325            return Err(AuthError::config("Token lifetime must be greater than 0"));
326        }
327
328        if self.refresh_token_lifetime.as_secs() == 0 {
329            return Err(AuthError::config("Refresh token lifetime must be greater than 0"));
330        }
331
332        if self.refresh_token_lifetime <= self.token_lifetime {
333            return Err(AuthError::config(
334                "Refresh token lifetime must be greater than token lifetime"
335            ));
336        }
337
338        // Validate security settings
339        if self.security.min_password_length < 4 {
340            return Err(AuthError::config(
341                "Minimum password length must be at least 4 characters"
342            ));
343        }
344
345        // Validate rate limiting
346        if self.rate_limiting.enabled && self.rate_limiting.max_requests == 0 {
347            return Err(AuthError::config(
348                "Rate limit max requests must be greater than 0 when enabled"
349            ));
350        }
351
352        Ok(())
353    }
354}
355
356impl RateLimitConfig {
357    /// Create a new rate limit configuration.
358    pub fn new(max_requests: u32, window: Duration) -> Self {
359        Self {
360            enabled: true,
361            max_requests,
362            window,
363            burst: max_requests / 10, // 10% of max as burst
364        }
365    }
366
367    /// Disable rate limiting.
368    pub fn disabled() -> Self {
369        Self {
370            enabled: false,
371            ..Default::default()
372        }
373    }
374}
375
376impl SecurityConfig {
377    /// Create a new security configuration with secure defaults.
378    pub fn secure() -> Self {
379        Self {
380            min_password_length: 12,
381            require_password_complexity: true,
382            password_hash_algorithm: PasswordHashAlgorithm::Argon2,
383            jwt_algorithm: JwtAlgorithm::RS256,
384            secret_key: None,
385            secure_cookies: true,
386            cookie_same_site: CookieSameSite::Strict,
387            csrf_protection: true,
388            session_timeout: Duration::from_secs(3600 * 8), // 8 hours
389        }
390    }
391
392    /// Create a development-friendly configuration.
393    pub fn development() -> Self {
394        Self {
395            min_password_length: 6,
396            require_password_complexity: false,
397            password_hash_algorithm: PasswordHashAlgorithm::Bcrypt,
398            jwt_algorithm: JwtAlgorithm::HS256,
399            secret_key: Some("development-secret-key".to_string()),
400            secure_cookies: false,
401            cookie_same_site: CookieSameSite::Lax,
402            csrf_protection: false,
403            session_timeout: Duration::from_secs(3600 * 24), // 24 hours
404        }
405    }
406}