1use 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#[derive(Clone)]
30pub struct AuthContext {
31 auth_framework: Arc<AuthFramework>,
32 config: AuthContextConfig,
33 user_sessions: Arc<RwLock<HashMap<String, UserSession>>>,
34 oauth2_server: Option<Arc<dyn Send + Sync>>, oidc_provider: Option<Arc<dyn Send + Sync>>, audit_logger: Option<Arc<dyn Send + Sync>>, rate_limiter: Option<Arc<dyn Send + Sync>>, session_manager: Option<Arc<dyn Send + Sync>>, mfa_manager: Option<Arc<dyn Send + Sync>>, }
42
43#[derive(Clone, Debug)]
45pub struct AuthContextConfig {
46 pub token_lifetime: Duration,
48 pub refresh_token_lifetime: Duration,
50 pub require_auth_by_default: bool,
52 pub default_permissions: Vec<String>,
54 pub jwt_secret: String,
56 pub api_key_prefix: String,
58 pub enable_mfa: bool,
60 pub enable_oauth2_server: bool,
62 pub enable_oidc: bool,
64 pub enable_audit_logging: bool,
66 pub enable_rate_limiting: bool,
68 pub rate_limit_rpm: u32,
70 pub enable_secure_sessions: bool,
72 pub enable_device_fingerprinting: bool,
74 pub oauth2_providers: Vec<String>,
76 pub rsa_private_key: Option<String>,
78 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), refresh_token_lifetime: Duration::from_secs(86400 * 7), 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#[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 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#[derive(Debug)]
135pub enum AuthMiddlewareResult {
136 Authenticated(Box<UserSession>),
138 Denied(AuthError),
140 Unauthenticated,
142}
143
144#[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 pub async fn new(config: AuthContextConfig) -> Result<Self> {
169 if std::env::var("ENVIRONMENT").is_err() {
171 unsafe {
172 std::env::set_var("ENVIRONMENT", "development");
173 }
174 }
175
176 let auth_config = AuthConfig::new()
178 .token_lifetime(config.token_lifetime)
179 .refresh_token_lifetime(config.refresh_token_lifetime);
180
181 let mut auth_framework = AuthFramework::new(auth_config);
183
184 let jwt_method = JwtMethod::new()
186 .secret_key(&config.jwt_secret)
187 .issuer("web-server-abstraction");
188
189 auth_framework.register_method("jwt", AuthMethodEnum::Jwt(jwt_method));
191
192 let api_key_method = ApiKeyMethod::new();
194
195 auth_framework.register_method("api-key", AuthMethodEnum::ApiKey(api_key_method));
197
198 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 pub async fn initialize_features(&mut self) -> Result<()> {
218 if self.config.enable_oauth2_server {
220 self.enable_oauth2_server().await?;
221 }
222
223 if self.config.enable_oidc {
225 self.enable_oidc_provider().await?;
226 }
227
228 if self.config.enable_audit_logging {
230 self.enable_audit_logging().await?;
231 }
232
233 if self.config.enable_rate_limiting {
235 self.enable_rate_limiting().await?;
236 }
237
238 if self.config.enable_mfa {
240 self.enable_mfa().await?;
241 }
242
243 Ok(())
244 }
245
246 pub async fn authenticate_request(&self, request: &Request) -> AuthMiddlewareResult {
248 if let Some(_rate_limiter) = &self.rate_limiter {
250 }
253
254 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 if let Some(_audit_logger) = &self.audit_logger {
264 match &result {
265 AuthMiddlewareResult::Authenticated(session) => {
266 println!(
268 "AUDIT: JWT authentication succeeded for user: {}",
269 session.user_id
270 );
271 }
272 AuthMiddlewareResult::Denied(_) => {
273 println!("AUDIT: JWT authentication failed");
275 }
276 _ => {}
277 }
278 }
279
280 return result;
281 }
282
283 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 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 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 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, email: None, permissions: auth_token.scopes.clone(),
327 roles: vec![], 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 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 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 async fn authenticate_session_token(&self, session_token: &str) -> AuthMiddlewareResult {
396 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 if self.is_session_valid(session) {
404 return AuthMiddlewareResult::Authenticated(Box::new(session.clone()));
405 }
406 }
407 drop(sessions);
408
409 AuthMiddlewareResult::Denied(AuthError::InvalidCredentials)
411 }
412
413 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 fn is_session_valid(&self, session: &UserSession) -> bool {
428 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 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 for required in required_permissions {
449 if !user_session.permissions.contains(required) {
450 return false;
451 }
452 }
453
454 true
455 }
456
457 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 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 pub async fn revoke_token(&self, token: &str) -> Result<()> {
485 let mut sessions = self.user_sessions.write().await;
488 sessions.retain(|_, session| session.token.access_token != token);
489 Ok(())
490 }
491
492 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 pub fn config(&self) -> &AuthContextConfig {
500 &self.config
501 }
502
503 pub fn auth_framework(&self) -> &Arc<AuthFramework> {
505 &self.auth_framework
506 }
507
508 pub fn is_oauth2_enabled(&self) -> bool {
510 self.oauth2_server.is_some()
511 }
512
513 pub fn is_oidc_enabled(&self) -> bool {
515 self.oidc_provider.is_some()
516 }
517
518 pub fn is_audit_logging_enabled(&self) -> bool {
520 self.audit_logger.is_some()
521 }
522
523 pub fn is_rate_limiting_enabled(&self) -> bool {
525 self.rate_limiter.is_some()
526 }
527
528 pub fn is_mfa_enabled(&self) -> bool {
530 self.mfa_manager.is_some()
531 }
532
533 pub fn is_session_management_enabled(&self) -> bool {
535 self.session_manager.is_some()
536 }
537
538 pub async fn enable_oauth2_server(&mut self) -> Result<()> {
540 if self.config.enable_oauth2_server {
541 self.oauth2_server = Some(Arc::new(()));
544 println!("OAuth2 server capabilities enabled");
545 }
546 Ok(())
547 }
548
549 pub async fn enable_oidc_provider(&mut self) -> Result<()> {
551 if self.config.enable_oidc {
552 self.oidc_provider = Some(Arc::new(()));
555 println!("OIDC provider capabilities enabled");
556 }
557 Ok(())
558 }
559
560 pub async fn enable_audit_logging(&mut self) -> Result<()> {
562 if self.config.enable_audit_logging {
563 self.audit_logger = Some(Arc::new(()));
566 println!("Audit logging enabled");
567 }
568 Ok(())
569 }
570
571 pub async fn enable_rate_limiting(&mut self) -> Result<()> {
573 if self.config.enable_rate_limiting {
574 self.rate_limiter = Some(Arc::new(()));
577 println!("Rate limiting enabled ({} RPM)", self.config.rate_limit_rpm);
578 }
579 Ok(())
580 }
581
582 pub async fn enable_mfa(&mut self) -> Result<()> {
584 if self.config.enable_mfa {
585 self.mfa_manager = Some(Arc::new(()));
588 println!("Multi-factor authentication enabled");
589 }
590 Ok(())
591 }
592
593 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 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 pub async fn authenticate_oauth2(
638 &self,
639 _provider: &str,
640 _authorization_code: &str,
641 _redirect_uri: &str,
642 ) -> Result<UserSession> {
643 Err(WebServerError::AuthError(
645 "OAuth2 authentication not yet implemented - waiting for auth-framework API stabilization".to_string(),
646 ))
647 }
648
649 pub async fn generate_totp_secret(&self, _user_id: &str) -> Result<String> {
651 Err(WebServerError::AuthError(
653 "TOTP not yet implemented - waiting for auth-framework API stabilization".to_string(),
654 ))
655 }
656
657 pub async fn verify_totp(&self, _user_id: &str, _code: &str) -> Result<bool> {
659 Err(WebServerError::AuthError(
661 "TOTP verification not yet implemented - waiting for auth-framework API stabilization"
662 .to_string(),
663 ))
664 }
665
666 pub async fn log_auth_event(
668 &self,
669 event_type: &str,
670 user_id: &str,
671 success: bool,
672 ) -> Result<()> {
673 if self.config.enable_audit_logging {
675 println!(
677 "AUDIT: {} - User: {} - Success: {}",
678 event_type, user_id, success
679 );
680 }
681 Ok(())
682 }
683
684 pub async fn check_rate_limit(&self, _user_id: &str) -> Result<bool> {
686 if self.config.enable_rate_limiting {
688 return Ok(true);
690 }
691 Ok(true)
692 }
693}
694
695#[derive(Clone, Debug)]
697pub struct AuthRequirements {
698 pub required: bool,
700 pub permissions: Vec<String>,
702 pub roles: Vec<String>,
704 pub allow_api_key: bool,
706 pub allow_jwt: bool,
708 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 pub fn required() -> Self {
728 Self {
729 required: true,
730 ..Default::default()
731 }
732 }
733
734 pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
736 self.permissions = permissions;
737 self
738 }
739
740 pub fn with_roles(mut self, roles: Vec<String>) -> Self {
742 self.roles = roles;
743 self
744 }
745
746 pub fn jwt_only(mut self) -> Self {
748 self.allow_api_key = false;
749 self.allow_session = false;
750 self
751 }
752
753 pub fn api_key_only(mut self) -> Self {
755 self.allow_jwt = false;
756 self.allow_session = false;
757 self
758 }
759}
760
761pub async fn enhanced_auth_middleware(
763 auth_context: &AuthContext,
764 auth_requirements: &AuthRequirements,
765 request: &Request,
766) -> Result<Option<UserSession>> {
767 if let Some(auth_header) = request.headers.get("authorization")
769 && let Some(_token) = auth_header.strip_prefix("Bearer ")
770 {
771 let user_id = "extracted_user_id"; if !auth_context.check_rate_limit(user_id).await? {
774 return Err(WebServerError::AuthError("Rate limit exceeded".to_string()));
775 }
776 }
777
778 let auth_result = auth_context.authenticate_request(request).await;
780
781 match auth_result {
782 AuthMiddlewareResult::Authenticated(mut user_session) => {
783 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 if !auth_requirements.permissions.is_empty()
798 && !auth_context
799 .check_permissions(&user_session, &auth_requirements.permissions)
800 .await
801 {
802 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 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 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 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 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 if let Some(auth_header) = request.headers.get("authorization")
851 && let Some(_token) = auth_header.strip_prefix("Bearer ")
852 {
853 let user_id = "unknown"; 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
873pub 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
882pub trait RequestAuthExt {
884 fn user_session(&self) -> Option<&UserSession>;
886
887 fn user_id(&self) -> Option<&str>;
889
890 fn is_authenticated(&self) -> bool;
892
893 fn has_permission(&self, permission: &str) -> bool;
895
896 fn has_role(&self, role: &str) -> bool;
898}
899
900#[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}