leptos_sync_core/security/authentication/
mod.rs

1//! Authentication system with comprehensive user management and security features
2
3pub mod config;
4pub mod crypto;
5pub mod manager;
6pub mod types;
7pub mod validation;
8
9// Re-export public types
10pub use config::AuthConfig;
11pub use manager::AuthenticationManager;
12pub use types::{AuthProvider, PasswordResetToken, User, UserSession};
13
14#[cfg(test)]
15mod tests {
16    use super::*;
17    use chrono::Utc;
18
19    #[tokio::test]
20    async fn test_user_registration() {
21        let auth_manager = AuthenticationManager::new();
22        let username = "test_user";
23        let password = "SecurePassword123!";
24        let email = "test@example.com";
25
26        let result = auth_manager.register_user(username, password, email).await;
27        assert!(result.is_ok());
28
29        let user_id = result.unwrap();
30        assert!(!user_id.is_empty());
31    }
32
33    #[tokio::test]
34    async fn test_user_login() {
35        let auth_manager = AuthenticationManager::new();
36        let username = "test_user";
37        let password = "SecurePassword123!";
38        let email = "test@example.com";
39
40        // Register user
41        let user_id = auth_manager
42            .register_user(username, password, email)
43            .await
44            .unwrap();
45
46        // Login
47        let session = auth_manager.login(username, password).await.unwrap();
48        assert_eq!(session.user_id, user_id);
49        assert!(!session.token.is_empty());
50        assert!(session.expires_at > Utc::now());
51    }
52
53    #[tokio::test]
54    async fn test_invalid_login() {
55        let auth_manager = AuthenticationManager::new();
56        let username = "test_user";
57        let password = "SecurePassword123!";
58        let wrong_password = "WrongPassword123!";
59
60        // Register user
61        auth_manager
62            .register_user(username, password, "test@example.com")
63            .await
64            .unwrap();
65
66        // Try to login with wrong password
67        let result = auth_manager.login(username, wrong_password).await;
68        assert!(result.is_err());
69    }
70
71    #[tokio::test]
72    async fn test_session_validation() {
73        let auth_manager = AuthenticationManager::new();
74        let username = "test_user";
75        let password = "SecurePassword123!";
76
77        // Register and login
78        auth_manager
79            .register_user(username, password, "test@example.com")
80            .await
81            .unwrap();
82        let session = auth_manager.login(username, password).await.unwrap();
83
84        // Validate session
85        let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
86        assert!(is_valid);
87
88        // Logout
89        auth_manager.logout(&session.token).await.unwrap();
90
91        // Session should no longer be valid
92        let is_valid_after_logout = auth_manager.validate_session(&session.token).await.unwrap();
93        assert!(!is_valid_after_logout);
94    }
95
96    #[tokio::test]
97    async fn test_password_reset() {
98        let auth_manager = AuthenticationManager::new();
99        let username = "test_user";
100        let old_password = "OldPassword123!";
101        let new_password = "NewPassword123!";
102
103        // Register user
104        auth_manager
105            .register_user(username, old_password, "test@example.com")
106            .await
107            .unwrap();
108
109        // Initiate password reset
110        let reset_token = auth_manager
111            .initiate_password_reset(username)
112            .await
113            .unwrap();
114        assert!(!reset_token.is_empty());
115
116        // Complete password reset
117        auth_manager
118            .complete_password_reset(&reset_token, new_password)
119            .await
120            .unwrap();
121
122        // Verify old password no longer works
123        let old_login_result = auth_manager.login(username, old_password).await;
124        assert!(old_login_result.is_err());
125
126        // Verify new password works
127        let new_login_result = auth_manager.login(username, new_password).await;
128        assert!(new_login_result.is_ok());
129    }
130
131    #[tokio::test]
132    async fn test_multi_factor_authentication() {
133        let auth_manager = AuthenticationManager::new();
134        let username = "test_user";
135        let password = "SecurePassword123!";
136
137        // Register user with MFA enabled
138        let user_id = auth_manager
139            .register_user(username, password, "test@example.com")
140            .await
141            .unwrap();
142        auth_manager.enable_mfa(&user_id).await.unwrap();
143
144        // Login should require MFA
145        let login_result = auth_manager.login(username, password).await;
146        assert!(login_result.is_err()); // Should fail without MFA code
147
148        // Generate MFA code
149        let mfa_code = auth_manager.generate_mfa_code(&user_id).await.unwrap();
150
151        // Login with MFA code
152        let session = auth_manager
153            .login_with_mfa(username, password, &mfa_code)
154            .await
155            .unwrap();
156        assert!(!session.token.is_empty());
157    }
158
159    #[tokio::test]
160    async fn test_password_validation() {
161        let auth_manager = AuthenticationManager::new();
162
163        // Test weak password
164        let weak_password = "123";
165        let result = auth_manager
166            .register_user("user1", weak_password, "test1@example.com")
167            .await;
168        assert!(result.is_err());
169
170        // Test password without uppercase
171        let no_upper = "password123!";
172        let result = auth_manager
173            .register_user("user2", no_upper, "test2@example.com")
174            .await;
175        assert!(result.is_err());
176
177        // Test password without lowercase
178        let no_lower = "PASSWORD123!";
179        let result = auth_manager
180            .register_user("user3", no_lower, "test3@example.com")
181            .await;
182        assert!(result.is_err());
183
184        // Test password without numbers
185        let no_numbers = "Password!";
186        let result = auth_manager
187            .register_user("user4", no_numbers, "test4@example.com")
188            .await;
189        assert!(result.is_err());
190
191        // Test password without special characters
192        let no_special = "Password123";
193        let result = auth_manager
194            .register_user("user5", no_special, "test5@example.com")
195            .await;
196        assert!(result.is_err());
197
198        // Test valid password
199        let valid_password = "SecurePassword123!";
200        let result = auth_manager
201            .register_user("user6", valid_password, "test6@example.com")
202            .await;
203        assert!(result.is_ok());
204    }
205
206    #[tokio::test]
207    async fn test_account_lockout() {
208        let auth_manager = AuthenticationManager::new();
209        let username = "test_user";
210        let password = "SecurePassword123!";
211        let wrong_password = "WrongPassword123!";
212
213        // Register user
214        auth_manager
215            .register_user(username, password, "test@example.com")
216            .await
217            .unwrap();
218
219        // Try wrong password multiple times
220        for _ in 0..5 {
221            let _ = auth_manager.login(username, wrong_password).await;
222        }
223
224        // Account should be locked
225        let result = auth_manager.login(username, password).await;
226        assert!(result.is_err());
227        assert!(result.unwrap_err().to_string().contains("locked"));
228    }
229
230    #[tokio::test]
231    async fn test_duplicate_user_registration() {
232        let auth_manager = AuthenticationManager::new();
233        let username = "test_user";
234        let password = "SecurePassword123!";
235        let email = "test@example.com";
236
237        // Register user first time
238        let result1 = auth_manager.register_user(username, password, email).await;
239        assert!(result1.is_ok());
240
241        // Try to register same user again
242        let result2 = auth_manager.register_user(username, password, email).await;
243        assert!(result2.is_err());
244        assert!(result2.unwrap_err().to_string().contains("already exists"));
245    }
246
247    #[tokio::test]
248    async fn test_session_cleanup() {
249        let auth_manager = AuthenticationManager::new();
250        let username = "test_user";
251        let password = "SecurePassword123!";
252
253        // Register and login
254        auth_manager
255            .register_user(username, password, "test@example.com")
256            .await
257            .unwrap();
258        let session = auth_manager.login(username, password).await.unwrap();
259
260        // Verify session exists
261        let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
262        assert!(is_valid);
263
264        // Clean up expired sessions (should not remove our session)
265        let cleaned = auth_manager.cleanup_expired_sessions().await;
266        assert_eq!(cleaned, 0);
267
268        // Verify session still exists
269        let is_valid_after_cleanup = auth_manager.validate_session(&session.token).await.unwrap();
270        assert!(is_valid_after_cleanup);
271    }
272}