leptos_sync_core/security/
authentication.rs

1//! Authentication system with comprehensive user management and security features
2
3use crate::SyncError;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use tokio::sync::RwLock;
7use chrono::{DateTime, Utc, Duration};
8use sha2::{Sha256, Digest};
9use rand::{Rng, rngs::OsRng};
10use base64::{Engine as _, engine::general_purpose};
11
12/// Authentication provider types
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub enum AuthProvider {
15    Local,
16    OAuth2,
17    JWT,
18    LDAP,
19}
20
21/// User session information
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct UserSession {
24    pub user_id: String,
25    pub token: String,
26    pub expires_at: DateTime<Utc>,
27    pub created_at: DateTime<Utc>,
28    pub last_activity: DateTime<Utc>,
29    pub ip_address: Option<String>,
30    pub user_agent: Option<String>,
31}
32
33/// User account information
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct User {
36    pub id: String,
37    pub username: String,
38    pub email: String,
39    pub password_hash: String,
40    pub salt: String,
41    pub created_at: DateTime<Utc>,
42    pub last_login: Option<DateTime<Utc>>,
43    pub is_active: bool,
44    pub is_verified: bool,
45    pub mfa_enabled: bool,
46    pub mfa_secret: Option<String>,
47    pub failed_login_attempts: u32,
48    pub locked_until: Option<DateTime<Utc>>,
49}
50
51/// Password reset token
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct PasswordResetToken {
54    pub token: String,
55    pub user_id: String,
56    pub expires_at: DateTime<Utc>,
57    pub created_at: DateTime<Utc>,
58    pub used: bool,
59}
60
61/// Authentication configuration
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct AuthConfig {
64    pub session_timeout: Duration,
65    pub max_failed_attempts: u32,
66    pub lockout_duration: Duration,
67    pub password_min_length: usize,
68    pub require_uppercase: bool,
69    pub require_lowercase: bool,
70    pub require_numbers: bool,
71    pub require_special_chars: bool,
72    pub mfa_required: bool,
73}
74
75impl Default for AuthConfig {
76    fn default() -> Self {
77        Self {
78            session_timeout: Duration::hours(24),
79            max_failed_attempts: 5,
80            lockout_duration: Duration::minutes(30),
81            password_min_length: 8,
82            require_uppercase: true,
83            require_lowercase: true,
84            require_numbers: true,
85            require_special_chars: true,
86            mfa_required: false,
87        }
88    }
89}
90
91/// Authentication manager for handling user authentication and sessions
92pub struct AuthenticationManager {
93    config: AuthConfig,
94    users: RwLock<HashMap<String, User>>,
95    sessions: RwLock<HashMap<String, UserSession>>,
96    reset_tokens: RwLock<HashMap<String, PasswordResetToken>>,
97}
98
99impl AuthenticationManager {
100    /// Create a new authentication manager
101    pub fn new() -> Self {
102        Self {
103            config: AuthConfig::default(),
104            users: RwLock::new(HashMap::new()),
105            sessions: RwLock::new(HashMap::new()),
106            reset_tokens: RwLock::new(HashMap::new()),
107        }
108    }
109
110    /// Create a new authentication manager with custom configuration
111    pub fn with_config(config: AuthConfig) -> Self {
112        Self {
113            config,
114            users: RwLock::new(HashMap::new()),
115            sessions: RwLock::new(HashMap::new()),
116            reset_tokens: RwLock::new(HashMap::new()),
117        }
118    }
119
120    /// Register a new user
121    pub async fn register_user(&self, username: &str, password: &str, email: &str) -> Result<String, SyncError> {
122        // Validate password strength
123        self.validate_password(password)?;
124
125        // Check if user already exists
126        let users = self.users.read().await;
127        if users.values().any(|u| u.username == username || u.email == email) {
128            return Err(SyncError::AuthenticationError("User already exists".to_string()));
129        }
130        drop(users);
131
132        // Generate user ID
133        let user_id = self.generate_user_id();
134
135        // Hash password
136        let (password_hash, salt) = self.hash_password(password)?;
137
138        // Create user
139        let user = User {
140            id: user_id.clone(),
141            username: username.to_string(),
142            email: email.to_string(),
143            password_hash,
144            salt,
145            created_at: Utc::now(),
146            last_login: None,
147            is_active: true,
148            is_verified: false,
149            mfa_enabled: false,
150            mfa_secret: None,
151            failed_login_attempts: 0,
152            locked_until: None,
153        };
154
155        // Store user
156        let mut users = self.users.write().await;
157        users.insert(user_id.clone(), user);
158
159        Ok(user_id)
160    }
161
162    /// Authenticate user with username and password
163    pub async fn login(&self, username: &str, password: &str) -> Result<UserSession, SyncError> {
164        // Find user
165        let user = self.find_user_by_username(username).await?;
166
167        // Check if user is locked
168        if let Some(locked_until) = user.locked_until {
169            if Utc::now() < locked_until {
170                return Err(SyncError::AuthenticationError("Account is locked".to_string()));
171            }
172        }
173
174        // Check if user is active
175        if !user.is_active {
176            return Err(SyncError::AuthenticationError("Account is inactive".to_string()));
177        }
178
179        // Verify password
180        if !self.verify_password(password, &user.password_hash, &user.salt)? {
181            // Increment failed login attempts
182            self.increment_failed_attempts(&user.id).await?;
183            return Err(SyncError::AuthenticationError("Invalid credentials".to_string()));
184        }
185
186        // Check if MFA is enabled for user
187        if user.mfa_enabled {
188            return Err(SyncError::AuthenticationError("MFA required - use login_with_mfa method".to_string()));
189        }
190
191        // Reset failed login attempts on successful login
192        self.reset_failed_attempts(&user.id).await?;
193
194        // Update last login
195        self.update_last_login(&user.id).await?;
196
197        // Create session
198        let session = self.create_session(&user.id).await?;
199
200        Ok(session)
201    }
202
203    /// Authenticate user with MFA
204    pub async fn login_with_mfa(&self, username: &str, password: &str, mfa_code: &str) -> Result<UserSession, SyncError> {
205        // First authenticate with password
206        let user = self.find_user_by_username(username).await?;
207
208        // Check if user is locked
209        if let Some(locked_until) = user.locked_until {
210            if Utc::now() < locked_until {
211                return Err(SyncError::AuthenticationError("Account is locked".to_string()));
212            }
213        }
214
215        // Check if user is active
216        if !user.is_active {
217            return Err(SyncError::AuthenticationError("Account is inactive".to_string()));
218        }
219
220        // Verify password
221        if !self.verify_password(password, &user.password_hash, &user.salt)? {
222            self.increment_failed_attempts(&user.id).await?;
223            return Err(SyncError::AuthenticationError("Invalid credentials".to_string()));
224        }
225
226        // Check if MFA is enabled
227        if !user.mfa_enabled {
228            return Err(SyncError::AuthenticationError("MFA not enabled for user".to_string()));
229        }
230
231        // Verify MFA code
232        if !self.verify_mfa_code(&user.id, mfa_code).await? {
233            self.increment_failed_attempts(&user.id).await?;
234            return Err(SyncError::AuthenticationError("Invalid MFA code".to_string()));
235        }
236
237        // Reset failed login attempts
238        self.reset_failed_attempts(&user.id).await?;
239
240        // Update last login
241        self.update_last_login(&user.id).await?;
242
243        // Create session
244        let session = self.create_session(&user.id).await?;
245
246        Ok(session)
247    }
248
249    /// Validate user session
250    pub async fn validate_session(&self, token: &str) -> Result<bool, SyncError> {
251        let sessions = self.sessions.read().await;
252        if let Some(session) = sessions.get(token) {
253            // Check if session is expired
254            if Utc::now() > session.expires_at {
255                drop(sessions);
256                self.logout(token).await?;
257                return Ok(false);
258            }
259
260            // Update last activity
261            drop(sessions);
262            self.update_session_activity(token).await?;
263            Ok(true)
264        } else {
265            Ok(false)
266        }
267    }
268
269    /// Logout user
270    pub async fn logout(&self, token: &str) -> Result<(), SyncError> {
271        let mut sessions = self.sessions.write().await;
272        sessions.remove(token);
273        Ok(())
274    }
275
276    /// Initiate password reset
277    pub async fn initiate_password_reset(&self, username: &str) -> Result<String, SyncError> {
278        let user = self.find_user_by_username(username).await?;
279
280        // Generate reset token
281        let token = self.generate_reset_token();
282        let expires_at = Utc::now() + Duration::hours(1);
283
284        let reset_token = PasswordResetToken {
285            token: token.clone(),
286            user_id: user.id.clone(),
287            expires_at,
288            created_at: Utc::now(),
289            used: false,
290        };
291
292        // Store reset token
293        let mut reset_tokens = self.reset_tokens.write().await;
294        reset_tokens.insert(token.clone(), reset_token);
295
296        Ok(token)
297    }
298
299    /// Complete password reset
300    pub async fn complete_password_reset(&self, token: &str, new_password: &str) -> Result<(), SyncError> {
301        // Validate new password
302        self.validate_password(new_password)?;
303
304        // Find reset token
305        let mut reset_tokens = self.reset_tokens.write().await;
306        if let Some(reset_token) = reset_tokens.get_mut(token) {
307            // Check if token is expired
308            if Utc::now() > reset_token.expires_at {
309                return Err(SyncError::AuthenticationError("Reset token has expired".to_string()));
310            }
311
312            // Check if token is already used
313            if reset_token.used {
314                return Err(SyncError::AuthenticationError("Reset token has already been used".to_string()));
315            }
316
317            // Mark token as used
318            reset_token.used = true;
319
320            // Update user password
321            let (password_hash, salt) = self.hash_password(new_password)?;
322            let mut users = self.users.write().await;
323            if let Some(user) = users.get_mut(&reset_token.user_id) {
324                user.password_hash = password_hash;
325                user.salt = salt;
326                user.failed_login_attempts = 0;
327                user.locked_until = None;
328            }
329
330            Ok(())
331        } else {
332            Err(SyncError::AuthenticationError("Invalid reset token".to_string()))
333        }
334    }
335
336    /// Enable MFA for user
337    pub async fn enable_mfa(&self, user_id: &str) -> Result<(), SyncError> {
338        let mut users = self.users.write().await;
339        if let Some(user) = users.get_mut(user_id) {
340            user.mfa_enabled = true;
341            user.mfa_secret = Some(self.generate_mfa_secret());
342        } else {
343            return Err(SyncError::AuthenticationError("User not found".to_string()));
344        }
345        Ok(())
346    }
347
348    /// Generate MFA code for user
349    pub async fn generate_mfa_code(&self, user_id: &str) -> Result<String, SyncError> {
350        let users = self.users.read().await;
351        if let Some(user) = users.get(user_id) {
352            if let Some(secret) = &user.mfa_secret {
353                // Generate TOTP code (simplified implementation)
354                let code = self.generate_totp_code(secret);
355                Ok(code)
356            } else {
357                Err(SyncError::AuthenticationError("MFA secret not found".to_string()))
358            }
359        } else {
360            Err(SyncError::AuthenticationError("User not found".to_string()))
361        }
362    }
363
364    /// Find user by username
365    async fn find_user_by_username(&self, username: &str) -> Result<User, SyncError> {
366        let users = self.users.read().await;
367        users.values()
368            .find(|u| u.username == username)
369            .cloned()
370            .ok_or_else(|| SyncError::AuthenticationError("User not found".to_string()))
371    }
372
373    /// Hash password with salt
374    fn hash_password(&self, password: &str) -> Result<(String, String), SyncError> {
375        let salt = self.generate_salt();
376        let mut hasher = Sha256::new();
377        hasher.update(password.as_bytes());
378        hasher.update(salt.as_bytes());
379        let hash = hasher.finalize();
380        let hash_string = general_purpose::STANDARD.encode(hash);
381        Ok((hash_string, salt))
382    }
383
384    /// Verify password
385    fn verify_password(&self, password: &str, hash: &str, salt: &str) -> Result<bool, SyncError> {
386        let mut hasher = Sha256::new();
387        hasher.update(password.as_bytes());
388        hasher.update(salt.as_bytes());
389        let computed_hash = hasher.finalize();
390        let computed_hash_string = general_purpose::STANDARD.encode(computed_hash);
391        Ok(computed_hash_string == hash)
392    }
393
394    /// Validate password strength
395    fn validate_password(&self, password: &str) -> Result<(), SyncError> {
396        if password.len() < self.config.password_min_length {
397            return Err(SyncError::AuthenticationError(format!(
398                "Password must be at least {} characters long",
399                self.config.password_min_length
400            )));
401        }
402
403        if self.config.require_uppercase && !password.chars().any(|c| c.is_uppercase()) {
404            return Err(SyncError::AuthenticationError("Password must contain at least one uppercase letter".to_string()));
405        }
406
407        if self.config.require_lowercase && !password.chars().any(|c| c.is_lowercase()) {
408            return Err(SyncError::AuthenticationError("Password must contain at least one lowercase letter".to_string()));
409        }
410
411        if self.config.require_numbers && !password.chars().any(|c| c.is_numeric()) {
412            return Err(SyncError::AuthenticationError("Password must contain at least one number".to_string()));
413        }
414
415        if self.config.require_special_chars && !password.chars().any(|c| "!@#$%^&*()_+-=[]{}|;:,.<>?".contains(c)) {
416            return Err(SyncError::AuthenticationError("Password must contain at least one special character".to_string()));
417        }
418
419        Ok(())
420    }
421
422    /// Generate user ID
423    fn generate_user_id(&self) -> String {
424        let mut rng = OsRng;
425        let random_bytes: [u8; 16] = rng.r#gen();
426        format!("user_{}", general_purpose::STANDARD.encode(random_bytes))
427    }
428
429    /// Generate salt
430    fn generate_salt(&self) -> String {
431        let mut rng = OsRng;
432        let random_bytes: [u8; 16] = rng.r#gen();
433        general_purpose::STANDARD.encode(random_bytes)
434    }
435
436    /// Generate session token
437    fn generate_session_token(&self) -> String {
438        let mut rng = OsRng;
439        let random_bytes: [u8; 32] = rng.r#gen();
440        general_purpose::STANDARD.encode(random_bytes)
441    }
442
443    /// Generate reset token
444    fn generate_reset_token(&self) -> String {
445        let mut rng = OsRng;
446        let random_bytes: [u8; 32] = rng.r#gen();
447        general_purpose::STANDARD.encode(random_bytes)
448    }
449
450    /// Generate MFA secret
451    fn generate_mfa_secret(&self) -> String {
452        let mut rng = OsRng;
453        let random_bytes: [u8; 20] = rng.r#gen();
454        general_purpose::STANDARD.encode(random_bytes)
455    }
456
457    /// Generate TOTP code (simplified implementation)
458    fn generate_totp_code(&self, secret: &str) -> String {
459        // Simplified TOTP implementation - in production, use a proper TOTP library
460        let timestamp = Utc::now().timestamp() / 30;
461        let mut hasher = Sha256::new();
462        hasher.update(secret.as_bytes());
463        hasher.update(timestamp.to_be_bytes());
464        let hash = hasher.finalize();
465        let code = (hash[0] as u32 % 1000000) as u32;
466        format!("{:06}", code)
467    }
468
469    /// Create user session
470    async fn create_session(&self, user_id: &str) -> Result<UserSession, SyncError> {
471        let token = self.generate_session_token();
472        let now = Utc::now();
473        let expires_at = now + self.config.session_timeout;
474
475        let session = UserSession {
476            user_id: user_id.to_string(),
477            token: token.clone(),
478            expires_at,
479            created_at: now,
480            last_activity: now,
481            ip_address: None,
482            user_agent: None,
483        };
484
485        let mut sessions = self.sessions.write().await;
486        sessions.insert(token, session.clone());
487
488        Ok(session)
489    }
490
491    /// Update session activity
492    async fn update_session_activity(&self, token: &str) -> Result<(), SyncError> {
493        let mut sessions = self.sessions.write().await;
494        if let Some(session) = sessions.get_mut(token) {
495            session.last_activity = Utc::now();
496        }
497        Ok(())
498    }
499
500    /// Increment failed login attempts
501    async fn increment_failed_attempts(&self, user_id: &str) -> Result<(), SyncError> {
502        let mut users = self.users.write().await;
503        if let Some(user) = users.get_mut(user_id) {
504            user.failed_login_attempts += 1;
505            if user.failed_login_attempts >= self.config.max_failed_attempts {
506                user.locked_until = Some(Utc::now() + self.config.lockout_duration);
507            }
508        }
509        Ok(())
510    }
511
512    /// Reset failed login attempts
513    async fn reset_failed_attempts(&self, user_id: &str) -> Result<(), SyncError> {
514        let mut users = self.users.write().await;
515        if let Some(user) = users.get_mut(user_id) {
516            user.failed_login_attempts = 0;
517            user.locked_until = None;
518        }
519        Ok(())
520    }
521
522    /// Update last login
523    async fn update_last_login(&self, user_id: &str) -> Result<(), SyncError> {
524        let mut users = self.users.write().await;
525        if let Some(user) = users.get_mut(user_id) {
526            user.last_login = Some(Utc::now());
527        }
528        Ok(())
529    }
530
531    /// Verify MFA code
532    async fn verify_mfa_code(&self, user_id: &str, code: &str) -> Result<bool, SyncError> {
533        let users = self.users.read().await;
534        if let Some(user) = users.get(user_id) {
535            if let Some(secret) = &user.mfa_secret {
536                let expected_code = self.generate_totp_code(secret);
537                Ok(expected_code == code)
538            } else {
539                Ok(false)
540            }
541        } else {
542            Ok(false)
543        }
544    }
545
546    /// Get user by ID
547    pub async fn get_user(&self, user_id: &str) -> Result<User, SyncError> {
548        let users = self.users.read().await;
549        users.get(user_id)
550            .cloned()
551            .ok_or_else(|| SyncError::AuthenticationError("User not found".to_string()))
552    }
553
554    /// List all users
555    pub async fn list_users(&self) -> Vec<User> {
556        let users = self.users.read().await;
557        users.values().cloned().collect()
558    }
559
560    /// Clean up expired sessions
561    pub async fn cleanup_expired_sessions(&self) -> usize {
562        let mut sessions = self.sessions.write().await;
563        let now = Utc::now();
564        let expired_tokens: Vec<String> = sessions
565            .iter()
566            .filter(|(_, session)| session.expires_at < now)
567            .map(|(token, _)| token.clone())
568            .collect();
569
570        for token in &expired_tokens {
571            sessions.remove(token);
572        }
573
574        expired_tokens.len()
575    }
576
577    /// Clean up expired reset tokens
578    pub async fn cleanup_expired_reset_tokens(&self) -> usize {
579        let mut reset_tokens = self.reset_tokens.write().await;
580        let now = Utc::now();
581        let expired_tokens: Vec<String> = reset_tokens
582            .iter()
583            .filter(|(_, token)| token.expires_at < now)
584            .map(|(token, _)| token.clone())
585            .collect();
586
587        for token in &expired_tokens {
588            reset_tokens.remove(token);
589        }
590
591        expired_tokens.len()
592    }
593}
594
595#[cfg(test)]
596mod tests {
597    use super::*;
598
599    #[tokio::test]
600    async fn test_user_registration() {
601        let auth_manager = AuthenticationManager::new();
602        let username = "test_user";
603        let password = "SecurePassword123!";
604        let email = "test@example.com";
605        
606        let result = auth_manager.register_user(username, password, email).await;
607        assert!(result.is_ok());
608        
609        let user_id = result.unwrap();
610        assert!(!user_id.is_empty());
611    }
612
613    #[tokio::test]
614    async fn test_user_login() {
615        let auth_manager = AuthenticationManager::new();
616        let username = "test_user";
617        let password = "SecurePassword123!";
618        let email = "test@example.com";
619        
620        // Register user
621        let user_id = auth_manager.register_user(username, password, email).await.unwrap();
622        
623        // Login
624        let session = auth_manager.login(username, password).await.unwrap();
625        assert_eq!(session.user_id, user_id);
626        assert!(!session.token.is_empty());
627        assert!(session.expires_at > Utc::now());
628    }
629
630    #[tokio::test]
631    async fn test_invalid_login() {
632        let auth_manager = AuthenticationManager::new();
633        let username = "test_user";
634        let password = "SecurePassword123!";
635        let wrong_password = "WrongPassword123!";
636        
637        // Register user
638        auth_manager.register_user(username, password, "test@example.com").await.unwrap();
639        
640        // Try to login with wrong password
641        let result = auth_manager.login(username, wrong_password).await;
642        assert!(result.is_err());
643    }
644
645    #[tokio::test]
646    async fn test_session_validation() {
647        let auth_manager = AuthenticationManager::new();
648        let username = "test_user";
649        let password = "SecurePassword123!";
650        
651        // Register and login
652        auth_manager.register_user(username, password, "test@example.com").await.unwrap();
653        let session = auth_manager.login(username, password).await.unwrap();
654        
655        // Validate session
656        let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
657        assert!(is_valid);
658        
659        // Logout
660        auth_manager.logout(&session.token).await.unwrap();
661        
662        // Session should no longer be valid
663        let is_valid_after_logout = auth_manager.validate_session(&session.token).await.unwrap();
664        assert!(!is_valid_after_logout);
665    }
666
667    #[tokio::test]
668    async fn test_password_reset() {
669        let auth_manager = AuthenticationManager::new();
670        let username = "test_user";
671        let old_password = "OldPassword123!";
672        let new_password = "NewPassword123!";
673        
674        // Register user
675        auth_manager.register_user(username, old_password, "test@example.com").await.unwrap();
676        
677        // Initiate password reset
678        let reset_token = auth_manager.initiate_password_reset(username).await.unwrap();
679        assert!(!reset_token.is_empty());
680        
681        // Complete password reset
682        auth_manager.complete_password_reset(&reset_token, new_password).await.unwrap();
683        
684        // Verify old password no longer works
685        let old_login_result = auth_manager.login(username, old_password).await;
686        assert!(old_login_result.is_err());
687        
688        // Verify new password works
689        let new_login_result = auth_manager.login(username, new_password).await;
690        assert!(new_login_result.is_ok());
691    }
692
693    #[tokio::test]
694    async fn test_multi_factor_authentication() {
695        let auth_manager = AuthenticationManager::new();
696        let username = "test_user";
697        let password = "SecurePassword123!";
698        
699        // Register user with MFA enabled
700        let user_id = auth_manager.register_user(username, password, "test@example.com").await.unwrap();
701        auth_manager.enable_mfa(&user_id).await.unwrap();
702        
703        // Login should require MFA
704        let login_result = auth_manager.login(username, password).await;
705        assert!(login_result.is_err()); // Should fail without MFA code
706        
707        // Generate MFA code
708        let mfa_code = auth_manager.generate_mfa_code(&user_id).await.unwrap();
709        
710        // Login with MFA code
711        let session = auth_manager.login_with_mfa(username, password, &mfa_code).await.unwrap();
712        assert!(!session.token.is_empty());
713    }
714
715    #[tokio::test]
716    async fn test_password_validation() {
717        let auth_manager = AuthenticationManager::new();
718        
719        // Test weak password
720        let weak_password = "123";
721        let result = auth_manager.register_user("user1", weak_password, "test1@example.com").await;
722        assert!(result.is_err());
723        
724        // Test password without uppercase
725        let no_upper = "password123!";
726        let result = auth_manager.register_user("user2", no_upper, "test2@example.com").await;
727        assert!(result.is_err());
728        
729        // Test password without lowercase
730        let no_lower = "PASSWORD123!";
731        let result = auth_manager.register_user("user3", no_lower, "test3@example.com").await;
732        assert!(result.is_err());
733        
734        // Test password without numbers
735        let no_numbers = "Password!";
736        let result = auth_manager.register_user("user4", no_numbers, "test4@example.com").await;
737        assert!(result.is_err());
738        
739        // Test password without special characters
740        let no_special = "Password123";
741        let result = auth_manager.register_user("user5", no_special, "test5@example.com").await;
742        assert!(result.is_err());
743        
744        // Test valid password
745        let valid_password = "SecurePassword123!";
746        let result = auth_manager.register_user("user6", valid_password, "test6@example.com").await;
747        assert!(result.is_ok());
748    }
749
750    #[tokio::test]
751    async fn test_account_lockout() {
752        let auth_manager = AuthenticationManager::new();
753        let username = "test_user";
754        let password = "SecurePassword123!";
755        let wrong_password = "WrongPassword123!";
756        
757        // Register user
758        auth_manager.register_user(username, password, "test@example.com").await.unwrap();
759        
760        // Try wrong password multiple times
761        for _ in 0..5 {
762            let _ = auth_manager.login(username, wrong_password).await;
763        }
764        
765        // Account should be locked
766        let result = auth_manager.login(username, password).await;
767        assert!(result.is_err());
768        assert!(result.unwrap_err().to_string().contains("locked"));
769    }
770
771    #[tokio::test]
772    async fn test_duplicate_user_registration() {
773        let auth_manager = AuthenticationManager::new();
774        let username = "test_user";
775        let password = "SecurePassword123!";
776        let email = "test@example.com";
777        
778        // Register user first time
779        let result1 = auth_manager.register_user(username, password, email).await;
780        assert!(result1.is_ok());
781        
782        // Try to register same user again
783        let result2 = auth_manager.register_user(username, password, email).await;
784        assert!(result2.is_err());
785        assert!(result2.unwrap_err().to_string().contains("already exists"));
786    }
787
788    #[tokio::test]
789    async fn test_session_cleanup() {
790        let auth_manager = AuthenticationManager::new();
791        let username = "test_user";
792        let password = "SecurePassword123!";
793        
794        // Register and login
795        auth_manager.register_user(username, password, "test@example.com").await.unwrap();
796        let session = auth_manager.login(username, password).await.unwrap();
797        
798        // Verify session exists
799        let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
800        assert!(is_valid);
801        
802        // Clean up expired sessions (should not remove our session)
803        let cleaned = auth_manager.cleanup_expired_sessions().await;
804        assert_eq!(cleaned, 0);
805        
806        // Verify session still exists
807        let is_valid_after_cleanup = auth_manager.validate_session(&session.token).await.unwrap();
808        assert!(is_valid_after_cleanup);
809    }
810}