1use crate::auth_operations::{
4 AuditLogQuery, DelegationRequest, PermissionContext, SessionCreateRequest, UserListQuery,
5};
6use crate::authentication::credentials::{Credential, CredentialMetadata};
7use crate::config::AuthConfig;
8use crate::distributed::DistributedSessionStore;
9use crate::errors::{AuthError, MfaError, Result};
10use crate::methods::{AuthMethod, AuthMethodEnum, MethodResult, MfaChallenge};
11use crate::permissions::PermissionChecker;
12use crate::storage::{AuthStorage, MemoryStorage, SessionData};
13use crate::tokens::{AuthToken, TokenManager};
14use crate::utils::rate_limit::RateLimiter;
15use std::collections::HashMap;
16use std::sync::Arc;
17use std::time::Duration;
18use tokio::sync::RwLock;
19use tracing::{debug, error, info, warn};
20
21#[derive(Debug, Clone)]
23pub enum AuthResult {
24 Success(Box<AuthToken>),
26
27 MfaRequired(Box<MfaChallenge>),
29
30 Failure(String),
32}
33
34#[derive(Debug, Clone)]
36pub struct UserInfo {
37 pub id: String,
39
40 pub username: String,
42
43 pub email: Option<String>,
45
46 pub name: Option<String>,
48
49 pub roles: crate::types::Roles,
51
52 pub active: bool,
54
55 pub email_verified: bool,
57
58 pub attributes: crate::types::UserAttributes,
60}
61
62#[inline]
71fn is_test_env() -> bool {
72 if std::env::var("ENVIRONMENT").as_deref() == Ok("production") {
74 return false;
75 }
76 cfg!(test)
77 || std::env::var("RUST_TEST").is_ok()
78 || std::env::var("ENVIRONMENT").as_deref() == Ok("test")
79}
80
81pub struct AuthFramework {
141 config: AuthConfig,
143
144 methods: HashMap<String, AuthMethodEnum>,
146
147 token_manager: TokenManager,
149
150 storage: Arc<dyn AuthStorage>,
152
153 authorization_manager: crate::auth_modular::authorization_manager::AuthorizationManager,
155
156 rate_limiter: Option<RateLimiter>,
158
159 monitoring_manager: Arc<crate::monitoring::MonitoringManager>,
161
162 audit_manager: Arc<crate::audit::AuditLogger<Arc<crate::storage::MemoryStorage>>>,
164
165 #[cfg(feature = "api-server")]
167 security_manager: Arc<crate::api::SecurityManager>,
168
169 pub(crate) runtime_config: Arc<tokio::sync::RwLock<crate::config::RuntimeConfig>>,
171
172 user_manager: crate::auth_modular::user_manager::UserManager,
174
175 session_manager: crate::auth_modular::session_manager::SessionManager,
177
178 mfa_manager: crate::auth_modular::mfa::MfaManager,
180
181 initialized: bool,
183
184 storage_overridden: bool,
186}
187
188pub use crate::auth_operations::{
189 AdminOperations, AuditOperations, AuthorizationOperations, MaintenanceOperations,
190 MfaOperations, MonitoringOperations, SessionOperations, TokenOperations, UserOperations,
191};
192
193fn resolve_jwt_secret_bytes(config: &AuthConfig) -> Result<Vec<u8>> {
199 if let Some(secret) = &config.security.secret_key {
200 if secret.len() < 32 && !is_test_env() {
201 return Err(AuthError::configuration(
202 "JWT secret must be at least 32 characters for production security",
203 ));
204 }
205 return Ok(secret.as_bytes().to_vec());
206 }
207 if let Some(secret) = &config.secret {
208 if secret.len() < 32 && !is_test_env() {
209 return Err(AuthError::configuration(
210 "JWT secret must be at least 32 characters for production security",
211 ));
212 }
213 return Ok(secret.as_bytes().to_vec());
214 }
215 if let Ok(jwt_secret) = std::env::var("JWT_SECRET") {
216 if jwt_secret.len() < 32 && !is_test_env() {
217 return Err(AuthError::configuration(
218 "JWT_SECRET must be at least 32 characters for production security",
219 ));
220 }
221 return Ok(jwt_secret.as_bytes().to_vec());
222 }
223 Err(AuthError::configuration(
224 "JWT secret not configured! Please set JWT_SECRET environment variable or provide in configuration.\n\
225 For security reasons, no default secret is provided.\n\
226 Generate a secure secret with: openssl rand -base64 32",
227 ))
228}
229
230impl AuthFramework {
231 pub fn users(&self) -> UserOperations<'_> {
233 UserOperations { framework: self }
234 }
235
236 pub fn sessions(&self) -> SessionOperations<'_> {
238 SessionOperations { framework: self }
239 }
240
241 pub fn tokens(&self) -> TokenOperations<'_> {
243 TokenOperations { framework: self }
244 }
245
246 pub fn authorization(&self) -> AuthorizationOperations<'_> {
248 AuthorizationOperations { framework: self }
249 }
250
251 pub fn mfa(&self) -> MfaOperations<'_> {
253 MfaOperations { framework: self }
254 }
255
256 pub fn monitoring(&self) -> MonitoringOperations<'_> {
258 MonitoringOperations { framework: self }
259 }
260
261 pub fn audit(&self) -> AuditOperations<'_> {
263 AuditOperations { framework: self }
264 }
265
266 pub fn maintenance(&self) -> MaintenanceOperations<'_> {
268 MaintenanceOperations { framework: self }
269 }
270
271 pub async fn runtime_config(&self) -> crate::config::RuntimeConfig {
273 self.runtime_config.read().await.clone()
274 }
275
276 #[deprecated(since = "0.6.0", note = "Use `runtime_config()` instead")]
277 #[doc(hidden)]
278 pub async fn get_runtime_config(&self) -> crate::config::RuntimeConfig {
279 self.runtime_config().await
280 }
281
282 pub async fn update_runtime_config(
287 &self,
288 update: crate::config::RuntimeConfig,
289 ) -> Result<crate::config::RuntimeConfig> {
290 if update.token_lifetime_secs == 0 {
292 return Err(AuthError::config("token_lifetime_secs must be > 0"));
293 }
294 if update.refresh_token_lifetime_secs == 0 {
295 return Err(AuthError::config("refresh_token_lifetime_secs must be > 0"));
296 }
297 if update.refresh_token_lifetime_secs <= update.token_lifetime_secs {
298 return Err(AuthError::config(
299 "refresh_token_lifetime_secs must be greater than token_lifetime_secs",
300 ));
301 }
302 if update.min_password_length == 0 {
303 return Err(AuthError::config("min_password_length must be > 0"));
304 }
305 let mut cfg = self.runtime_config.write().await;
306 *cfg = update.clone();
307 Ok(update)
308 }
309
310 pub fn admin(&self) -> AdminOperations<'_> {
312 AdminOperations { framework: self }
313 }
314
315 pub fn new(config: AuthConfig) -> Self {
323 let storage = Arc::new(MemoryStorage::new()) as Arc<dyn AuthStorage>;
325 let audit_storage = Arc::new(crate::storage::MemoryStorage::new());
326 let audit_manager = Arc::new(crate::audit::AuditLogger::new(audit_storage));
327
328 let ephemeral_secret = {
334 let rng = ring::rand::SystemRandom::new();
335 let mut buf = [0u8; 32];
336 ring::rand::SecureRandom::fill(&rng, &mut buf)
337 .expect("AuthFramework fatal: system CSPRNG unavailable — the operating system cannot provide cryptographic randomness");
338 buf
339 };
340 let token_manager =
341 TokenManager::new_hmac(&ephemeral_secret, "auth-framework", "auth-framework");
342
343 let user_manager = crate::auth_modular::user_manager::UserManager::new(storage.clone());
344 let session_manager =
345 crate::auth_modular::session_manager::SessionManager::new(storage.clone());
346 let mfa_manager = crate::auth_modular::mfa::MfaManager::new(storage.clone());
347 let authorization_manager =
348 crate::auth_modular::authorization_manager::AuthorizationManager::new(
349 Arc::new(RwLock::new(PermissionChecker::new())),
350 storage.clone(),
351 );
352
353 Self {
354 config,
355 methods: HashMap::new(),
356 token_manager,
357 storage,
358 authorization_manager,
359 rate_limiter: None, monitoring_manager: Arc::new(crate::monitoring::MonitoringManager::new(
361 crate::monitoring::MonitoringConfig::default(),
362 )),
363 audit_manager,
364 #[cfg(feature = "api-server")]
365 security_manager: Arc::new(crate::api::SecurityManager::new()),
366 runtime_config: Arc::new(tokio::sync::RwLock::new(
367 crate::config::RuntimeConfig::default(),
368 )),
369 user_manager,
370 session_manager,
371 mfa_manager,
372 initialized: false,
373 storage_overridden: false,
374 }
375 }
376
377 pub fn new_validated(config: AuthConfig) -> Result<Self> {
382 config.validate().map_err(|e| {
384 AuthError::configuration(format!("Configuration validation failed: {}", e))
385 })?;
386
387 let current_secret_bytes = resolve_jwt_secret_bytes(&config)?;
389
390 let mut token_manager =
391 TokenManager::new_hmac(¤t_secret_bytes, "auth-framework", "auth-framework");
392
393 if let Some(prev_secret) = &config.security.previous_secret_key {
395 token_manager =
397 TokenManager::new_hmac(prev_secret.as_bytes(), "auth-framework", "auth-framework");
398 token_manager.rotate_hmac_key(¤t_secret_bytes);
399 }
400
401 let storage: Arc<dyn AuthStorage> = match &config.storage {
403 #[cfg(feature = "redis-storage")]
404 crate::config::StorageConfig::Redis { url, key_prefix } => Arc::new(
405 crate::storage::RedisStorage::new(url, key_prefix).map_err(|e| {
406 AuthError::configuration(format!("Failed to create Redis storage: {}", e))
407 })?,
408 ),
409 _ => Arc::new(MemoryStorage::new()) as Arc<dyn AuthStorage>,
410 };
411
412 let rate_limiter = if config.rate_limiting.enabled {
414 Some(RateLimiter::new(
415 config.rate_limiting.max_requests,
416 config.rate_limiting.window,
417 ))
418 } else {
419 None
420 };
421
422 let audit_storage = Arc::new(crate::storage::MemoryStorage::new());
424 let audit_manager = Arc::new(crate::audit::AuditLogger::new(audit_storage));
425
426 let user_manager = crate::auth_modular::user_manager::UserManager::new(storage.clone());
427 let session_manager =
428 crate::auth_modular::session_manager::SessionManager::new(storage.clone());
429 let mfa_manager = crate::auth_modular::mfa::MfaManager::new(storage.clone());
430 let authorization_manager =
431 crate::auth_modular::authorization_manager::AuthorizationManager::new(
432 Arc::new(RwLock::new(PermissionChecker::new())),
433 storage.clone(),
434 );
435
436 Ok(Self {
437 config: config.clone(),
438 methods: HashMap::new(),
439 token_manager,
440 storage,
441 authorization_manager,
442 rate_limiter,
443 monitoring_manager: Arc::new(crate::monitoring::MonitoringManager::new(
444 crate::monitoring::MonitoringConfig::default(),
445 )),
446 audit_manager,
447 #[cfg(feature = "api-server")]
448 security_manager: Arc::new(crate::api::SecurityManager::new()),
449 runtime_config: Arc::new(tokio::sync::RwLock::new(
450 crate::config::RuntimeConfig::from_auth_config(&config),
451 )),
452 user_manager,
453 session_manager,
454 mfa_manager,
455 initialized: false,
456 storage_overridden: false,
457 })
458 }
459
460 pub fn replace_storage(&mut self, storage: std::sync::Arc<dyn AuthStorage>) {
467 self.storage = storage.clone();
468 self.user_manager = crate::auth_modular::user_manager::UserManager::new(storage.clone());
469 self.session_manager =
470 crate::auth_modular::session_manager::SessionManager::new(storage.clone());
471 self.mfa_manager = crate::auth_modular::mfa::MfaManager::new(storage.clone());
472 self.authorization_manager =
473 crate::auth_modular::authorization_manager::AuthorizationManager::new(
474 Arc::new(RwLock::new(PermissionChecker::new())),
475 storage,
476 );
477 self.storage_overridden = true;
478 }
479
480 pub fn set_distributed_store(&mut self, store: Arc<dyn DistributedSessionStore>) {
487 self.session_manager.set_distributed_store(store);
488 }
489
490 pub fn new_with_storage(config: AuthConfig, storage: std::sync::Arc<dyn AuthStorage>) -> Self {
492 let mut framework = Self::new(config);
493 framework.replace_storage(storage);
494 framework
495 }
496
497 pub fn register_method(&mut self, name: impl Into<String>, method: AuthMethodEnum) {
499 let name = name.into();
500 info!("Registering authentication method: {}", name);
501
502 if let Err(e) = method.validate_config() {
504 error!("Method '{}' configuration validation failed: {}", name, e);
505 return;
506 }
507
508 self.methods.insert(name, method);
509 }
510
511 fn require_initialized(&self) -> Result<()> {
517 if self.initialized {
518 Ok(())
519 } else {
520 Err(AuthError::configuration(
521 "Framework not initialized. Call `initialize().await` first, \
522 or use `AuthFramework::builder().build().await` which initializes automatically.",
523 ))
524 }
525 }
526
527 pub async fn initialize(&mut self) -> Result<()> {
537 if self.initialized {
538 return Ok(());
539 }
540
541 info!("Initializing authentication framework");
542
543 self.config.validate().map_err(|e| {
545 AuthError::configuration(format!("Configuration validation failed: {}", e))
546 })?;
547
548 let token_manager = match resolve_jwt_secret_bytes(&self.config) {
550 Ok(bytes) => TokenManager::new_hmac(&bytes, "auth-framework", "auth-framework"),
551 Err(_) => {
552 if Self::is_production_environment() {
553 return Err(AuthError::configuration(
554 "Production deployment requires JWT_SECRET environment variable or configuration!\n\
555 Generate a secure secret with: openssl rand -base64 32\n\
556 Set it with: export JWT_SECRET=\"your-secret-here\"",
557 ));
558 }
559 warn!("No JWT secret configured, using development-only default");
560 warn!("CRITICAL: Set JWT_SECRET environment variable for production!");
561 warn!("This configuration is NOT SECURE and should only be used in development!");
562 self.token_manager.clone()
563 }
564 };
565
566 self.token_manager = token_manager;
568
569 if !self.storage_overridden {
571 let storage =
572 crate::storage::factory::build_storage_backend(&self.config.storage, None).await?;
573 self.replace_storage(storage);
574 self.storage_overridden = false;
575 }
576
577 if self.config.rate_limiting.enabled {
579 self.rate_limiter = Some(RateLimiter::new(
580 self.config.rate_limiting.max_requests,
581 self.config.rate_limiting.window,
582 ));
583 }
584
585 self.authorization_manager.create_default_roles().await;
587
588 self.authorization_manager.load_persisted_roles().await?;
590
591 self.cleanup_expired_data().await?;
593
594 self.initialized = true;
595 info!("Authentication framework initialized successfully");
596
597 Ok(())
598 }
599
600 pub async fn authenticate(
628 &self,
629 method_name: &str,
630 credential: Credential,
631 ) -> Result<AuthResult> {
632 self.authenticate_with_metadata(method_name, credential, CredentialMetadata::new())
633 .await
634 }
635
636 pub async fn authenticate_with_metadata(
638 &self,
639 method_name: &str,
640 credential: Credential,
641 metadata: CredentialMetadata,
642 ) -> Result<AuthResult> {
643 use std::time::Instant;
644 use tokio::time::{Duration as TokioDuration, sleep};
645
646 let start_time = Instant::now();
647
648 self.monitoring_manager.record_auth_request().await;
650
651 self.require_initialized()?;
652
653 let result = self
655 .authenticate_internal(method_name, credential, metadata)
656 .await;
657
658 let min_duration = TokioDuration::from_millis(100); let elapsed = start_time.elapsed();
661 if elapsed < min_duration {
662 sleep(min_duration - elapsed).await;
663 }
664
665 if let Ok(ref auth_result) = result {
667 match auth_result {
668 AuthResult::Success(token) => {
669 self.monitoring_manager
670 .record_auth_success(&token.user_id, elapsed)
671 .await;
672 }
673 AuthResult::Failure(reason) => {
674 self.monitoring_manager
675 .record_auth_failure(None, reason)
676 .await;
677 }
678 _ => {} }
680 }
681
682 result
683 }
684
685 async fn authenticate_internal(
687 &self,
688 method_name: &str,
689 credential: Credential,
690 metadata: CredentialMetadata,
691 ) -> Result<AuthResult> {
692 if let Some(ref rate_limiter) = self.rate_limiter {
694 let rate_key = format!(
695 "auth:{}:{}",
696 method_name,
697 metadata.client_ip.as_deref().unwrap_or("unknown")
698 );
699
700 if !rate_limiter.is_allowed(&rate_key) {
701 warn!(
702 "Rate limit exceeded for method '{}' from IP {:?}",
703 method_name, metadata.client_ip
704 );
705 return Err(AuthError::rate_limit("Too many authentication attempts"));
706 }
707 }
708
709 if method_name == "password"
713 && let Credential::Password {
714 ref username,
715 ref password,
716 } = credential
717 {
718 return self
719 .authenticate_password_builtin(username, password, &metadata)
720 .await;
721 }
722
723 if method_name == "jwt" {
724 return match credential {
725 Credential::Jwt { token } | Credential::Bearer { token } => {
726 self.authenticate_jwt_builtin(&token, &metadata, "jwt")
727 .await
728 }
729 _ => Ok(AuthResult::Failure(
730 "JWT authentication expects Credential::jwt or Credential::bearer".to_string(),
731 )),
732 };
733 }
734
735 if matches!(method_name, "api_key" | "api-key") {
736 return match credential {
737 Credential::ApiKey { key } => {
738 self.authenticate_api_key_builtin(&key, &metadata, "api_key")
739 .await
740 }
741 _ => Ok(AuthResult::Failure(
742 "API key authentication expects Credential::api_key".to_string(),
743 )),
744 };
745 }
746
747 if method_name == "oauth2" {
748 return self
749 .authenticate_oauth2_builtin(credential, &metadata)
750 .await;
751 }
752
753 let method = self.methods.get(method_name).ok_or_else(|| {
755 AuthError::auth_method(method_name, "Authentication method not found".to_string())
756 })?;
757
758 debug!(
760 "Authentication attempt with method '{}' for credential: {}",
761 method_name,
762 credential.safe_display()
763 );
764
765 let result = method.authenticate(credential, metadata.clone()).await?;
767
768 match &result {
770 MethodResult::Success(token) => {
771 info!(
772 "Authentication successful for user '{}' with method '{}'",
773 token.user_id, method_name
774 );
775
776 self.storage.store_token(token).await?;
778
779 self.log_audit_event("auth_success", &token.user_id, method_name, &metadata)
781 .await;
782
783 Ok(AuthResult::Success(token.clone()))
784 }
785
786 MethodResult::MfaRequired(challenge) => {
787 info!(
788 "MFA required for user '{}' with method '{}'",
789 challenge.user_id, method_name
790 );
791
792 self.guard_and_store_mfa_challenge((**challenge).clone())
794 .await?;
795
796 self.log_audit_event("mfa_required", &challenge.user_id, method_name, &metadata)
798 .await;
799
800 Ok(AuthResult::MfaRequired(challenge.clone()))
801 }
802
803 MethodResult::Failure { reason } => {
804 warn!(
805 "Authentication failed for method '{}': {}",
806 method_name, reason
807 );
808
809 self.log_audit_event("auth_failure", "unknown", method_name, &metadata)
811 .await;
812
813 Ok(AuthResult::Failure(reason.clone()))
814 }
815 }
816 }
817
818 async fn authenticate_jwt_builtin(
819 &self,
820 token: &str,
821 metadata: &CredentialMetadata,
822 auth_method: &str,
823 ) -> Result<AuthResult> {
824 if token.is_empty() {
825 return Ok(AuthResult::Failure("JWT token cannot be empty".to_string()));
826 }
827
828 match self.token_manager.validate_jwt_token(token) {
829 Ok(claims) => {
830 let token =
831 Self::build_validated_jwt_auth_token(token, claims, metadata, auth_method);
832 Ok(AuthResult::Success(Box::new(token)))
833 }
834 Err(error) => {
835 if let Some(reason) = Self::credential_failure_reason(&error) {
836 Ok(AuthResult::Failure(reason))
837 } else {
838 Err(error)
839 }
840 }
841 }
842 }
843
844 async fn authenticate_api_key_builtin(
845 &self,
846 api_key: &str,
847 metadata: &CredentialMetadata,
848 auth_method: &str,
849 ) -> Result<AuthResult> {
850 if api_key.is_empty() {
851 return Ok(AuthResult::Failure("API key cannot be empty".to_string()));
852 }
853
854 match self.validate_api_key(api_key).await {
855 Ok(user) => {
856 let scopes: Vec<String> = if user.roles.is_empty() {
857 vec!["api_user".to_string()]
858 } else {
859 user.roles.to_vec()
860 };
861 let mut token = self
862 .token_manager
863 .create_auth_token(&user.id, scopes.clone(), auth_method, None)?
864 .with_roles(user.roles)
865 .with_scopes(scopes);
866 token.metadata.issued_ip = metadata.client_ip.clone();
867 token.metadata.user_agent = metadata.user_agent.clone();
868 Ok(AuthResult::Success(Box::new(token)))
869 }
870 Err(error) => {
871 if let Some(reason) = Self::credential_failure_reason(&error) {
872 Ok(AuthResult::Failure(reason))
873 } else {
874 Err(error)
875 }
876 }
877 }
878 }
879
880 async fn authenticate_oauth2_builtin(
881 &self,
882 credential: Credential,
883 metadata: &CredentialMetadata,
884 ) -> Result<AuthResult> {
885 match credential {
886 Credential::OAuth {
887 authorization_code, ..
888 } => {
889 if authorization_code.is_empty() {
890 return Ok(AuthResult::Failure(
891 "OAuth authorization code cannot be empty".to_string(),
892 ));
893 }
894 Ok(AuthResult::Failure(
895 "OAuth 2.0 authorization codes must be exchanged through an OAuth provider or server endpoint before authentication completes"
896 .to_string(),
897 ))
898 }
899 Credential::OAuthRefresh { refresh_token } => {
900 if refresh_token.is_empty() {
901 return Ok(AuthResult::Failure(
902 "OAuth refresh token cannot be empty".to_string(),
903 ));
904 }
905 Ok(AuthResult::Failure(
906 "OAuth 2.0 refresh tokens must be exchanged through an OAuth provider or server endpoint before authentication completes"
907 .to_string(),
908 ))
909 }
910 Credential::Jwt { token }
911 | Credential::Bearer { token }
912 | Credential::OpenIdConnect { id_token: token, .. } => {
913 self.authenticate_jwt_builtin(&token, metadata, "oauth2").await
914 }
915 _ => Ok(AuthResult::Failure(
916 "OAuth2 authentication expects Credential::oauth_code, Credential::oauth_refresh, Credential::jwt, Credential::bearer, or Credential::openid_connect"
917 .to_string(),
918 )),
919 }
920 }
921
922 fn build_validated_jwt_auth_token(
923 raw_token: &str,
924 claims: crate::tokens::JwtClaims,
925 metadata: &CredentialMetadata,
926 auth_method: &str,
927 ) -> AuthToken {
928 let crate::tokens::JwtClaims {
929 sub,
930 iss,
931 exp,
932 iat,
933 jti,
934 scope,
935 permissions,
936 roles,
937 client_id,
938 ..
939 } = claims;
940
941 let now = chrono::Utc::now();
942 let issued_at = chrono::DateTime::<chrono::Utc>::from_timestamp(iat, 0).unwrap_or(now);
943 let expires_at = chrono::DateTime::<chrono::Utc>::from_timestamp(exp, 0)
944 .unwrap_or(now + chrono::Duration::hours(1));
945 let lifetime = (expires_at - now)
946 .to_std()
947 .unwrap_or_else(|_| Duration::from_secs(1));
948 let scopes = if scope.trim().is_empty() {
949 Vec::new()
950 } else {
951 scope.split_whitespace().map(str::to_string).collect()
952 };
953
954 let mut token = AuthToken::new(sub.clone(), raw_token.to_string(), lifetime, auth_method)
955 .with_scopes(scopes)
956 .with_permissions(permissions.unwrap_or_default())
957 .with_roles(roles.unwrap_or_default());
958 token.token_id = jti;
959 token.subject = Some(sub);
960 token.issuer = Some(iss);
961 token.issued_at = issued_at;
962 token.expires_at = expires_at;
963 token.metadata.issued_ip = metadata.client_ip.clone();
964 token.metadata.user_agent = metadata.user_agent.clone();
965 if let Some(client_id) = client_id {
966 token.client_id = Some(client_id);
967 }
968 token
969 }
970
971 fn credential_failure_reason(error: &AuthError) -> Option<String> {
972 match error {
973 AuthError::Token(_) | AuthError::Jwt(_) => Some(error.to_string()),
974 AuthError::Validation { message } => Some(message.clone()),
975 AuthError::UserNotFound => Some("User not found".to_string()),
976 _ => None,
977 }
978 }
979
980 async fn authenticate_password_builtin(
982 &self,
983 username: &str,
984 password: &str,
985 metadata: &CredentialMetadata,
986 ) -> Result<AuthResult> {
987 use crate::auth_modular::user_manager::CredentialCheckResult;
988
989 if username.is_empty() || password.is_empty() {
990 return Ok(AuthResult::Failure(
991 "Username or password cannot be empty".to_string(),
992 ));
993 }
994
995 match self
996 .user_manager
997 .verify_login_credentials(username, password)
998 .await?
999 {
1000 None => {
1001 self.log_audit_event("auth_failure", "unknown", "password", metadata)
1002 .await;
1003 Ok(AuthResult::Failure(
1004 "Invalid username or password".to_string(),
1005 ))
1006 }
1007 Some(CredentialCheckResult {
1008 ref user_id,
1009 mfa_enabled: true,
1010 }) => {
1011 let now = chrono::Utc::now();
1012 let challenge = MfaChallenge {
1013 id: crate::utils::string::generate_id(Some("mfa")),
1014 mfa_type: crate::methods::MfaType::MultiMethod,
1015 user_id: user_id.clone(),
1016 created_at: now,
1017 expires_at: now + chrono::Duration::minutes(5),
1018 attempts: 0,
1019 max_attempts: 5,
1020 code_hash: None,
1021 message: Some(
1022 "Provide your current TOTP code or a backup code to complete login"
1023 .to_string(),
1024 ),
1025 data: HashMap::new(),
1026 };
1027 self.guard_and_store_mfa_challenge(challenge.clone())
1028 .await?;
1029 self.log_audit_event("mfa_required", user_id, "password", metadata)
1030 .await;
1031 info!(
1032 "Built-in password authentication requires MFA for user: {}",
1033 username
1034 );
1035 Ok(AuthResult::MfaRequired(Box::new(challenge)))
1036 }
1037 Some(CredentialCheckResult {
1038 ref user_id,
1039 mfa_enabled: false,
1040 }) => {
1041 let token = self
1042 .mint_and_store_token(
1043 user_id,
1044 vec!["read".to_string(), "write".to_string()],
1045 "password",
1046 None,
1047 )
1048 .await?;
1049 self.monitoring_manager.record_auth_request().await;
1050 self.log_audit_event("auth_success", user_id, "password", metadata)
1051 .await;
1052 info!(
1053 "Built-in password authentication successful for user: {}",
1054 username
1055 );
1056 Ok(AuthResult::Success(Box::new(token)))
1057 }
1058 }
1059 }
1060
1061 pub async fn complete_mfa(&self, challenge: MfaChallenge, mfa_code: &str) -> Result<AuthToken> {
1063 debug!("Completing MFA for challenge '{}'", challenge.id);
1064
1065 let stored_challenge = self
1066 .mfa_manager
1067 .get_challenge(&challenge.id)
1068 .await?
1069 .ok_or(MfaError::ChallengeExpired)?;
1070
1071 if stored_challenge.is_expired() {
1072 self.mfa_manager.remove_challenge(&challenge.id).await?;
1073 return Err(MfaError::ChallengeExpired.into());
1074 }
1075
1076 if !self.verify_mfa_code(&stored_challenge, mfa_code).await? {
1077 return Err(MfaError::InvalidCode.into());
1078 }
1079
1080 self.mfa_manager.remove_challenge(&challenge.id).await?;
1081
1082 let scopes = self
1083 .user_manager
1084 .get_user_roles(&challenge.user_id)
1085 .await
1086 .unwrap_or_else(|_| vec!["user".to_string()]);
1087
1088 let token = self
1089 .mint_and_store_token(&challenge.user_id, scopes, "mfa", None)
1090 .await?;
1091
1092 info!(
1093 "MFA completed successfully for user '{}'",
1094 challenge.user_id
1095 );
1096 Ok(token)
1097 }
1098
1099 pub async fn complete_mfa_by_id(
1101 &self,
1102 challenge_id: &str,
1103 mfa_code: &str,
1104 ) -> Result<AuthToken> {
1105 let challenge = self
1106 .mfa_manager
1107 .get_challenge(challenge_id)
1108 .await?
1109 .ok_or(MfaError::ChallengeExpired)?;
1110
1111 self.complete_mfa(challenge, mfa_code).await
1112 }
1113
1114 pub async fn validate_token(&self, token: &AuthToken) -> Result<bool> {
1116 self.require_initialized()?;
1117 let valid = token.is_valid()
1118 && self.token_manager.validate_auth_token(token).is_ok()
1119 && self.touch_stored_token(token).await?;
1120 self.monitoring_manager.record_token_validation(valid).await;
1121 Ok(valid)
1122 }
1123
1124 async fn touch_stored_token(&self, token: &AuthToken) -> Result<bool> {
1125 let Some(mut stored) = self.storage.get_token(&token.token_id).await? else {
1126 return Ok(false);
1127 };
1128 stored.mark_used();
1129 self.storage.update_token(&stored).await?;
1130 Ok(true)
1131 }
1132
1133 pub async fn get_user_info(&self, token: &AuthToken) -> Result<UserInfo> {
1135 if !self.validate_token(token).await? {
1136 return Err(AuthError::auth_method("token", "Invalid token".to_string()));
1137 }
1138
1139 let token_info = self.token_manager.extract_token_info(&token.access_token)?;
1140
1141 match self.user_manager.get_user_info(&token_info.user_id).await {
1144 Ok(mut info) => {
1145 if !token_info.attributes.is_empty() {
1147 let string_attrs: HashMap<String, String> = token_info
1148 .attributes
1149 .into_iter()
1150 .map(|(k, v)| {
1151 (
1152 k,
1153 v.as_str()
1154 .map(|s| s.to_string())
1155 .unwrap_or_else(|| v.to_string()),
1156 )
1157 })
1158 .collect();
1159 info.attributes = string_attrs.into();
1160 }
1161 Ok(info)
1162 }
1163 Err(_) => {
1164 let string_attrs: HashMap<String, String> = token_info
1165 .attributes
1166 .into_iter()
1167 .map(|(k, v)| {
1168 (
1169 k,
1170 v.as_str()
1171 .map(|s| s.to_string())
1172 .unwrap_or_else(|| v.to_string()),
1173 )
1174 })
1175 .collect();
1176 Ok(UserInfo {
1177 id: token_info.user_id,
1178 username: token_info.username.unwrap_or_else(|| "unknown".to_string()),
1179 email: token_info.email,
1180 name: token_info.name,
1181 roles: token_info.roles.into(),
1182 active: false,
1183 email_verified: false,
1184 attributes: string_attrs.into(),
1185 })
1186 }
1187 }
1188 }
1189
1190 pub async fn check_permission(
1217 &self,
1218 token: &AuthToken,
1219 action: &str,
1220 resource: &str,
1221 ) -> Result<bool> {
1222 if !self.validate_token(token).await? {
1223 return Ok(false);
1224 }
1225 self.authorization_manager
1226 .check_token_permission(token, action, resource)
1227 .await
1228 }
1229
1230 pub async fn refresh_token(&self, token: &AuthToken) -> Result<AuthToken> {
1232 self.require_initialized()?;
1233 debug!("Refreshing token for user '{}'", token.user_id);
1234
1235 if let Some(method) = self.methods.get(&token.auth_method)
1237 && method.supports_refresh()
1238 && let Some(ref refresh_token) = token.refresh_token
1239 {
1240 let new_token = method.refresh_token(refresh_token.to_string()).await?;
1241 self.storage.store_token(&new_token).await?;
1242 return Ok(new_token);
1243 }
1244
1245 let new_token = self.token_manager.refresh_token(token)?;
1247 self.storage.store_token(&new_token).await?;
1248
1249 info!("Token refreshed for user '{}'", token.user_id);
1250
1251 Ok(new_token)
1252 }
1253
1254 pub async fn revoke_token(&self, token: &AuthToken) -> Result<()> {
1256 self.require_initialized()?;
1257 debug!("Revoking token for user '{}'", token.user_id);
1258
1259 let mut revoked_token = token.clone();
1261 revoked_token.revoke(Some("Manual revocation".to_string()));
1262
1263 self.storage.update_token(&revoked_token).await?;
1265
1266 info!("Token revoked for user '{}'", token.user_id);
1267
1268 Ok(())
1269 }
1270
1271 pub async fn create_api_key(
1273 &self,
1274 user_id: &str,
1275 expires_in: Option<Duration>,
1276 ) -> Result<String> {
1277 self.require_initialized()?;
1278 self.user_manager.create_api_key(user_id, expires_in).await
1279 }
1280
1281 pub async fn validate_api_key(&self, api_key: &str) -> Result<UserInfo> {
1283 self.require_initialized()?;
1284 self.user_manager.validate_api_key(api_key).await
1285 }
1286
1287 pub async fn revoke_api_key(&self, api_key: &str) -> Result<()> {
1289 self.require_initialized()?;
1290 self.user_manager.revoke_api_key(api_key).await
1291 }
1292
1293 pub async fn create_session(
1295 &self,
1296 user_id: &str,
1297 expires_in: Duration,
1298 ip_address: Option<String>,
1299 user_agent: Option<String>,
1300 ) -> Result<String> {
1301 self.require_initialized()?;
1302 let (session_id, new_total) = self
1303 .session_manager
1304 .create_session_limited(user_id, expires_in, ip_address, user_agent)
1305 .await?;
1306 self.monitoring_manager
1307 .update_session_count(new_total)
1308 .await;
1309 Ok(session_id)
1310 }
1311
1312 pub async fn create_session_with_request(&self, req: SessionCreateRequest) -> Result<String> {
1332 self.create_session(
1333 req.get_user_id(),
1334 req.get_expires_in(),
1335 req.get_ip_address().map(|s| s.to_string()),
1336 req.get_user_agent().map(|s| s.to_string()),
1337 )
1338 .await
1339 }
1340
1341 pub async fn get_session(&self, session_id: &str) -> Result<Option<SessionData>> {
1343 self.require_initialized()?;
1344 self.session_manager.get_session(session_id).await
1345 }
1346
1347 pub async fn delete_session(&self, session_id: &str) -> Result<()> {
1349 self.require_initialized()?;
1350 self.session_manager.delete_session(session_id).await?;
1351
1352 let remaining = self
1353 .session_manager
1354 .count_active_sessions()
1355 .await
1356 .unwrap_or(0);
1357 self.monitoring_manager
1358 .update_session_count(remaining)
1359 .await;
1360
1361 Ok(())
1362 }
1363
1364 pub async fn list_user_tokens(&self, user_id: &str) -> Result<Vec<AuthToken>> {
1366 self.require_initialized()?;
1367 self.storage.list_user_tokens(user_id).await
1368 }
1369
1370 pub async fn cleanup_expired_data(&self) -> Result<()> {
1372 debug!("Cleaning up expired data");
1373
1374 self.storage.cleanup_expired().await?;
1376
1377 self.mfa_manager.cleanup_expired_challenges().await?;
1379
1380 self.session_manager.cleanup_expired_sessions().await?;
1382
1383 if let Some(ref rate_limiter) = self.rate_limiter {
1385 let _ = rate_limiter.cleanup().ok();
1386 }
1387
1388 Ok(())
1389 }
1390
1391 fn is_production_environment() -> bool {
1394 if let Ok(env) = std::env::var("ENVIRONMENT")
1395 && (env.to_lowercase() == "production" || env.to_lowercase() == "prod")
1396 {
1397 return true;
1398 }
1399 if let Ok(env) = std::env::var("ENV")
1400 && (env.to_lowercase() == "production" || env.to_lowercase() == "prod")
1401 {
1402 return true;
1403 }
1404 if let Ok(env) = std::env::var("NODE_ENV")
1405 && env.to_lowercase() == "production"
1406 {
1407 return true;
1408 }
1409 if let Ok(env) = std::env::var("RUST_ENV")
1410 && env.to_lowercase() == "production"
1411 {
1412 return true;
1413 }
1414 std::env::var("KUBERNETES_SERVICE_HOST").is_ok()
1415 || std::env::var("DOCKER_CONTAINER").is_ok()
1416 }
1417
1418 pub async fn get_stats(&self) -> Result<AuthStats> {
1420 let mut stats = AuthStats::default();
1421
1422 if let Err(e) = self.storage.cleanup_expired().await {
1423 warn!("Failed to cleanup expired data: {}", e);
1424 }
1425 if let Some(rate_limiter) = &self.rate_limiter {
1426 let _ = rate_limiter.cleanup().ok();
1427 }
1428
1429 let active_sessions = self
1430 .session_manager
1431 .count_active_sessions()
1432 .await
1433 .unwrap_or(0) as u32;
1434
1435 stats.registered_methods = self.methods.keys().cloned().collect();
1436 stats.active_sessions = active_sessions as u64;
1437 stats.active_mfa_challenges = self.mfa_manager.get_active_challenge_count().await as u64;
1438 let perf = self.monitoring_manager.get_performance_metrics();
1440 stats.tokens_issued = perf.get("token_creations").copied().unwrap_or(0);
1441 stats.auth_attempts = perf.get("auth_successes").copied().unwrap_or(0)
1442 + perf.get("auth_failures").copied().unwrap_or(0);
1443
1444 Ok(stats)
1445 }
1446
1447 pub fn token_manager(&self) -> &TokenManager {
1452 &self.token_manager
1453 }
1454
1455 pub async fn validate_username(&self, username: &str) -> Result<bool> {
1465 self.user_manager.validate_username(username).await
1466 }
1467
1468 pub async fn validate_display_name(&self, display_name: &str) -> Result<bool> {
1475 self.user_manager.validate_display_name(display_name).await
1476 }
1477
1478 pub async fn validate_password_strength(&self, password: &str) -> Result<bool> {
1487 self.user_manager.validate_password_strength(password).await
1488 }
1489
1490 pub async fn validate_user_input(&self, input: &str) -> Result<bool> {
1495 Ok(crate::utils::validation::validate_user_input(input))
1496 }
1497
1498 pub async fn create_auth_token(
1518 &self,
1519 user_id: impl Into<String>,
1520 scopes: impl Into<crate::types::Scopes>,
1521 method_name: impl Into<String>,
1522 lifetime: Option<Duration>,
1523 ) -> Result<AuthToken> {
1524 let method_name = method_name.into();
1525 let user_id = user_id.into();
1526 let scopes: crate::types::Scopes = scopes.into();
1527
1528 let auth_method = self
1530 .methods
1531 .get(&method_name)
1532 .ok_or_else(|| AuthError::auth_method(&method_name, "Method not found"))?;
1533 auth_method.validate_config()?;
1534
1535 const MAX_TOKENS_PER_USER: usize = 100;
1537 let user_tokens = self.storage.list_user_tokens(&user_id).await?;
1538 if user_tokens.len() >= MAX_TOKENS_PER_USER {
1539 warn!(
1540 "User '{}' has reached maximum tokens ({})",
1541 user_id, MAX_TOKENS_PER_USER
1542 );
1543 return Err(AuthError::rate_limit(
1544 "Maximum tokens per user exceeded. Please revoke unused tokens.",
1545 ));
1546 }
1547
1548 let token = self
1549 .mint_and_store_token(&user_id, scopes, &method_name, lifetime)
1550 .await?;
1551 self.monitoring_manager
1552 .record_token_creation(&method_name)
1553 .await;
1554 Ok(token)
1555 }
1556
1557 pub async fn initiate_sms_challenge(&self, user_id: &str) -> Result<String> {
1567 self.mfa_manager.sms.initiate_challenge(user_id).await
1568 }
1569
1570 pub async fn verify_sms_code(&self, challenge_id: &str, code: &str) -> Result<bool> {
1578 self.mfa_manager.sms.verify_code(challenge_id, code).await
1579 }
1580
1581 pub async fn register_email(&self, user_id: &str, email: &str) -> Result<()> {
1588 self.mfa_manager.email.register_email(user_id, email).await
1589 }
1590
1591 pub async fn generate_totp_secret(&self, user_id: &str) -> Result<String> {
1602 self.mfa_manager.totp.generate_secret(user_id).await
1603 }
1604
1605 pub async fn generate_totp_qr_code(
1613 &self,
1614 user_id: &str,
1615 app_name: &str,
1616 secret: &str,
1617 ) -> Result<String> {
1618 self.mfa_manager
1619 .totp
1620 .generate_qr_code(user_id, app_name, secret)
1621 .await
1622 }
1623
1624 pub async fn generate_totp_code(&self, secret: &str) -> Result<String> {
1629 self.mfa_manager.totp.generate_code(secret).await
1630 }
1631
1632 pub async fn generate_totp_code_for_window(
1636 &self,
1637 secret: &str,
1638 time_window: Option<u64>,
1639 ) -> Result<String> {
1640 self.mfa_manager
1641 .totp
1642 .generate_code_for_window(secret, time_window)
1643 .await
1644 }
1645
1646 pub async fn verify_totp_code(&self, user_id: &str, code: &str) -> Result<bool> {
1654 self.mfa_manager.totp.verify_code(user_id, code).await
1655 }
1656
1657 pub async fn check_ip_rate_limit(&self, ip: &str) -> Result<bool> {
1662 debug!("Checking IP rate limit for '{}'", ip);
1663 let Some(ref rate_limiter) = self.rate_limiter else {
1664 return Ok(true);
1665 };
1666 if !rate_limiter.is_allowed(&format!("ip:{}", ip)) {
1667 warn!("Rate limit exceeded for IP: {}", ip);
1668 return Err(AuthError::rate_limit(format!(
1669 "Too many requests from IP {}. Please try again later.",
1670 ip
1671 )));
1672 }
1673 Ok(true)
1674 }
1675
1676 pub async fn get_security_metrics(&self) -> Result<std::collections::HashMap<String, u64>> {
1681 debug!("Getting security metrics");
1682 let mut metrics = std::collections::HashMap::new();
1683 let total_active_sessions = self
1684 .session_manager
1685 .count_active_sessions()
1686 .await
1687 .unwrap_or(0);
1688 metrics.insert("active_sessions".to_string(), total_active_sessions);
1689 metrics.insert("total_tokens".to_string(), total_active_sessions);
1690 metrics.insert(
1691 "failed_attempts".to_string(),
1692 self.audit_manager
1693 .get_failed_login_count_24h()
1694 .await
1695 .unwrap_or(0),
1696 );
1697 metrics.insert(
1698 "successful_attempts".to_string(),
1699 self.audit_manager
1700 .get_successful_login_count_24h()
1701 .await
1702 .unwrap_or(0),
1703 );
1704 metrics.insert("expired_tokens".to_string(), 0u64);
1705 Ok(metrics)
1706 }
1707
1708 pub async fn register_phone_number(&self, user_id: &str, phone_number: &str) -> Result<()> {
1714 self.mfa_manager
1715 .sms
1716 .register_phone_number(user_id, phone_number)
1717 .await
1718 }
1719
1720 pub async fn generate_backup_codes(&self, user_id: &str, count: usize) -> Result<Vec<String>> {
1725 self.mfa_manager
1726 .backup_codes
1727 .generate_codes(user_id, count)
1728 .await
1729 }
1730 pub async fn grant_permission(
1742 &self,
1743 user_id: &str,
1744 action: &str,
1745 resource: &str,
1746 ) -> Result<()> {
1747 self.authorization_manager
1748 .grant_permission(user_id, action, resource)
1749 .await
1750 }
1751
1752 pub async fn initiate_email_challenge(&self, user_id: &str) -> Result<String> {
1762 self.mfa_manager.email.initiate_challenge(user_id).await
1763 }
1764
1765 pub fn storage(&self) -> Arc<dyn AuthStorage> {
1770 self.storage.clone()
1771 }
1772
1773 pub fn config(&self) -> &AuthConfig {
1775 &self.config
1776 }
1777
1778 pub async fn reset_authorization_runtime(&self) {
1780 self.authorization_manager.reset_runtime_state().await;
1781 }
1782
1783 pub async fn register_user(
1806 &self,
1807 username: &str,
1808 email: &str,
1809 password: &str,
1810 ) -> Result<String> {
1811 self.require_initialized()?;
1812 self.user_manager
1813 .register_user(username, email, password)
1814 .await
1815 }
1816
1817 #[deprecated(
1844 since = "0.6.0",
1845 note = "use `list_users_with_query(UserListQuery::new().limit(n).active_only())` instead"
1846 )]
1847 pub async fn list_users(
1848 &self,
1849 limit: Option<usize>,
1850 offset: Option<usize>,
1851 active_only: bool,
1852 ) -> Result<Vec<UserInfo>> {
1853 self.require_initialized()?;
1854 self.user_manager
1855 .list_users(limit, offset, active_only)
1856 .await
1857 }
1858
1859 pub async fn list_users_with_query(&self, query: UserListQuery) -> Result<Vec<UserInfo>> {
1878 self.require_initialized()?;
1879 self.user_manager
1880 .list_users(
1881 query.get_limit(),
1882 query.get_offset(),
1883 query.get_active_only(),
1884 )
1885 .await
1886 }
1887
1888 pub async fn get_user_record(&self, user_id: &str) -> Result<UserInfo> {
1890 self.require_initialized()?;
1891 self.user_manager.get_user_info(user_id).await
1892 }
1893
1894 pub async fn update_user_roles(&self, user_id: &str, roles: &[String]) -> Result<()> {
1896 self.require_initialized()?;
1897 self.user_manager.update_user_roles(user_id, roles).await
1898 }
1899
1900 pub async fn set_user_active(&self, user_id: &str, active: bool) -> Result<()> {
1902 self.require_initialized()?;
1903 self.user_manager.set_user_active(user_id, active).await
1904 }
1905
1906 pub async fn update_user_email(&self, user_id: &str, email: &str) -> Result<()> {
1908 self.require_initialized()?;
1909 self.user_manager.update_user_email(user_id, email).await
1910 }
1911
1912 pub async fn verify_user_password(&self, user_id: &str, password: &str) -> Result<bool> {
1914 self.require_initialized()?;
1915 self.user_manager
1916 .verify_user_password(user_id, password)
1917 .await
1918 }
1919
1920 pub async fn get_username_by_id(&self, user_id: &str) -> Result<String> {
1922 self.user_manager.get_username_by_id(user_id).await
1923 }
1924
1925 pub async fn username_exists(&self, username: &str) -> Result<bool> {
1927 self.user_manager.username_exists(username).await
1928 }
1929
1930 pub async fn email_exists(&self, email: &str) -> Result<bool> {
1932 self.user_manager.email_exists(email).await
1933 }
1934
1935 pub async fn get_user_by_username(
1937 &self,
1938 username: &str,
1939 ) -> Result<HashMap<String, serde_json::Value>> {
1940 self.user_manager.get_user_by_username(username).await
1941 }
1942
1943 pub async fn update_user_password(&self, username: &str, new_password: &str) -> Result<()> {
1945 self.require_initialized()?;
1946 self.user_manager
1947 .update_user_password(username, new_password)
1948 .await
1949 }
1950
1951 pub async fn update_user_password_by_id(
1953 &self,
1954 user_id: &str,
1955 new_password: &str,
1956 ) -> Result<()> {
1957 self.require_initialized()?;
1958 self.user_manager
1959 .update_user_password_by_id(user_id, new_password)
1960 .await
1961 }
1962
1963 pub async fn delete_user(&self, username: &str) -> Result<()> {
1965 self.require_initialized()?;
1966 self.user_manager.delete_user(username).await
1967 }
1968
1969 pub async fn delete_user_by_id(&self, user_id: &str) -> Result<()> {
1971 self.require_initialized()?;
1972 self.user_manager.delete_user_by_id(user_id).await
1973 }
1974
1975 async fn verify_mfa_code(&self, challenge: &MfaChallenge, code: &str) -> Result<bool> {
1977 self.mfa_manager
1978 .verify_challenge_code(challenge, code)
1979 .await
1980 }
1981
1982 async fn log_audit_event(
1984 &self,
1985 event_type: &str,
1986 user_id: &str,
1987 method: &str,
1988 metadata: &CredentialMetadata,
1989 ) {
1990 if !self.config.audit.enabled {
1991 return;
1992 }
1993 let should_log = match event_type {
1994 "auth_success" | "mfa_required" => self.config.audit.log_success,
1995 "auth_failure" => self.config.audit.log_failures,
1996 _ => true,
1997 };
1998 if should_log {
1999 self.audit_manager
2000 .log_auth_trace_event(
2001 event_type,
2002 user_id,
2003 method,
2004 metadata.client_ip.as_deref().unwrap_or("unknown"),
2005 metadata.user_agent.as_deref().unwrap_or("unknown"),
2006 )
2007 .await;
2008 }
2009 }
2010
2011 async fn guard_and_store_mfa_challenge(&self, challenge: MfaChallenge) -> Result<()> {
2013 self.mfa_manager.guard_and_store(challenge).await
2014 }
2015
2016 async fn mint_and_store_token(
2018 &self,
2019 user_id: &str,
2020 scopes: impl Into<crate::types::Scopes>,
2021 method: &str,
2022 lifetime: Option<Duration>,
2023 ) -> Result<AuthToken> {
2024 let token = self
2025 .token_manager
2026 .create_auth_token(user_id, scopes, method, lifetime)?;
2027 self.storage.store_token(&token).await?;
2028 Ok(token)
2029 }
2030
2031 pub async fn coordinate_distributed_sessions(&self) -> Result<SessionCoordinationStats> {
2033 self.session_manager.coordinate_distributed_sessions().await
2034 }
2035
2036 pub async fn synchronize_session(&self, session_id: &str) -> Result<()> {
2038 self.session_manager.synchronize_session(session_id).await
2039 }
2040
2041 pub fn monitoring_manager(&self) -> Arc<crate::monitoring::MonitoringManager> {
2043 self.monitoring_manager.clone()
2044 }
2045
2046 #[cfg(feature = "api-server")]
2048 pub fn security_manager(&self) -> Option<Arc<crate::api::SecurityManager>> {
2049 Some(self.security_manager.clone())
2050 }
2051
2052 pub async fn get_performance_metrics(&self) -> std::collections::HashMap<String, u64> {
2054 self.monitoring_manager.get_performance_metrics()
2055 }
2056
2057 pub async fn health_check(
2059 &self,
2060 ) -> Result<std::collections::HashMap<String, crate::monitoring::HealthCheckResult>> {
2061 self.monitoring_manager.health_check().await
2062 }
2063
2064 pub async fn export_prometheus_metrics(&self) -> String {
2066 self.monitoring_manager.export_prometheus_metrics().await
2067 }
2068 pub async fn create_role(&self, role: crate::permissions::Role) -> Result<()> {
2070 self.require_initialized()?;
2071 self.authorization_manager.create_role(role).await
2072 }
2073
2074 pub async fn list_roles(&self) -> Vec<crate::permissions::Role> {
2076 self.authorization_manager.list_roles().await
2077 }
2078
2079 pub async fn get_role(&self, role_name: &str) -> Result<crate::permissions::Role> {
2081 self.authorization_manager.get_role(role_name).await
2082 }
2083
2084 pub async fn add_role_permission(
2086 &self,
2087 role_name: &str,
2088 permission: crate::permissions::Permission,
2089 ) -> Result<()> {
2090 self.authorization_manager
2091 .add_role_permission(role_name, permission)
2092 .await
2093 }
2094
2095 pub async fn assign_role(&self, user_id: &str, role_name: &str) -> Result<()> {
2097 self.require_initialized()?;
2098 self.authorization_manager
2099 .assign_role(user_id, role_name)
2100 .await
2101 }
2102
2103 pub async fn remove_role(&self, user_id: &str, role_name: &str) -> Result<()> {
2105 self.require_initialized()?;
2106 self.authorization_manager
2107 .remove_role(user_id, role_name)
2108 .await
2109 }
2110
2111 pub async fn set_role_inheritance(&self, child_role: &str, parent_role: &str) -> Result<()> {
2113 self.require_initialized()?;
2114 self.authorization_manager
2115 .set_role_inheritance(child_role, parent_role)
2116 .await
2117 }
2118
2119 pub async fn revoke_permission(
2121 &self,
2122 user_id: &str,
2123 action: &str,
2124 resource: &str,
2125 ) -> Result<()> {
2126 self.require_initialized()?;
2127 self.authorization_manager
2128 .revoke_permission(user_id, action, resource)
2129 .await
2130 }
2131
2132 pub async fn user_has_role(&self, user_id: &str, role_name: &str) -> Result<bool> {
2134 self.authorization_manager
2135 .user_has_role(user_id, role_name)
2136 .await
2137 }
2138
2139 pub async fn list_user_roles(&self, user_id: &str) -> Result<Vec<String>> {
2141 self.authorization_manager.list_user_roles(user_id).await
2142 }
2143
2144 pub async fn get_effective_permissions(&self, user_id: &str) -> Result<Vec<String>> {
2146 self.authorization_manager
2147 .get_effective_permissions(user_id)
2148 .await
2149 }
2150
2151 pub async fn create_abac_policy(&self, name: &str, description: &str) -> Result<()> {
2153 self.authorization_manager
2154 .create_abac_policy(name, description)
2155 .await
2156 }
2157
2158 pub async fn map_user_attribute(
2179 &self,
2180 user_id: &str,
2181 attribute: &str,
2182 value: &str,
2183 ) -> Result<()> {
2184 self.authorization_manager
2185 .map_user_attribute(user_id, attribute, value)
2186 .await
2187 }
2188
2189 pub async fn get_user_attribute(
2213 &self,
2214 user_id: &str,
2215 attribute: &str,
2216 ) -> Result<Option<String>> {
2217 self.authorization_manager
2218 .get_user_attribute(user_id, attribute)
2219 .await
2220 }
2221
2222 pub async fn check_dynamic_permission(
2253 &self,
2254 user_id: &str,
2255 action: &str,
2256 resource: &str,
2257 context: std::collections::HashMap<String, String>,
2258 ) -> Result<bool> {
2259 self.authorization_manager
2260 .check_dynamic_permission(user_id, action, resource, context)
2261 .await
2262 }
2263
2264 pub async fn check_dynamic_permission_with_context(
2284 &self,
2285 user_id: &str,
2286 action: &str,
2287 resource: &str,
2288 context: PermissionContext,
2289 ) -> Result<bool> {
2290 self.check_dynamic_permission(user_id, action, resource, context.into_attributes())
2291 .await
2292 }
2293
2294 pub async fn create_resource(&self, resource: &str) -> Result<()> {
2296 self.authorization_manager.create_resource(resource).await
2297 }
2298
2299 pub async fn delegate_permission_with_request(&self, req: DelegationRequest) -> Result<()> {
2318 self.authorization_manager
2319 .delegate_permission(
2320 req.delegator_id(),
2321 req.delegatee_id(),
2322 req.action(),
2323 req.resource(),
2324 req.get_duration(),
2325 )
2326 .await
2327 }
2328
2329 pub async fn delegate_permission(
2334 &self,
2335 delegator_id: &str,
2336 delegatee_id: &str,
2337 action: &str,
2338 resource: &str,
2339 duration: std::time::Duration,
2340 ) -> Result<()> {
2341 self.authorization_manager
2342 .delegate_permission(delegator_id, delegatee_id, action, resource, duration)
2343 .await
2344 }
2345
2346 pub async fn get_active_delegations(&self, user_id: &str) -> Result<Vec<String>> {
2348 self.authorization_manager
2349 .get_active_delegations(user_id)
2350 .await
2351 }
2352
2353 pub async fn get_permission_audit_logs(
2355 &self,
2356 user_id: Option<&str>,
2357 action: Option<&str>,
2358 resource: Option<&str>,
2359 limit: Option<usize>,
2360 ) -> Result<Vec<String>> {
2361 self.audit_manager
2362 .get_permission_audit_logs(user_id, action, resource, limit)
2363 .await
2364 }
2365
2366 pub async fn get_permission_audit_logs_with_query(
2386 &self,
2387 query: AuditLogQuery,
2388 ) -> Result<Vec<String>> {
2389 self.audit_manager
2390 .get_permission_audit_logs(
2391 query.get_user_id(),
2392 query.get_action(),
2393 query.get_resource(),
2394 query.get_limit(),
2395 )
2396 .await
2397 }
2398
2399 pub async fn get_permission_metrics(
2401 &self,
2402 ) -> Result<std::collections::HashMap<String, u64>, AuthError> {
2403 let active_sessions = self.storage.count_active_sessions().await.unwrap_or(0);
2404 let permission_checks_last_hour = self
2405 .audit_manager
2406 .get_permission_checks_last_hour()
2407 .await
2408 .unwrap_or(0);
2409 self.authorization_manager
2410 .get_permission_metrics(active_sessions, permission_checks_last_hour)
2411 .await
2412 }
2413
2414 pub async fn get_security_audit_stats(&self) -> Result<SecurityAuditStats> {
2416 let active_sessions = self
2417 .session_manager
2418 .count_active_sessions()
2419 .await
2420 .unwrap_or(0);
2421 self.audit_manager
2422 .get_security_audit_stats(active_sessions)
2423 .await
2424 }
2425
2426 pub async fn get_user_profile(
2428 &self,
2429 user_id: &str,
2430 ) -> Result<crate::providers::ProviderProfile> {
2431 self.user_manager.get_user_profile(user_id).await
2432 }
2433}
2434
2435pub use crate::audit::SecurityAuditStats;
2436
2437pub use crate::auth_modular::session_manager::SessionCoordinationStats;
2438
2439#[derive(Debug, Clone, Default)]
2441pub struct AuthStats {
2442 pub registered_methods: Vec<String>,
2444
2445 pub active_sessions: u64,
2447
2448 pub active_mfa_challenges: u64,
2450
2451 pub tokens_issued: u64,
2453
2454 pub auth_attempts: u64,
2456}
2457
2458#[cfg(test)]
2459mod tests {
2460 use super::*;
2461 use crate::config::{AuthConfig, SecurityConfig};
2462 #[tokio::test]
2463 async fn test_framework_initialization() {
2464 let config = AuthConfig::new().security(SecurityConfig {
2465 min_password_length: 8,
2466 require_password_complexity: false,
2467 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2468 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2469 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2470 secure_cookies: false,
2471 cookie_same_site: crate::config::CookieSameSite::Lax,
2472 csrf_protection: false,
2473 session_timeout: Duration::from_secs(3600),
2474 previous_secret_key: None,
2475 });
2476 let mut framework = AuthFramework::new(config);
2477
2478 assert!(framework.initialize().await.is_ok());
2479 assert!(framework.initialized);
2480 }
2481
2482 #[tokio::test]
2483 async fn test_method_registration() {
2484 let config = AuthConfig::new().security(SecurityConfig {
2489 min_password_length: 8,
2490 require_password_complexity: false,
2491 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2492 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2493 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2494 secure_cookies: false,
2495 cookie_same_site: crate::config::CookieSameSite::Lax,
2496 csrf_protection: false,
2497 session_timeout: Duration::from_secs(3600),
2498 previous_secret_key: None,
2499 });
2500 let framework = AuthFramework::new(config);
2501
2502 assert!(!framework.initialized);
2504
2505 }
2508
2509 #[tokio::test]
2510 async fn test_token_validation() {
2511 let config = AuthConfig::new().security(SecurityConfig {
2512 min_password_length: 8,
2513 require_password_complexity: false,
2514 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2515 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2516 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2517 secure_cookies: false,
2518 cookie_same_site: crate::config::CookieSameSite::Lax,
2519 csrf_protection: false,
2520 session_timeout: Duration::from_secs(3600),
2521 previous_secret_key: None,
2522 });
2523 let mut framework = AuthFramework::new(config);
2524 framework.initialize().await.unwrap();
2525
2526 let token = framework
2527 .token_manager
2528 .create_auth_token("test-user", vec!["read".to_string()], "test", None)
2529 .unwrap();
2530
2531 framework.storage.store_token(&token).await.unwrap();
2533
2534 assert!(framework.validate_token(&token).await.unwrap());
2535 }
2536
2537 #[tokio::test]
2538 async fn test_session_management() {
2539 let config = AuthConfig::new().security(SecurityConfig {
2540 min_password_length: 8,
2541 require_password_complexity: false,
2542 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2543 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2544 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2545 secure_cookies: false,
2546 cookie_same_site: crate::config::CookieSameSite::Lax,
2547 csrf_protection: false,
2548 session_timeout: Duration::from_secs(3600),
2549 previous_secret_key: None,
2550 });
2551 let mut framework = AuthFramework::new(config);
2552 framework.initialize().await.unwrap();
2553
2554 let session_id = framework
2555 .create_session(
2556 "test-user",
2557 Duration::from_secs(3600),
2558 Some("192.168.1.1".to_string()),
2559 Some("Test Agent".to_string()),
2560 )
2561 .await
2562 .unwrap();
2563
2564 let session = framework.get_session(&session_id).await.unwrap();
2565 assert!(session.is_some());
2566
2567 framework.delete_session(&session_id).await.unwrap();
2568 let session = framework.get_session(&session_id).await.unwrap();
2569 assert!(session.is_none());
2570 }
2571
2572 #[tokio::test]
2573 async fn test_grouped_operations_accessors() {
2574 let config = AuthConfig::new().security(SecurityConfig {
2575 min_password_length: 8,
2576 require_password_complexity: false,
2577 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2578 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2579 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2580 secure_cookies: false,
2581 cookie_same_site: crate::config::CookieSameSite::Lax,
2582 csrf_protection: false,
2583 session_timeout: Duration::from_secs(3600),
2584 previous_secret_key: None,
2585 });
2586 let mut framework = AuthFramework::new(config);
2587 framework.initialize().await.unwrap();
2588
2589 let user_id = framework
2590 .users()
2591 .register("grouped-user", "grouped-user@example.com", "P@ssw0rd123")
2592 .await
2593 .unwrap();
2594 assert!(
2595 framework
2596 .users()
2597 .exists_by_username("grouped-user")
2598 .await
2599 .unwrap()
2600 );
2601
2602 let session_id = framework
2603 .sessions()
2604 .create(&user_id, Duration::from_secs(300), None, None)
2605 .await
2606 .unwrap();
2607 assert!(
2608 framework
2609 .sessions()
2610 .get(&session_id)
2611 .await
2612 .unwrap()
2613 .is_some()
2614 );
2615 assert_eq!(
2616 framework
2617 .sessions()
2618 .list_for_user(&user_id)
2619 .await
2620 .unwrap()
2621 .len(),
2622 1
2623 );
2624
2625 framework
2626 .authorization()
2627 .grant(&user_id, "read", "documents")
2628 .await
2629 .unwrap();
2630 let permissions = framework
2631 .authorization()
2632 .effective_permissions(&user_id)
2633 .await
2634 .unwrap();
2635 assert!(
2636 permissions
2637 .iter()
2638 .any(|permission| permission == "read:documents")
2639 );
2640
2641 framework.sessions().delete(&session_id).await.unwrap();
2642 assert!(
2643 framework
2644 .sessions()
2645 .get(&session_id)
2646 .await
2647 .unwrap()
2648 .is_none()
2649 );
2650 }
2651
2652 #[tokio::test]
2653 async fn test_cleanup_expired_data() {
2654 let config = AuthConfig::new().security(SecurityConfig {
2655 min_password_length: 8,
2656 require_password_complexity: false,
2657 password_hash_algorithm: crate::config::PasswordHashAlgorithm::Bcrypt,
2658 jwt_algorithm: crate::config::JwtAlgorithm::HS256,
2659 secret_key: Some("test_secret_key_32_bytes_long!!!!".to_string()),
2660 secure_cookies: false,
2661 cookie_same_site: crate::config::CookieSameSite::Lax,
2662 csrf_protection: false,
2663 session_timeout: Duration::from_secs(3600),
2664 previous_secret_key: None,
2665 });
2666 let mut framework = AuthFramework::new(config);
2667 framework.initialize().await.unwrap();
2668
2669 assert!(framework.cleanup_expired_data().await.is_ok());
2671 }
2672}