web_server_abstraction/
auth.rs

1//! Comprehensive authentication and authorization integration.
2//!
3//! This module provides deep integration with auth-framework 0.4.0, enabling seamless
4//! authentication across all mountable interfaces and web server adapters.
5//!
6//! ## Features
7//!
8//! - **Multiple Authentication Methods**: JWT, API Keys, OAuth2, Passwords, TOTP
9//! - **OAuth2/OIDC Server**: Full authorization server capabilities
10//! - **Multi-Factor Authentication**: TOTP, SMS, Email verification
11//! - **Audit Logging**: Comprehensive security event tracking
12//! - **Session Management**: Secure session handling with device fingerprinting
13//! - **Rate Limiting**: Built-in protection against brute force attacks
14//! - **Enterprise Features**: SAML, WS-Security, Token introspection
15
16use crate::error::{Result, WebServerError};
17use crate::types::Request;
18use auth_framework::{
19    AuthConfig, AuthFramework, AuthResult, Credential,
20    methods::{ApiKeyMethod, AuthMethodEnum, JwtMethod},
21    tokens::AuthToken,
22};
23use std::collections::HashMap;
24use std::sync::Arc;
25use std::time::Duration;
26use tokio::sync::RwLock;
27
28/// Central authentication context that can be shared across all mountable interfaces
29#[derive(Clone)]
30pub struct AuthContext {
31    auth_framework: Arc<AuthFramework>,
32    config: AuthContextConfig,
33    user_sessions: Arc<RwLock<HashMap<String, UserSession>>>,
34    // Advanced features from auth-framework 0.4.0
35    oauth2_server: Option<Arc<dyn Send + Sync>>, // OAuth2Server placeholder
36    oidc_provider: Option<Arc<dyn Send + Sync>>, // OidcProvider placeholder
37    audit_logger: Option<Arc<dyn Send + Sync>>,  // AuditLogger placeholder
38    rate_limiter: Option<Arc<dyn Send + Sync>>,  // RateLimiter placeholder
39    session_manager: Option<Arc<dyn Send + Sync>>, // SecureSessionManager placeholder
40    mfa_manager: Option<Arc<dyn Send + Sync>>,   // MfaManager placeholder
41}
42
43/// Configuration for the authentication context
44#[derive(Clone, Debug)]
45pub struct AuthContextConfig {
46    /// Default token lifetime
47    pub token_lifetime: Duration,
48    /// Refresh token lifetime
49    pub refresh_token_lifetime: Duration,
50    /// Whether to require authentication for all routes by default
51    pub require_auth_by_default: bool,
52    /// Default permissions required for authenticated routes
53    pub default_permissions: Vec<String>,
54    /// JWT secret key
55    pub jwt_secret: String,
56    /// API key prefix
57    pub api_key_prefix: String,
58    /// Whether to enable multi-factor authentication
59    pub enable_mfa: bool,
60    /// Enable OAuth2 server capabilities
61    pub enable_oauth2_server: bool,
62    /// Enable OIDC provider functionality
63    pub enable_oidc: bool,
64    /// Enable audit logging
65    pub enable_audit_logging: bool,
66    /// Enable rate limiting
67    pub enable_rate_limiting: bool,
68    /// Rate limit requests per minute
69    pub rate_limit_rpm: u32,
70    /// Enable session security features
71    pub enable_secure_sessions: bool,
72    /// Enable device fingerprinting
73    pub enable_device_fingerprinting: bool,
74    /// Supported OAuth2 providers
75    pub oauth2_providers: Vec<String>,
76    /// RSA private key for JWT signing (PEM format)
77    pub rsa_private_key: Option<String>,
78    /// RSA public key for JWT verification (PEM format)
79    pub rsa_public_key: Option<String>,
80}
81
82impl Default for AuthContextConfig {
83    fn default() -> Self {
84        Self {
85            token_lifetime: Duration::from_secs(3600), // 1 hour
86            refresh_token_lifetime: Duration::from_secs(86400 * 7), // 7 days
87            require_auth_by_default: false,
88            default_permissions: vec!["read".to_string()],
89            jwt_secret: "development-secret-change-in-production".to_string(),
90            api_key_prefix: "wsa_".to_string(),
91            enable_mfa: false,
92            enable_oauth2_server: false,
93            enable_oidc: false,
94            enable_audit_logging: true,
95            enable_rate_limiting: true,
96            rate_limit_rpm: 100,
97            enable_secure_sessions: true,
98            enable_device_fingerprinting: false,
99            oauth2_providers: vec![
100                "google".to_string(),
101                "github".to_string(),
102                "microsoft".to_string(),
103            ],
104            rsa_private_key: None,
105            rsa_public_key: None,
106        }
107    }
108}
109
110/// User session information with enhanced auth-framework 0.4.0 features
111#[derive(Clone, Debug)]
112pub struct UserSession {
113    pub user_id: String,
114    pub username: Option<String>,
115    pub email: Option<String>,
116    pub permissions: Vec<String>,
117    pub roles: Vec<String>,
118    pub token: Box<AuthToken>,
119    pub last_activity: std::time::SystemTime,
120    pub metadata: HashMap<String, serde_json::Value>,
121    // Enhanced features from auth-framework 0.4.0
122    pub mfa_enabled: bool,
123    pub mfa_verified: bool,
124    pub device_fingerprint: Option<String>,
125    pub oauth2_provider: Option<String>,
126    pub session_id: String,
127    pub ip_address: Option<String>,
128    pub user_agent: Option<String>,
129    pub login_time: std::time::SystemTime,
130    pub totp_secret: Option<String>,
131}
132
133/// Authentication middleware result
134#[derive(Debug)]
135pub enum AuthMiddlewareResult {
136    /// Authentication succeeded, proceed with request
137    Authenticated(Box<UserSession>),
138    /// Authentication failed, deny request
139    Denied(AuthError),
140    /// No authentication attempted, proceed if not required
141    Unauthenticated,
142}
143
144/// Authentication errors
145#[derive(Debug, thiserror::Error)]
146pub enum AuthError {
147    #[error("Authentication required")]
148    AuthenticationRequired,
149    #[error("Invalid credentials")]
150    InvalidCredentials,
151    #[error("Insufficient permissions: required {required:?}, have {have:?}")]
152    InsufficientPermissions {
153        required: Vec<String>,
154        have: Vec<String>,
155    },
156    #[error("Token expired")]
157    TokenExpired,
158    #[error("Multi-factor authentication required")]
159    MfaRequired,
160    #[error("Rate limited")]
161    RateLimited,
162    #[error("Internal auth error: {0}")]
163    Internal(String),
164}
165
166impl AuthContext {
167    /// Create a new authentication context
168    pub async fn new(config: AuthContextConfig) -> Result<Self> {
169        // Set environment for development/testing if not set
170        if std::env::var("ENVIRONMENT").is_err() {
171            unsafe {
172                std::env::set_var("ENVIRONMENT", "development");
173            }
174        }
175
176        // Configure auth framework
177        let auth_config = AuthConfig::new()
178            .token_lifetime(config.token_lifetime)
179            .refresh_token_lifetime(config.refresh_token_lifetime);
180
181        // Create auth framework instance
182        let mut auth_framework = AuthFramework::new(auth_config);
183
184        // Register JWT authentication method
185        let jwt_method = JwtMethod::new()
186            .secret_key(&config.jwt_secret)
187            .issuer("web-server-abstraction");
188
189        // Register the JWT method
190        auth_framework.register_method("jwt", AuthMethodEnum::Jwt(jwt_method));
191
192        // Register API key authentication method
193        let api_key_method = ApiKeyMethod::new();
194
195        // Register the API key method
196        auth_framework.register_method("api-key", AuthMethodEnum::ApiKey(api_key_method));
197
198        // Initialize the framework
199        auth_framework.initialize().await.map_err(|e| {
200            WebServerError::AuthError(format!("Failed to initialize auth framework: {}", e))
201        })?;
202
203        Ok(Self {
204            auth_framework: Arc::new(auth_framework),
205            config: config.clone(),
206            user_sessions: Arc::new(RwLock::new(HashMap::new())),
207            oauth2_server: None,
208            oidc_provider: None,
209            audit_logger: None,
210            rate_limiter: None,
211            session_manager: None,
212            mfa_manager: None,
213        })
214    }
215
216    /// Initialize all enabled authentication features
217    pub async fn initialize_features(&mut self) -> Result<()> {
218        // Initialize OAuth2 server if enabled
219        if self.config.enable_oauth2_server {
220            self.enable_oauth2_server().await?;
221        }
222
223        // Initialize OIDC provider if enabled
224        if self.config.enable_oidc {
225            self.enable_oidc_provider().await?;
226        }
227
228        // Initialize audit logging if enabled
229        if self.config.enable_audit_logging {
230            self.enable_audit_logging().await?;
231        }
232
233        // Initialize rate limiting if enabled
234        if self.config.enable_rate_limiting {
235            self.enable_rate_limiting().await?;
236        }
237
238        // Initialize MFA if enabled
239        if self.config.enable_mfa {
240            self.enable_mfa().await?;
241        }
242
243        Ok(())
244    }
245
246    /// Authenticate a request and extract user session
247    pub async fn authenticate_request(&self, request: &Request) -> AuthMiddlewareResult {
248        // Check rate limiting first if enabled
249        if let Some(_rate_limiter) = &self.rate_limiter {
250            // For now, just check the presence of rate limiter
251            // In a real implementation, this would check IP/user rate limits
252        }
253
254        // Try different authentication methods
255
256        // 1. Try Bearer token (JWT)
257        if let Some(auth_header) = request.headers.get("authorization")
258            && let Some(token) = auth_header.strip_prefix("Bearer ")
259        {
260            let result = self.authenticate_bearer_token(token).await;
261
262            // Log authentication attempt if audit logging is enabled
263            if let Some(_audit_logger) = &self.audit_logger {
264                match &result {
265                    AuthMiddlewareResult::Authenticated(session) => {
266                        // Would log successful authentication
267                        println!(
268                            "AUDIT: JWT authentication succeeded for user: {}",
269                            session.user_id
270                        );
271                    }
272                    AuthMiddlewareResult::Denied(_) => {
273                        // Would log failed authentication
274                        println!("AUDIT: JWT authentication failed");
275                    }
276                    _ => {}
277                }
278            }
279
280            return result;
281        }
282
283        // 2. Try API key
284        if let Some(api_key_str) = request.headers.get("x-api-key") {
285            let result = self.authenticate_api_key(api_key_str).await;
286
287            // Log authentication attempt if audit logging is enabled
288            if let Some(_audit_logger) = &self.audit_logger {
289                match &result {
290                    AuthMiddlewareResult::Authenticated(session) => {
291                        println!(
292                            "AUDIT: API key authentication succeeded for user: {}",
293                            session.user_id
294                        );
295                    }
296                    AuthMiddlewareResult::Denied(_) => {
297                        println!("AUDIT: API key authentication failed");
298                    }
299                    _ => {}
300                }
301            }
302
303            return result;
304        }
305
306        // 3. Try session cookie
307        if let Some(cookie_str) = request.headers.get("cookie")
308            && let Some(session_token) = self.extract_session_token(cookie_str)
309        {
310            return self.authenticate_session_token(&session_token).await;
311        }
312
313        AuthMiddlewareResult::Unauthenticated
314    }
315
316    /// Authenticate using bearer token (JWT)
317    async fn authenticate_bearer_token(&self, token: &str) -> AuthMiddlewareResult {
318        let credential = Credential::jwt(token);
319
320        match self.auth_framework.authenticate("jwt", credential).await {
321            Ok(AuthResult::Success(auth_token)) => {
322                let user_session = UserSession {
323                    user_id: auth_token.user_id.clone(),
324                    username: None, // Could be extracted from token claims
325                    email: None,    // Could be extracted from token claims
326                    permissions: auth_token.scopes.clone(),
327                    roles: vec![], // Could be extracted from token claims
328                    token: auth_token,
329                    last_activity: std::time::SystemTime::now(),
330                    metadata: HashMap::new(),
331                    mfa_enabled: false,
332                    mfa_verified: false,
333                    device_fingerprint: None,
334                    oauth2_provider: None,
335                    session_id: uuid::Uuid::new_v4().to_string(),
336                    ip_address: None,
337                    user_agent: None,
338                    login_time: std::time::SystemTime::now(),
339                    totp_secret: None,
340                };
341
342                // Cache the session
343                let mut sessions = self.user_sessions.write().await;
344                sessions.insert(user_session.user_id.clone(), user_session.clone());
345
346                AuthMiddlewareResult::Authenticated(Box::new(user_session))
347            }
348            Ok(AuthResult::MfaRequired(_)) => AuthMiddlewareResult::Denied(AuthError::MfaRequired),
349            Ok(AuthResult::Failure(_)) | Err(_) => {
350                AuthMiddlewareResult::Denied(AuthError::InvalidCredentials)
351            }
352        }
353    }
354
355    /// Authenticate using API key
356    async fn authenticate_api_key(&self, api_key: &str) -> AuthMiddlewareResult {
357        let credential = Credential::api_key(api_key);
358
359        match self
360            .auth_framework
361            .authenticate("api-key", credential)
362            .await
363        {
364            Ok(AuthResult::Success(auth_token)) => {
365                let user_session = UserSession {
366                    user_id: auth_token.user_id.clone(),
367                    username: None,
368                    email: None,
369                    permissions: auth_token.scopes.clone(),
370                    roles: vec![],
371                    token: auth_token,
372                    last_activity: std::time::SystemTime::now(),
373                    metadata: HashMap::new(),
374                    mfa_enabled: false,
375                    mfa_verified: false,
376                    device_fingerprint: None,
377                    oauth2_provider: None,
378                    session_id: uuid::Uuid::new_v4().to_string(),
379                    ip_address: None,
380                    user_agent: None,
381                    login_time: std::time::SystemTime::now(),
382                    totp_secret: None,
383                };
384
385                AuthMiddlewareResult::Authenticated(Box::new(user_session))
386            }
387            Ok(AuthResult::MfaRequired(_)) => AuthMiddlewareResult::Denied(AuthError::MfaRequired),
388            Ok(AuthResult::Failure(_)) | Err(_) => {
389                AuthMiddlewareResult::Denied(AuthError::InvalidCredentials)
390            }
391        }
392    }
393
394    /// Authenticate using session token
395    async fn authenticate_session_token(&self, session_token: &str) -> AuthMiddlewareResult {
396        // Check if we have a cached session
397        let sessions = self.user_sessions.read().await;
398        if let Some(session) = sessions
399            .values()
400            .find(|s| s.token.token_id == session_token)
401        {
402            // Check if session is still valid
403            if self.is_session_valid(session) {
404                return AuthMiddlewareResult::Authenticated(Box::new(session.clone()));
405            }
406        }
407        drop(sessions);
408
409        // Session not found or invalid
410        AuthMiddlewareResult::Denied(AuthError::InvalidCredentials)
411    }
412
413    /// Extract session token from cookie string
414    fn extract_session_token(&self, cookie_str: &str) -> Option<String> {
415        for cookie in cookie_str.split(';') {
416            let cookie = cookie.trim();
417            if let Some((name, value)) = cookie.split_once('=')
418                && name.trim() == "session_token"
419            {
420                return Some(value.trim().to_string());
421            }
422        }
423        None
424    }
425
426    /// Check if a session is still valid
427    fn is_session_valid(&self, session: &UserSession) -> bool {
428        // Check if session has expired based on last activity
429        let now = std::time::SystemTime::now();
430        if let Ok(duration) = now.duration_since(session.last_activity) {
431            duration < self.config.token_lifetime
432        } else {
433            false
434        }
435    }
436
437    /// Check if user has required permissions
438    pub async fn check_permissions(
439        &self,
440        user_session: &UserSession,
441        required_permissions: &[String],
442    ) -> bool {
443        if required_permissions.is_empty() {
444            return true;
445        }
446
447        // Check if user has all required permissions
448        for required in required_permissions {
449            if !user_session.permissions.contains(required) {
450                return false;
451            }
452        }
453
454        true
455    }
456
457    /// Create an authentication token for a user
458    pub async fn create_token(&self, user_id: &str, permissions: Vec<String>) -> Result<String> {
459        let token = self
460            .auth_framework
461            .create_auth_token(user_id, permissions, "jwt", None)
462            .await
463            .map_err(|e| WebServerError::AuthError(format!("Failed to create token: {}", e)))?;
464
465        Ok(token.access_token)
466    }
467
468    /// Create an API key for a user
469    pub async fn create_api_key(
470        &self,
471        user_id: &str,
472        expires_in: Option<Duration>,
473    ) -> Result<String> {
474        let api_key = self
475            .auth_framework
476            .create_api_key(user_id, expires_in)
477            .await
478            .map_err(|e| WebServerError::AuthError(format!("Failed to create API key: {}", e)))?;
479
480        Ok(api_key)
481    }
482
483    /// Revoke a token or API key
484    pub async fn revoke_token(&self, token: &str) -> Result<()> {
485        // Implementation would depend on auth-framework's revocation capabilities
486        // For now, we'll remove from our local cache
487        let mut sessions = self.user_sessions.write().await;
488        sessions.retain(|_, session| session.token.access_token != token);
489        Ok(())
490    }
491
492    /// Get user session by user ID
493    pub async fn get_user_session(&self, user_id: &str) -> Option<UserSession> {
494        let sessions = self.user_sessions.read().await;
495        sessions.get(user_id).cloned()
496    }
497
498    /// Get configuration
499    pub fn config(&self) -> &AuthContextConfig {
500        &self.config
501    }
502
503    /// Get the underlying auth framework (for advanced usage)
504    pub fn auth_framework(&self) -> &Arc<AuthFramework> {
505        &self.auth_framework
506    }
507
508    /// Check if OAuth2 server is enabled
509    pub fn is_oauth2_enabled(&self) -> bool {
510        self.oauth2_server.is_some()
511    }
512
513    /// Check if OIDC provider is enabled
514    pub fn is_oidc_enabled(&self) -> bool {
515        self.oidc_provider.is_some()
516    }
517
518    /// Check if audit logging is enabled
519    pub fn is_audit_logging_enabled(&self) -> bool {
520        self.audit_logger.is_some()
521    }
522
523    /// Check if rate limiting is enabled
524    pub fn is_rate_limiting_enabled(&self) -> bool {
525        self.rate_limiter.is_some()
526    }
527
528    /// Check if MFA is enabled
529    pub fn is_mfa_enabled(&self) -> bool {
530        self.mfa_manager.is_some()
531    }
532
533    /// Check if session management is enabled
534    pub fn is_session_management_enabled(&self) -> bool {
535        self.session_manager.is_some()
536    }
537
538    /// Enable OAuth2 server functionality
539    pub async fn enable_oauth2_server(&mut self) -> Result<()> {
540        if self.config.enable_oauth2_server {
541            // For now, create a placeholder that indicates OAuth2 is enabled
542            // In a real implementation, this would initialize OAuth2Server from auth-framework
543            self.oauth2_server = Some(Arc::new(()));
544            println!("OAuth2 server capabilities enabled");
545        }
546        Ok(())
547    }
548
549    /// Enable OIDC provider functionality
550    pub async fn enable_oidc_provider(&mut self) -> Result<()> {
551        if self.config.enable_oidc {
552            // For now, create a placeholder that indicates OIDC is enabled
553            // In a real implementation, this would initialize OidcProvider from auth-framework
554            self.oidc_provider = Some(Arc::new(()));
555            println!("OIDC provider capabilities enabled");
556        }
557        Ok(())
558    }
559
560    /// Enable audit logging
561    pub async fn enable_audit_logging(&mut self) -> Result<()> {
562        if self.config.enable_audit_logging {
563            // For now, create a placeholder that indicates audit logging is enabled
564            // In a real implementation, this would initialize AuditLogger from auth-framework
565            self.audit_logger = Some(Arc::new(()));
566            println!("Audit logging enabled");
567        }
568        Ok(())
569    }
570
571    /// Enable rate limiting
572    pub async fn enable_rate_limiting(&mut self) -> Result<()> {
573        if self.config.enable_rate_limiting {
574            // For now, create a placeholder that indicates rate limiting is enabled
575            // In a real implementation, this would initialize RateLimiter from auth-framework
576            self.rate_limiter = Some(Arc::new(()));
577            println!("Rate limiting enabled ({} RPM)", self.config.rate_limit_rpm);
578        }
579        Ok(())
580    }
581
582    /// Enable multi-factor authentication
583    pub async fn enable_mfa(&mut self) -> Result<()> {
584        if self.config.enable_mfa {
585            // For now, create a placeholder that indicates MFA is enabled
586            // In a real implementation, this would initialize MfaManager from auth-framework
587            self.mfa_manager = Some(Arc::new(()));
588            println!("Multi-factor authentication enabled");
589        }
590        Ok(())
591    }
592
593    /// Create a user with password authentication
594    pub async fn create_user_with_password(
595        &self,
596        user_id: &str,
597        username: &str,
598        email: &str,
599        _password: &str,
600        permissions: Vec<String>,
601        roles: Vec<String>,
602    ) -> Result<UserSession> {
603        // TODO: Implement password-based user creation when auth-framework API is stable
604        // For now, create a basic user session
605        let user_session = UserSession {
606            user_id: user_id.to_string(),
607            username: Some(username.to_string()),
608            email: Some(email.to_string()),
609            permissions,
610            roles,
611            token: Box::new(AuthToken::new(
612                user_id,
613                "temporary_token",
614                std::time::Duration::from_secs(3600),
615                "password",
616            )),
617            last_activity: std::time::SystemTime::now(),
618            metadata: HashMap::new(),
619            mfa_enabled: false,
620            mfa_verified: false,
621            device_fingerprint: None,
622            oauth2_provider: None,
623            session_id: uuid::Uuid::new_v4().to_string(),
624            ip_address: None,
625            user_agent: None,
626            login_time: std::time::SystemTime::now(),
627            totp_secret: None,
628        };
629
630        let mut sessions = self.user_sessions.write().await;
631        sessions.insert(user_id.to_string(), user_session.clone());
632
633        Ok(user_session)
634    }
635
636    /// Authenticate with OAuth2 provider
637    pub async fn authenticate_oauth2(
638        &self,
639        _provider: &str,
640        _authorization_code: &str,
641        _redirect_uri: &str,
642    ) -> Result<UserSession> {
643        // TODO: Implement OAuth2 authentication when auth-framework API is stable
644        Err(WebServerError::AuthError(
645            "OAuth2 authentication not yet implemented - waiting for auth-framework API stabilization".to_string(),
646        ))
647    }
648
649    /// Generate TOTP secret for user
650    pub async fn generate_totp_secret(&self, _user_id: &str) -> Result<String> {
651        // TODO: Implement TOTP when auth-framework API is stable
652        Err(WebServerError::AuthError(
653            "TOTP not yet implemented - waiting for auth-framework API stabilization".to_string(),
654        ))
655    }
656
657    /// Verify TOTP code
658    pub async fn verify_totp(&self, _user_id: &str, _code: &str) -> Result<bool> {
659        // TODO: Implement TOTP verification when auth-framework API is stable
660        Err(WebServerError::AuthError(
661            "TOTP verification not yet implemented - waiting for auth-framework API stabilization"
662                .to_string(),
663        ))
664    }
665
666    /// Log authentication event for audit
667    pub async fn log_auth_event(
668        &self,
669        event_type: &str,
670        user_id: &str,
671        success: bool,
672    ) -> Result<()> {
673        // TODO: Implement audit logging when auth-framework API is stable
674        if self.config.enable_audit_logging {
675            // Would log to audit system
676            println!(
677                "AUDIT: {} - User: {} - Success: {}",
678                event_type, user_id, success
679            );
680        }
681        Ok(())
682    }
683
684    /// Check rate limit for user
685    pub async fn check_rate_limit(&self, _user_id: &str) -> Result<bool> {
686        // TODO: Implement rate limiting when auth-framework API is stable
687        if self.config.enable_rate_limiting {
688            // For now, always allow (would implement actual rate limiting)
689            return Ok(true);
690        }
691        Ok(true)
692    }
693}
694
695/// Authentication requirements for routes
696#[derive(Clone, Debug)]
697pub struct AuthRequirements {
698    /// Whether authentication is required
699    pub required: bool,
700    /// Required permissions
701    pub permissions: Vec<String>,
702    /// Required roles
703    pub roles: Vec<String>,
704    /// Whether to allow API key authentication
705    pub allow_api_key: bool,
706    /// Whether to allow JWT authentication
707    pub allow_jwt: bool,
708    /// Whether to allow session authentication
709    pub allow_session: bool,
710}
711
712impl Default for AuthRequirements {
713    fn default() -> Self {
714        Self {
715            required: false,
716            permissions: vec![],
717            roles: vec![],
718            allow_api_key: true,
719            allow_jwt: true,
720            allow_session: true,
721        }
722    }
723}
724
725impl AuthRequirements {
726    /// Create auth requirements that require authentication
727    pub fn required() -> Self {
728        Self {
729            required: true,
730            ..Default::default()
731        }
732    }
733
734    /// Add required permissions
735    pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
736        self.permissions = permissions;
737        self
738    }
739
740    /// Add required roles
741    pub fn with_roles(mut self, roles: Vec<String>) -> Self {
742        self.roles = roles;
743        self
744    }
745
746    /// Only allow JWT authentication
747    pub fn jwt_only(mut self) -> Self {
748        self.allow_api_key = false;
749        self.allow_session = false;
750        self
751    }
752
753    /// Only allow API key authentication
754    pub fn api_key_only(mut self) -> Self {
755        self.allow_jwt = false;
756        self.allow_session = false;
757        self
758    }
759}
760
761/// Enhanced middleware function for authentication with auth-framework 0.4.0 features
762pub async fn enhanced_auth_middleware(
763    auth_context: &AuthContext,
764    auth_requirements: &AuthRequirements,
765    request: &Request,
766) -> Result<Option<UserSession>> {
767    // Check rate limiting first
768    if let Some(auth_header) = request.headers.get("authorization")
769        && let Some(_token) = auth_header.strip_prefix("Bearer ")
770    {
771        // Extract user ID from token for rate limiting (simplified)
772        let user_id = "extracted_user_id"; // Would extract from token in real implementation
773        if !auth_context.check_rate_limit(user_id).await? {
774            return Err(WebServerError::AuthError("Rate limit exceeded".to_string()));
775        }
776    }
777
778    // Perform authentication
779    let auth_result = auth_context.authenticate_request(request).await;
780
781    match auth_result {
782        AuthMiddlewareResult::Authenticated(mut user_session) => {
783            // Enhanced security checks for auth-framework 0.4.0
784
785            // Check if MFA is required but not verified
786            if auth_requirements.required
787                && auth_context.config.enable_mfa
788                && user_session.mfa_enabled
789                && !user_session.mfa_verified
790            {
791                return Err(WebServerError::AuthError(
792                    "Multi-factor authentication required".to_string(),
793                ));
794            }
795
796            // Check permissions if required
797            if !auth_requirements.permissions.is_empty()
798                && !auth_context
799                    .check_permissions(&user_session, &auth_requirements.permissions)
800                    .await
801            {
802                // Log failed permission check
803                auth_context
804                    .log_auth_event("permission_denied", &user_session.user_id, false)
805                    .await?;
806
807                return Err(WebServerError::AuthError(format!(
808                    "Insufficient permissions: required {:?}, have {:?}",
809                    auth_requirements.permissions, user_session.permissions
810                )));
811            }
812
813            // Check roles if required
814            if !auth_requirements.roles.is_empty() {
815                let has_required_role = auth_requirements
816                    .roles
817                    .iter()
818                    .any(|role| user_session.roles.contains(role));
819                if !has_required_role {
820                    // Log failed role check
821                    auth_context
822                        .log_auth_event("role_denied", &user_session.user_id, false)
823                        .await?;
824
825                    return Err(WebServerError::AuthError(format!(
826                        "Insufficient roles: required one of {:?}, have {:?}",
827                        auth_requirements.roles, user_session.roles
828                    )));
829                }
830            }
831
832            // Update session with request information
833            user_session.last_activity = std::time::SystemTime::now();
834            if let Some(ip) = request.headers.get("x-forwarded-for") {
835                user_session.ip_address = Some(ip.clone());
836            }
837            if let Some(user_agent) = request.headers.get("user-agent") {
838                user_session.user_agent = Some(user_agent.clone());
839            }
840
841            // Log successful authentication
842            auth_context
843                .log_auth_event("authentication_success", &user_session.user_id, true)
844                .await?;
845
846            Ok(Some(*user_session))
847        }
848        AuthMiddlewareResult::Denied(auth_error) => {
849            // Log failed authentication attempt
850            if let Some(auth_header) = request.headers.get("authorization")
851                && let Some(_token) = auth_header.strip_prefix("Bearer ")
852            {
853                let user_id = "unknown"; // Would extract from token
854                auth_context
855                    .log_auth_event("authentication_failed", user_id, false)
856                    .await?;
857            }
858
859            Err(WebServerError::AuthError(format!("{:?}", auth_error)))
860        }
861        AuthMiddlewareResult::Unauthenticated => {
862            if auth_requirements.required {
863                Err(WebServerError::AuthError(
864                    "Authentication required".to_string(),
865                ))
866            } else {
867                Ok(None)
868            }
869        }
870    }
871}
872
873/// Original middleware function for authentication (backward compatibility)
874pub async fn auth_middleware(
875    auth_context: &AuthContext,
876    auth_requirements: &AuthRequirements,
877    request: &Request,
878) -> Result<Option<UserSession>> {
879    enhanced_auth_middleware(auth_context, auth_requirements, request).await
880}
881
882/// Extension trait to add authentication information to requests
883pub trait RequestAuthExt {
884    /// Get the authenticated user session from the request
885    fn user_session(&self) -> Option<&UserSession>;
886
887    /// Get the user ID from the authenticated session
888    fn user_id(&self) -> Option<&str>;
889
890    /// Check if the request is authenticated
891    fn is_authenticated(&self) -> bool;
892
893    /// Check if the user has a specific permission
894    fn has_permission(&self, permission: &str) -> bool;
895
896    /// Check if the user has a specific role
897    fn has_role(&self, role: &str) -> bool;
898}
899
900// Note: Implementation of RequestAuthExt would be done through request extensions
901// in the actual middleware integration with specific frameworks
902
903#[cfg(test)]
904mod tests {
905    use super::*;
906
907    #[tokio::test]
908    async fn test_auth_context_creation() {
909        let config = AuthContextConfig::default();
910        let auth_context = AuthContext::new(config).await.unwrap();
911
912        assert!(!auth_context.config().require_auth_by_default);
913        assert_eq!(auth_context.config().default_permissions, vec!["read"]);
914    }
915
916    #[tokio::test]
917    async fn test_auth_requirements() {
918        let requirements = AuthRequirements::required()
919            .with_permissions(vec!["admin.read".to_string(), "admin.write".to_string()])
920            .jwt_only();
921
922        assert!(requirements.required);
923        assert_eq!(requirements.permissions.len(), 2);
924        assert!(!requirements.allow_api_key);
925        assert!(requirements.allow_jwt);
926    }
927
928    #[tokio::test]
929    async fn test_token_creation() {
930        let config = AuthContextConfig::default();
931        let auth_context = AuthContext::new(config).await.unwrap();
932
933        let token = auth_context
934            .create_token("test_user", vec!["read".to_string(), "write".to_string()])
935            .await
936            .unwrap();
937
938        assert!(!token.is_empty());
939    }
940}