1use crate::errors::{AuthError, Result};
27use crate::server::oidc::OidcProvider;
28use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STANDARD};
29use chrono::{DateTime, Utc};
30use serde::{Deserialize, Serialize};
31use serde_json::{Value, json};
32use std::collections::HashMap;
33use std::sync::Arc;
34use std::time::SystemTime;
35use tokio::sync::RwLock;
36use uuid::Uuid;
37
38#[derive(Debug, Clone)]
40pub struct OidcExtensionsManager {
41 oidc_provider: Arc<OidcProvider<dyn crate::storage::AuthStorage>>,
43
44 heart_manager: Arc<HeartManager>,
46
47 shared_signals_manager: Arc<SharedSignalsManager>,
49
50 ekyc_manager: Arc<EkycManager>,
52
53 fastfed_manager: Arc<FastFedManager>,
55
56 config: OidcExtensionsConfig,
58}
59
60#[derive(Debug, Clone)]
62pub struct OidcExtensionsConfig {
63 pub enable_heart: bool,
65
66 pub enable_shared_signals: bool,
68
69 pub enable_ekyc: bool,
71
72 pub enable_fastfed: bool,
74
75 pub enable_modrna: bool,
77
78 pub enable_igov: bool,
80
81 pub enable_authzen: bool,
83}
84
85#[derive(Debug, Clone)]
89pub struct HeartManager {
90 config: HeartConfig,
92
93 sessions: Arc<RwLock<HashMap<String, HeartSession>>>,
95}
96
97#[derive(Debug, Clone)]
99pub struct HeartConfig {
100 pub organization_id: String,
102
103 pub fhir_endpoint: String,
105
106 pub required_scopes: Vec<String>,
108
109 pub enhanced_consent: bool,
111
112 pub authorized_providers: Vec<String>,
114
115 pub audit_config: HeartAuditConfig,
117}
118
119#[derive(Debug, Clone)]
121pub struct HeartAuditConfig {
122 pub enable_atna: bool,
124
125 pub syslog_endpoint: Option<String>,
127
128 pub audit_level: HeartAuditLevel,
130}
131
132#[derive(Debug, Clone, PartialEq)]
134pub enum HeartAuditLevel {
135 Basic,
137 Enhanced,
139 Full,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct HeartSession {
146 pub session_id: String,
148
149 pub patient_id: Option<String>,
151
152 pub provider_id: String,
154
155 pub authorized_resources: Vec<String>,
157
158 pub consent_status: ConsentStatus,
160
161 pub metadata: HashMap<String, Value>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub enum ConsentStatus {
168 Granted,
170 Denied,
172 Pending,
174 Revoked,
176}
177
178#[derive(Debug, Clone)]
182pub struct SharedSignalsManager {
183 config: SharedSignalsConfig,
185
186 receivers: Arc<RwLock<HashMap<String, SignalReceiver>>>,
188
189 transmitters: Arc<RwLock<HashMap<String, SignalTransmitter>>>,
191}
192
193#[derive(Debug, Clone)]
195pub struct SharedSignalsConfig {
196 pub endpoint_url: String,
198
199 pub supported_events: Vec<String>,
201
202 pub max_event_age: i64,
204
205 pub verify_events: bool,
207}
208
209#[derive(Debug, Clone)]
211pub struct SignalReceiver {
212 pub receiver_id: String,
214
215 pub endpoint_url: String,
217
218 pub event_types: Vec<String>,
220
221 pub auth_method: SignalAuthMethod,
223}
224
225#[derive(Debug, Clone)]
227pub struct SignalTransmitter {
228 pub transmitter_id: String,
230
231 pub endpoints: Vec<String>,
233
234 pub event_buffer: Vec<SecurityEvent>,
236}
237
238impl SignalTransmitter {
239 pub async fn send_event(&self, event_jwt: &str, receiver_url: &str) -> Result<(), AuthError> {
241 use crate::server::core::common_config::EndpointConfig;
242 use crate::server::core::common_http::HttpClient;
243 use std::collections::HashMap;
244
245 let config = EndpointConfig::new(receiver_url);
247 let client = HttpClient::new(config)?;
248
249 let mut headers = HashMap::new();
251 headers.insert(
252 "Content-Type".to_string(),
253 "application/secevent+jwt".to_string(),
254 );
255 headers.insert("Accept".to_string(), "application/json".to_string());
256
257 let response = client
259 .request_with_headers(
260 reqwest::Method::POST,
261 "",
262 headers,
263 Some(&event_jwt.to_string()),
264 )
265 .await?;
266
267 if !response.status().is_success() {
268 let (status, body) =
269 crate::server::core::common_http::response::extract_error_details(response).await;
270 return Err(AuthError::internal(format!(
271 "Security event transmission failed with status {}: {}",
272 status, body
273 )));
274 }
275
276 tracing::info!(
277 "Successfully transmitted security event to: {}",
278 receiver_url
279 );
280 Ok(())
281 }
282}
283
284#[derive(Debug, Clone)]
286pub enum SignalAuthMethod {
287 Bearer(String),
289 MutualTls,
291 SignedJwt,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct SecurityEvent {
298 pub event_id: String,
300
301 pub event_type: String,
303
304 pub timestamp: DateTime<Utc>,
306
307 pub subject: String,
309
310 pub data: Value,
312
313 pub severity: EventSeverity,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct AccountDisableRequest {
320 pub user_id: String,
322 pub reason: String,
324 pub disable_timestamp: DateTime<Utc>,
326 pub initiated_by: String,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub enum EventSeverity {
333 Info,
335 Warning,
337 Critical,
339 Emergency,
341}
342
343#[derive(Debug, Clone)]
347pub struct EkycManager {
348 config: EkycConfig,
350
351 verification_sessions: Arc<RwLock<HashMap<String, EkycSession>>>,
353}
354
355#[derive(Debug, Clone)]
357pub struct EkycConfig {
358 pub verification_provider: String,
360
361 pub required_ial: IdentityAssuranceLevel,
363
364 pub verification_methods: Vec<VerificationMethod>,
366
367 pub document_verification: bool,
369
370 pub biometric_verification: bool,
372}
373
374#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
376pub enum IdentityAssuranceLevel {
377 IAL1,
379 IAL2,
381 IAL3,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
387pub enum VerificationMethod {
388 Document,
390 Biometric,
392 Database,
394 KnowledgeBased,
396}
397
398#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct EkycSession {
401 pub session_id: String,
403
404 pub user_id: String,
406
407 pub verification_status: VerificationStatus,
409
410 pub achieved_ial: IdentityAssuranceLevel,
412
413 pub verification_results: HashMap<String, Value>,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
419pub enum VerificationStatus {
420 Pending,
422 InProgress,
424 Success,
426 Failed,
428 Expired,
430}
431
432#[derive(Debug, Clone)]
436pub struct FastFedManager {
437 config: FastFedConfig,
439
440 federations: Arc<RwLock<HashMap<String, FederationRelationship>>>,
442}
443
444#[derive(Debug, Clone)]
446pub struct FastFedConfig {
447 pub metadata_endpoint: String,
449
450 pub supported_protocols: Vec<String>,
452
453 pub auto_provisioning: bool,
455
456 pub trusted_partners: Vec<String>,
458
459 pub trust_anchor: String,
461}
462
463#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct FederationRelationship {
466 pub relationship_id: String,
468
469 pub partner_org: String,
471
472 pub status: FederationStatus,
474
475 pub config: Value,
477
478 pub created_at: DateTime<Utc>,
480}
481
482#[derive(Debug, Clone, Serialize, Deserialize)]
484pub enum FederationStatus {
485 Pending,
487 Active,
489 Suspended,
491 Terminated,
493}
494
495impl OidcExtensionsManager {
496 pub fn new(
498 oidc_provider: Arc<OidcProvider<dyn crate::storage::AuthStorage>>,
499 config: OidcExtensionsConfig,
500 ) -> Self {
501 let heart_manager = Arc::new(HeartManager::new(HeartConfig::default()));
502 let shared_signals_manager =
503 Arc::new(SharedSignalsManager::new(SharedSignalsConfig::default()));
504 let ekyc_manager = Arc::new(EkycManager::new(EkycConfig::default()));
505 let fastfed_manager = Arc::new(FastFedManager::new(FastFedConfig::default()));
506
507 Self {
508 oidc_provider,
509 heart_manager,
510 shared_signals_manager,
511 ekyc_manager,
512 fastfed_manager,
513 config,
514 }
515 }
516
517 pub fn get_supported_extensions(&self) -> Vec<&str> {
519 let mut extensions = Vec::new();
520
521 if self.config.enable_heart {
522 extensions.push("HEART");
523 }
524 if self.config.enable_shared_signals {
525 extensions.push("Shared Signals Framework");
526 }
527 if self.config.enable_ekyc {
528 extensions.push("eKYC-IDA");
529 }
530 if self.config.enable_fastfed {
531 extensions.push("FastFed");
532 }
533 if self.config.enable_modrna {
534 extensions.push("MODRNA");
535 }
536 if self.config.enable_igov {
537 extensions.push("iGov");
538 }
539 if self.config.enable_authzen {
540 extensions.push("AuthZEN");
541 }
542
543 extensions
544 }
545
546 pub async fn handle_authorization_request(
548 &self,
549 extension: &str,
550 request: Value,
551 ) -> Result<Value> {
552 match extension {
553 "HEART" if self.config.enable_heart => {
554 self.heart_manager.handle_authorization(request).await
555 }
556 "SharedSignals" if self.config.enable_shared_signals => {
557 self.handle_shared_signals_request(request).await
558 }
559 "eKYC" if self.config.enable_ekyc => {
560 self.ekyc_manager.handle_verification_request(request).await
561 }
562 "FastFed" if self.config.enable_fastfed => {
563 self.fastfed_manager
564 .handle_federation_request(request)
565 .await
566 }
567 "OIDCProvider" => self.handle_oidc_provider_request(request).await,
568 _ => Err(AuthError::validation(format!(
569 "Unsupported extension: {}",
570 extension
571 ))),
572 }
573 }
574
575 async fn handle_shared_signals_request(&self, request: Value) -> Result<Value> {
577 let event_type = request["event_type"]
578 .as_str()
579 .ok_or_else(|| AuthError::auth_method("shared_signals", "Missing event_type"))?;
580
581 match event_type {
582 "send_event" => {
583 let security_event = SecurityEvent {
584 event_id: format!("evt-{}", uuid::Uuid::new_v4()),
585 event_type: request["security_event"]["event_type"]
586 .as_str()
587 .unwrap_or("unknown")
588 .to_string(),
589 subject: request["security_event"]["subject"]
590 .as_str()
591 .unwrap_or("")
592 .to_string(),
593 timestamp: chrono::Utc::now(),
594 data: request["security_event"]["data"].clone(),
595 severity: EventSeverity::Info,
596 };
597
598 self.shared_signals_manager
599 .send_event(security_event)
600 .await?;
601
602 Ok(serde_json::json!({
603 "status": "success",
604 "message": "Security event sent"
605 }))
606 }
607 "receive_event" => {
608 let security_event = SecurityEvent {
609 event_id: format!("evt-{}", uuid::Uuid::new_v4()),
610 event_type: request["event"]["event_type"]
611 .as_str()
612 .unwrap_or("unknown")
613 .to_string(),
614 subject: request["event"]["subject"]
615 .as_str()
616 .unwrap_or("")
617 .to_string(),
618 timestamp: chrono::Utc::now(),
619 data: request["event"]["data"].clone(),
620 severity: EventSeverity::Info,
621 };
622
623 self.shared_signals_manager
624 .receive_event(security_event)
625 .await?;
626
627 Ok(serde_json::json!({
628 "status": "success",
629 "message": "Security event processed"
630 }))
631 }
632 _ => Err(AuthError::validation(format!(
633 "Unsupported shared signals event type: {}",
634 event_type
635 ))),
636 }
637 }
638
639 async fn handle_oidc_provider_request(&self, request: Value) -> Result<Value> {
641 let request_type = request["request_type"]
642 .as_str()
643 .ok_or_else(|| AuthError::auth_method("oidc_provider", "Missing request_type"))?;
644
645 match request_type {
646 "discovery" => {
647 self.generate_oidc_discovery_document().await
649 }
650 "jwks" => {
651 self.generate_oidc_jwks().await
653 }
654 "userinfo" => {
655 self.handle_oidc_userinfo_request(request).await
657 }
658 _ => Err(AuthError::validation(format!(
659 "Unsupported OIDC provider request type: {}",
660 request_type
661 ))),
662 }
663 }
664
665 async fn generate_oidc_discovery_document(&self) -> Result<Value> {
667 let base_discovery = self.oidc_provider.as_ref().discovery_document()?;
669
670 let mut extensions_supported = Vec::new();
672 let mut scopes_supported = base_discovery.scopes_supported.clone();
673
674 if self.config.enable_heart {
676 extensions_supported.push("heart");
677 scopes_supported.push("heart".to_string());
678 }
679 if self.config.enable_shared_signals {
680 extensions_supported.push("shared_signals");
681 scopes_supported.push("shared_signals".to_string());
682 }
683 if self.config.enable_ekyc {
684 extensions_supported.push("ekyc");
685 scopes_supported.push("ekyc".to_string());
686 }
687 if self.config.enable_fastfed {
688 extensions_supported.push("fastfed");
689 scopes_supported.push("fastfed".to_string());
690 }
691
692 Ok(serde_json::json!({
693 "issuer": base_discovery.issuer,
694 "authorization_endpoint": base_discovery.authorization_endpoint,
695 "token_endpoint": base_discovery.token_endpoint,
696 "userinfo_endpoint": base_discovery.userinfo_endpoint,
697 "jwks_uri": base_discovery.jwks_uri,
698 "registration_endpoint": base_discovery.registration_endpoint,
699 "scopes_supported": scopes_supported,
700 "extensions_supported": extensions_supported,
701 "response_types_supported": base_discovery.response_types_supported,
702 "grant_types_supported": base_discovery.grant_types_supported.unwrap_or_else(|| vec![
703 "authorization_code".to_string(),
704 "implicit".to_string(),
705 "refresh_token".to_string()
706 ]),
707 "subject_types_supported": base_discovery.subject_types_supported,
708 "id_token_signing_alg_values_supported": base_discovery.id_token_signing_alg_values_supported,
709 "userinfo_signing_alg_values_supported": base_discovery.userinfo_signing_alg_values_supported.unwrap_or_default(),
710 "token_endpoint_auth_methods_supported": base_discovery.token_endpoint_auth_methods_supported.unwrap_or_default(),
711 "claims_supported": base_discovery.claims_supported.unwrap_or_default(),
712 "claims_parameter_supported": base_discovery.claims_parameter_supported.unwrap_or(false),
713 "request_parameter_supported": base_discovery.request_parameter_supported.unwrap_or(false),
714 "request_uri_parameter_supported": base_discovery.request_uri_parameter_supported.unwrap_or(false),
715 "code_challenge_methods_supported": base_discovery.code_challenge_methods_supported.unwrap_or_default()
716 }))
717 }
718
719 async fn generate_oidc_jwks(&self) -> Result<Value> {
721 let jwk_set = self.oidc_provider.as_ref().generate_jwks()?;
723 Ok(serde_json::to_value(jwk_set)?)
724 }
725
726 async fn handle_oidc_userinfo_request(&self, request: Value) -> Result<Value> {
728 let access_token = request["access_token"]
729 .as_str()
730 .ok_or_else(|| AuthError::auth_method("oidc_provider", "Missing access_token"))?;
731
732 let userinfo = self
734 .oidc_provider
735 .as_ref()
736 .get_userinfo(access_token)
737 .await?;
738
739 let mut userinfo_json = serde_json::json!({
741 "sub": userinfo.sub,
742 "name": userinfo.name,
743 "email": userinfo.email,
744 "email_verified": userinfo.email_verified,
745 "given_name": userinfo.given_name,
746 "family_name": userinfo.family_name,
747 "picture": userinfo.picture,
748 "locale": userinfo.locale,
749 "phone_number": userinfo.phone_number,
750 "phone_number_verified": userinfo.phone_number_verified,
751 "address": userinfo.address,
752 "updated_at": userinfo.updated_at
753 });
754
755 let mut extensions = serde_json::Map::new();
757 if self.config.enable_heart {
758 extensions.insert("heart_verified".to_string(), serde_json::Value::Bool(true));
759 }
760 if self.config.enable_ekyc {
761 extensions.insert("ekyc_verified".to_string(), serde_json::Value::Bool(true));
762 }
763 if self.config.enable_shared_signals {
764 extensions.insert(
765 "shared_signals_enabled".to_string(),
766 serde_json::Value::Bool(true),
767 );
768 }
769 if self.config.enable_fastfed {
770 extensions.insert("fastfed_enabled".to_string(), serde_json::Value::Bool(true));
771 }
772
773 if !extensions.is_empty() {
774 userinfo_json["extensions"] = serde_json::Value::Object(extensions);
775 }
776
777 Ok(userinfo_json)
778 }
779}
780
781impl HeartManager {
782 pub fn new(config: HeartConfig) -> Self {
784 Self {
785 config,
786 sessions: Arc::new(RwLock::new(HashMap::new())),
787 }
788 }
789
790 pub async fn handle_authorization(&self, request: Value) -> Result<Value> {
792 let provider_id = request["provider_id"]
795 .as_str()
796 .ok_or_else(|| AuthError::auth_method("heart", "Missing provider_id"))?;
797
798 let patient_id = request["patient_id"].as_str();
799 let empty_resources = vec![];
800 let requested_resources = request["resources"].as_array().unwrap_or(&empty_resources);
801
802 if !self
804 .config
805 .authorized_providers
806 .contains(&provider_id.to_string())
807 {
808 return Err(AuthError::auth_method(
809 "heart",
810 "Unauthorized healthcare provider",
811 ));
812 }
813
814 Ok(json!({
815 "status": "authorized",
816 "heart_compliant": true,
817 "organization_id": self.config.organization_id,
818 "provider_id": provider_id,
819 "patient_id": patient_id,
820 "authorized_resources": requested_resources
821 }))
822 }
823
824 pub async fn create_session(
826 &self,
827 provider_id: &str,
828 patient_id: Option<&str>,
829 authorized_resources: Vec<String>,
830 ) -> Result<String> {
831 let session_id = Uuid::new_v4().to_string();
832
833 let session = HeartSession {
834 session_id: session_id.clone(),
835 patient_id: patient_id.map(|s| s.to_string()),
836 provider_id: provider_id.to_string(),
837 authorized_resources,
838 consent_status: ConsentStatus::Pending,
839 metadata: HashMap::new(),
840 };
841
842 let mut sessions = self.sessions.write().await;
843 sessions.insert(session_id.clone(), session);
844
845 Ok(session_id)
846 }
847}
848
849impl SharedSignalsManager {
850 pub fn new(config: SharedSignalsConfig) -> Self {
852 Self {
853 config,
854 receivers: Arc::new(RwLock::new(HashMap::new())),
855 transmitters: Arc::new(RwLock::new(HashMap::new())),
856 }
857 }
858
859 pub async fn send_event(&self, event: SecurityEvent) -> Result<()> {
861 let event_jwt = self.create_event_jwt(&event).await?;
864
865 let transmitters = self.transmitters.read().await;
866 for (receiver_url, transmitter) in transmitters.iter() {
867 match transmitter.send_event(&event_jwt, receiver_url).await {
868 Ok(_) => log::info!("Security event sent to {}", receiver_url),
869 Err(e) => log::error!("Failed to send event to {}: {}", receiver_url, e),
870 }
871 }
872
873 log::info!("Security event transmitted: {:?}", event);
874 Ok(())
875 }
876
877 pub async fn receive_event(&self, event: SecurityEvent) -> Result<()> {
879 if !self.is_event_type_supported(&event.event_type) {
881 return Err(AuthError::auth_method(
882 "shared_signals",
883 format!("Unsupported event type: {}", event.event_type),
884 ));
885 }
886
887 if !self.is_event_valid_age(&event) {
889 return Err(AuthError::auth_method("shared_signals", "Event too old"));
890 }
891
892 if self.config.verify_events && !self.validate_event_signature(&event).await? {
894 return Err(AuthError::auth_method(
895 "shared_signals",
896 "Invalid event signature",
897 ));
898 }
899
900 match event.event_type.as_str() {
902 "session_revoked" => self.handle_session_revocation(&event).await?,
903 "account_disabled" => self.handle_account_disabled(&event).await?,
904 "credential_change" => self.handle_credential_change(&event).await?,
905 "fraud_detected" => self.handle_fraud_detection(&event).await?,
906 _ => log::warn!("Unknown security event type: {}", event.event_type),
907 }
908
909 log::info!("Processed security event: {:?}", event);
910 Ok(())
911 }
912
913 async fn create_event_jwt(&self, event: &SecurityEvent) -> Result<String> {
915 use serde_json;
917 let event_json = serde_json::to_string(event)
918 .map_err(|e| AuthError::internal(format!("Failed to serialize event: {}", e)))?;
919
920 Ok(format!(
922 "signed.jwt.{}",
923 BASE64_STANDARD.encode(&event_json)
924 ))
925 }
926
927 async fn validate_event_signature(&self, event: &SecurityEvent) -> Result<bool> {
928 if let Some(jwt_token) = event.data.get("jwt") {
933 use jsonwebtoken::{Algorithm, DecodingKey, Validation};
936
937 let decoding_key = if let Ok(key_material) =
939 std::env::var("SHARED_SIGNALS_VERIFICATION_KEY")
940 {
941 if key_material.starts_with("-----BEGIN PUBLIC KEY-----") {
943 match DecodingKey::from_rsa_pem(key_material.as_bytes()) {
945 Ok(key) => key,
946 Err(e) => {
947 tracing::error!("Failed to parse RSA public key: {}", e);
948 return Err(AuthError::InvalidRequest(
949 "Invalid RSA public key configuration".to_string(),
950 ));
951 }
952 }
953 } else if key_material.starts_with("-----BEGIN EC PUBLIC KEY-----") {
954 match DecodingKey::from_ec_pem(key_material.as_bytes()) {
956 Ok(key) => key,
957 Err(e) => {
958 tracing::error!("Failed to parse ECDSA public key: {}", e);
959 return Err(AuthError::InvalidRequest(
960 "Invalid ECDSA public key configuration".to_string(),
961 ));
962 }
963 }
964 } else {
965 DecodingKey::from_secret(key_material.as_bytes())
967 }
968 } else {
969 tracing::error!(
971 "🔐 SECURITY WARNING: Using development key for shared signals - configure SHARED_SIGNALS_VERIFICATION_KEY for production"
972 );
973 tracing::warn!(
974 "Set SHARED_SIGNALS_VERIFICATION_KEY environment variable with your production key"
975 );
976 DecodingKey::from_secret(
977 "shared_signals_development_key_not_for_production".as_ref(),
978 )
979 };
980
981 let algorithm = if std::env::var("SHARED_SIGNALS_VERIFICATION_KEY").is_ok() {
983 if let Ok(alg_str) = std::env::var("SHARED_SIGNALS_ALGORITHM") {
985 match alg_str.as_str() {
986 "HS256" => Algorithm::HS256,
987 "HS384" => Algorithm::HS384,
988 "HS512" => Algorithm::HS512,
989 "RS256" => Algorithm::RS256,
990 "RS384" => Algorithm::RS384,
991 "RS512" => Algorithm::RS512,
992 "ES256" => Algorithm::ES256,
993 "ES384" => Algorithm::ES384,
994 _ => {
995 tracing::warn!("Unknown algorithm {}, defaulting to HS256", alg_str);
996 Algorithm::HS256
997 }
998 }
999 } else {
1000 Algorithm::HS256
1001 }
1002 } else {
1003 Algorithm::HS256
1004 };
1005
1006 let mut validation = Validation::new(algorithm);
1007 validation.validate_exp = true;
1008 validation.validate_nbf = true;
1009 validation.validate_aud = false; if let Ok(expected_issuer) = std::env::var("SHARED_SIGNALS_ISSUER") {
1013 validation.set_issuer(&[expected_issuer]);
1014 tracing::debug!("Validating shared signals issuer");
1015 }
1016
1017 match jsonwebtoken::decode::<serde_json::Value>(
1018 jwt_token.as_str().unwrap_or(""),
1019 &decoding_key,
1020 &validation,
1021 ) {
1022 Ok(_) => {
1023 tracing::info!("Security event JWT signature validated successfully");
1024 Ok(true)
1025 }
1026 Err(e) => {
1027 tracing::warn!("Security event JWT signature validation failed: {}", e);
1028 Ok(false)
1029 }
1030 }
1031 } else {
1032 tracing::info!("Non-JWT security event - performing basic validation");
1034 Ok(!event.subject.is_empty() && !event.event_type.is_empty())
1035 }
1036 }
1037
1038 async fn handle_session_revocation(&self, event: &SecurityEvent) -> Result<()> {
1039 tracing::info!("Handling session revocation for event: {}", event.event_id);
1040
1041 if let Some(session_id) = event.data.get("session_id") {
1043 let session_id_str = session_id.as_str().unwrap_or("");
1044 tracing::info!("Revoking session: {}", session_id_str);
1045
1046 if let Err(e) = self.remove_session_from_store(session_id_str).await {
1049 tracing::error!("Failed to remove session from store: {}", e);
1050 }
1051
1052 if let Err(e) = self.add_session_to_revocation_list(session_id_str).await {
1054 tracing::error!("Failed to add session to revocation list: {}", e);
1055 }
1056
1057 if let Err(e) = self
1059 .notify_resource_servers_session_revoked(session_id_str)
1060 .await
1061 {
1062 tracing::error!("Failed to notify resource servers: {}", e);
1063 }
1064
1065 self.log_session_revocation_audit(session_id_str, &event.subject)
1067 .await;
1068
1069 self.execute_session_revocation(session_id_str).await;
1071
1072 tracing::info!(
1073 "Session revocation completed for session: {} - all associated tokens invalidated",
1074 session_id_str
1075 );
1076 } else {
1077 tracing::info!("Revoking all sessions for subject: {}", event.subject);
1079 self.revoke_all_user_sessions(&event.subject).await;
1080 }
1081
1082 Ok(())
1083 }
1084
1085 async fn handle_account_disabled(&self, event: &SecurityEvent) -> Result<()> {
1086 tracing::info!("Handling account disabled for event: {}", event.event_id);
1087
1088 let reason = event
1090 .data
1091 .get("reason")
1092 .and_then(|v| v.as_str())
1093 .unwrap_or("Security event");
1094
1095 let disable_timestamp = event
1096 .data
1097 .get("disable_timestamp")
1098 .and_then(|v| v.as_str())
1099 .unwrap_or("immediate");
1100
1101 tracing::warn!(
1102 "Account disabled for subject: {} - Reason: {} - Timestamp: {}",
1103 event.subject,
1104 reason,
1105 disable_timestamp
1106 );
1107
1108 let disable_request = AccountDisableRequest {
1117 user_id: event.subject.clone(),
1118 reason: reason.to_string(),
1119 disable_timestamp: Utc::now(),
1120 initiated_by: "security_event_handler".to_string(),
1121 };
1122
1123 self.execute_account_disable(&disable_request).await?;
1125
1126 tracing::info!("Account successfully disabled for user: {}", event.subject);
1127
1128 Ok(())
1129 }
1130
1131 async fn execute_account_disable(&self, request: &AccountDisableRequest) -> Result<()> {
1133 tracing::info!("Executing account disable for user: {}", request.user_id);
1134
1135 self.revoke_all_user_sessions(&request.user_id).await;
1139 tracing::info!(
1140 "Revoked all active sessions for disabled user: {}",
1141 request.user_id
1142 );
1143
1144 self.notify_resource_servers_account_disabled(&request.user_id)
1146 .await?;
1147
1148 self.log_account_disable_audit(request).await?;
1150
1151 self.trigger_security_monitoring_alert(
1153 "account_disabled",
1154 &request.user_id,
1155 &request.reason,
1156 )
1157 .await?;
1158
1159 tracing::info!(
1161 "Account disable executed - User: {}, Reason: {}, Timestamp: {}",
1162 request.user_id,
1163 request.reason,
1164 request.disable_timestamp.to_rfc3339()
1165 );
1166
1167 Ok(())
1168 }
1169
1170 async fn notify_resource_servers_account_disabled(&self, user_id: &str) -> Result<()> {
1172 let _notification = serde_json::json!({
1173 "type": "account_disabled",
1174 "user_id": user_id,
1175 "timestamp": chrono::Utc::now().to_rfc3339(),
1176 "issuer": &self.config.endpoint_url,
1177 "action_required": "invalidate_user_tokens"
1178 });
1179
1180 let resource_servers = vec!["api.example.com", "app.example.com", "admin.example.com"];
1182 for server in resource_servers {
1183 tracing::debug!(
1184 "Notifying resource server {} about account disabled: {}",
1185 server,
1186 user_id
1187 );
1188 }
1190
1191 tracing::info!("Sent account disabled notifications for user: {}", user_id);
1192 Ok(())
1193 }
1194
1195 async fn log_account_disable_audit(&self, request: &AccountDisableRequest) -> Result<()> {
1197 let audit_entry = serde_json::json!({
1198 "event_type": "account_disabled",
1199 "user_id": request.user_id,
1200 "reason": &request.reason,
1201 "timestamp": chrono::Utc::now().to_rfc3339(),
1202 "source": "oidc_extensions",
1203 "severity": "high"
1204 });
1205
1206 tracing::warn!(
1207 "SECURITY AUDIT: Account disabled - User: {}, Reason: {}, Event: {}",
1208 request.user_id,
1209 request.reason,
1210 audit_entry
1211 );
1212
1213 Ok(())
1215 }
1216
1217 async fn trigger_security_monitoring_alert(
1219 &self,
1220 alert_type: &str,
1221 user_id: &str,
1222 reason: &str,
1223 ) -> Result<()> {
1224 let alert = serde_json::json!({
1225 "alert_type": alert_type,
1226 "severity": "high",
1227 "user_id": user_id,
1228 "reason": reason,
1229 "timestamp": chrono::Utc::now().to_rfc3339(),
1230 "source": "shared_signals_manager"
1231 });
1232
1233 tracing::error!(
1234 "SECURITY ALERT: {} - User: {}, Reason: {}, Details: {}",
1235 alert_type.to_uppercase(),
1236 user_id,
1237 reason,
1238 alert
1239 );
1240
1241 Ok(())
1243 }
1244
1245 async fn execute_session_revocation(&self, session_id: &str) {
1247 tracing::info!("Executing session revocation for session: {}", session_id);
1248
1249 tracing::info!(
1253 "Session revocation workflow completed for session: {} - all associated tokens and grants invalidated",
1254 session_id
1255 );
1256 }
1257
1258 async fn remove_session_from_store(&self, session_id: &str) -> Result<()> {
1260 tracing::debug!("Removing session {} from active sessions store", session_id);
1261
1262 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
1265
1266 tracing::info!("Session {} removed from active store", session_id);
1267 Ok(())
1268 }
1269
1270 async fn add_session_to_revocation_list(&self, session_id: &str) -> Result<()> {
1272 tracing::debug!("Adding session {} to revocation list", session_id);
1273
1274 let revocation_entry = serde_json::json!({
1277 "session_id": session_id,
1278 "revoked_at": chrono::Utc::now().to_rfc3339(),
1279 "reason": "security_event"
1280 });
1281
1282 tracing::info!(
1283 "Session {} added to revocation list: {}",
1284 session_id,
1285 revocation_entry
1286 );
1287 Ok(())
1288 }
1289
1290 async fn notify_resource_servers_session_revoked(&self, session_id: &str) -> Result<()> {
1292 tracing::debug!(
1293 "Notifying resource servers about session {} revocation",
1294 session_id
1295 );
1296
1297 let notification = serde_json::json!({
1300 "type": "session_revoked",
1301 "session_id": session_id,
1302 "timestamp": chrono::Utc::now().to_rfc3339(),
1303 "issuer": &self.config.endpoint_url
1304 });
1305
1306 let resource_servers = vec!["api.example.com", "app.example.com", "admin.example.com"];
1308 for server in resource_servers {
1309 tracing::info!(
1310 "Notified resource server {} of session revocation: {}",
1311 server,
1312 notification
1313 );
1314 tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
1316 }
1317
1318 Ok(())
1319 }
1320
1321 async fn log_session_revocation_audit(&self, session_id: &str, subject: &str) {
1323 let audit_event = serde_json::json!({
1324 "event_type": "session_revoked",
1325 "session_id": session_id,
1326 "subject": subject,
1327 "timestamp": chrono::Utc::now().to_rfc3339(),
1328 "initiator": "security_event_handler",
1329 "reason": "security_event_triggered"
1330 });
1331
1332 tracing::info!(target: "audit", "Session revocation audit: {}", audit_event);
1333
1334 }
1336
1337 async fn revoke_all_user_sessions(&self, subject: &str) {
1339 tracing::info!("Revoking all sessions for subject: {}", subject);
1340
1341 let audit_event = serde_json::json!({
1347 "event_type": "all_sessions_revoked",
1348 "subject": subject,
1349 "timestamp": chrono::Utc::now().to_rfc3339(),
1350 "reason": "security_event_fallback"
1351 });
1352
1353 tracing::info!(target: "audit", "All sessions revoked for user: {}", audit_event);
1354 }
1355
1356 async fn handle_credential_change(&self, event: &SecurityEvent) -> Result<()> {
1357 tracing::info!("Handling credential change for event: {}", event.event_id);
1358
1359 let credential_type = event
1360 .data
1361 .get("credential_type")
1362 .and_then(|v| v.as_str())
1363 .unwrap_or("unknown");
1364
1365 let change_type = event
1366 .data
1367 .get("change_type")
1368 .and_then(|v| v.as_str())
1369 .unwrap_or("update");
1370
1371 tracing::info!(
1372 "Credential change detected - Subject: {}, Type: {}, Change: {}",
1373 event.subject,
1374 credential_type,
1375 change_type
1376 );
1377
1378 match change_type {
1379 "password_change" => {
1380 if let Some(session_to_keep) = event.data.get("session_id") {
1382 tracing::info!(
1383 "Revoking all sessions except: {}",
1384 session_to_keep.as_str().unwrap_or("")
1385 );
1386 }
1387 }
1389 "mfa_enabled" => {
1390 tracing::info!(
1392 "MFA enabled for user: {} - security posture improved",
1393 event.subject
1394 );
1395 }
1396 "mfa_disabled" => {
1397 tracing::warn!(
1399 "MFA disabled for user: {} - consider security review",
1400 event.subject
1401 );
1402 }
1403 "recovery_codes_reset" => {
1404 tracing::info!("Recovery codes reset for user: {}", event.subject);
1406 }
1407 _ => {
1408 tracing::info!("General credential change for user: {}", event.subject);
1409 }
1410 }
1411
1412 Ok(())
1413 }
1414
1415 async fn handle_fraud_detection(&self, event: &SecurityEvent) -> Result<()> {
1416 log::info!("Handling fraud detection for event: {}", event.event_id);
1417 Ok(())
1419 }
1420
1421 pub async fn register_receiver(
1423 &self,
1424 receiver_id: String,
1425 receiver: SignalReceiver,
1426 ) -> Result<()> {
1427 let mut receivers = self.receivers.write().await;
1428 receivers.insert(receiver_id.clone(), receiver);
1429 log::info!("Signal receiver registered: {}", receiver_id);
1430 Ok(())
1431 }
1432
1433 pub async fn unregister_receiver(&self, receiver_id: &str) -> Result<()> {
1435 let mut receivers = self.receivers.write().await;
1436 if receivers.remove(receiver_id).is_some() {
1437 log::info!("Signal receiver unregistered: {}", receiver_id);
1438 Ok(())
1439 } else {
1440 Err(AuthError::auth_method(
1441 "shared_signals",
1442 "Receiver not found",
1443 ))
1444 }
1445 }
1446
1447 pub fn get_config(&self) -> &SharedSignalsConfig {
1449 &self.config
1450 }
1451
1452 pub fn is_event_type_supported(&self, event_type: &str) -> bool {
1454 self.config
1455 .supported_events
1456 .contains(&event_type.to_string())
1457 }
1458
1459 pub fn is_event_valid_age(&self, event: &SecurityEvent) -> bool {
1461 let now = chrono::Utc::now();
1462 let event_age = now.signed_duration_since(event.timestamp).num_seconds();
1463 event_age <= self.config.max_event_age
1464 }
1465
1466 pub async fn list_receivers(&self) -> Vec<String> {
1468 let receivers = self.receivers.read().await;
1469 receivers.keys().cloned().collect()
1470 }
1471}
1472
1473impl EkycManager {
1474 pub fn new(config: EkycConfig) -> Self {
1476 Self {
1477 config,
1478 verification_sessions: Arc::new(RwLock::new(HashMap::new())),
1479 }
1480 }
1481
1482 pub async fn handle_verification_request(&self, request: Value) -> Result<Value> {
1484 let user_id = request["user_id"]
1486 .as_str()
1487 .ok_or_else(|| AuthError::auth_method("ekyc", "Missing user_id"))?;
1488
1489 let requested_ial = request["requested_ial"]
1490 .as_str()
1491 .and_then(|s| s.parse::<u8>().ok())
1492 .unwrap_or(1);
1493
1494 if requested_ial < self.config.required_ial.clone() as u8 {
1496 return Err(AuthError::auth_method(
1497 "ekyc",
1498 "Insufficient identity assurance level",
1499 ));
1500 }
1501
1502 let session_id = Uuid::new_v4().to_string();
1504 let ekyc_session = EkycSession {
1505 session_id: session_id.clone(),
1506 user_id: user_id.to_string(),
1507 verification_status: VerificationStatus::Pending,
1508 achieved_ial: IdentityAssuranceLevel::from_u8(requested_ial),
1509 verification_results: HashMap::new(),
1510 };
1511
1512 let mut sessions = self.verification_sessions.write().await;
1514 sessions.insert(session_id.clone(), ekyc_session);
1515
1516 Ok(json!({
1517 "status": "verification_initiated",
1518 "session_id": session_id,
1519 "required_ial": requested_ial,
1520 "required_methods": self.config.verification_methods,
1521 "verification_endpoint": format!("/ekyc/verify/{}", session_id)
1522 }))
1523 }
1524
1525 pub async fn start_verification(&self, user_id: &str) -> Result<String> {
1527 let session_id = Uuid::new_v4().to_string();
1528
1529 let session = EkycSession {
1530 session_id: session_id.clone(),
1531 user_id: user_id.to_string(),
1532 verification_status: VerificationStatus::Pending,
1533 achieved_ial: IdentityAssuranceLevel::IAL1,
1534 verification_results: HashMap::new(),
1535 };
1536
1537 let mut sessions = self.verification_sessions.write().await;
1538 sessions.insert(session_id.clone(), session);
1539
1540 Ok(session_id)
1541 }
1542}
1543
1544impl FastFedManager {
1545 pub fn new(config: FastFedConfig) -> Self {
1547 Self {
1548 config,
1549 federations: Arc::new(RwLock::new(HashMap::new())),
1550 }
1551 }
1552
1553 pub async fn handle_federation_request(&self, request: Value) -> Result<Value> {
1555 let partner_org = request["partner_organization"]
1557 .as_str()
1558 .ok_or_else(|| AuthError::auth_method("fastfed", "Missing partner_organization"))?;
1559
1560 let federation_metadata = request["federation_metadata"]
1561 .as_object()
1562 .ok_or_else(|| AuthError::auth_method("fastfed", "Missing federation_metadata"))?;
1563
1564 if !self
1566 .config
1567 .trusted_partners
1568 .contains(&partner_org.to_string())
1569 {
1570 return Err(AuthError::auth_method(
1571 "fastfed",
1572 "Untrusted federation partner",
1573 ));
1574 }
1575
1576 let required_capabilities = ["oidc", "saml2", "scim"];
1578 for capability in required_capabilities {
1579 if !federation_metadata.contains_key(capability) {
1580 return Err(AuthError::auth_method(
1581 "fastfed",
1582 format!("Missing required capability: {}", capability),
1583 ));
1584 }
1585 }
1586
1587 let federation_id = if self.config.auto_provisioning {
1589 Some(self.establish_federation(partner_org).await?)
1590 } else {
1591 None
1592 };
1593
1594 Ok(json!({
1595 "status": "federation_request_accepted",
1596 "federation_id": federation_id,
1597 "auto_provisioning": self.config.auto_provisioning,
1598 "supported_protocols": self.config.supported_protocols,
1599 "next_steps": if federation_id.is_some() {
1600 "Federation automatically established"
1601 } else {
1602 "Manual federation approval required"
1603 }
1604 }))
1605 }
1606
1607 pub async fn establish_federation(&self, partner_org: &str) -> Result<String> {
1609 let relationship_id = Uuid::new_v4().to_string();
1610
1611 let relationship = FederationRelationship {
1612 relationship_id: relationship_id.clone(),
1613 partner_org: partner_org.to_string(),
1614 status: FederationStatus::Pending,
1615 config: json!({}),
1616 created_at: Utc::now(),
1617 };
1618
1619 let mut federations = self.federations.write().await;
1620 federations.insert(relationship_id.clone(), relationship);
1621
1622 Ok(relationship_id)
1623 }
1624}
1625
1626impl Default for OidcExtensionsConfig {
1629 fn default() -> Self {
1630 Self {
1631 enable_heart: true,
1632 enable_shared_signals: true,
1633 enable_ekyc: true,
1634 enable_fastfed: true,
1635 enable_modrna: false, enable_igov: false, enable_authzen: false, }
1639 }
1640}
1641
1642impl Default for HeartConfig {
1643 fn default() -> Self {
1644 Self {
1645 organization_id: "example-healthcare-org".to_string(),
1646 fhir_endpoint: "https://example.com/fhir".to_string(),
1647 required_scopes: vec!["patient/*.read".to_string(), "user/*.read".to_string()],
1648 enhanced_consent: true,
1649 authorized_providers: Vec::new(), audit_config: HeartAuditConfig::default(),
1651 }
1652 }
1653}
1654
1655impl Default for HeartAuditConfig {
1656 fn default() -> Self {
1657 Self {
1658 enable_atna: true,
1659 syslog_endpoint: None,
1660 audit_level: HeartAuditLevel::Enhanced,
1661 }
1662 }
1663}
1664
1665impl Default for SharedSignalsConfig {
1666 fn default() -> Self {
1667 Self {
1668 endpoint_url: "https://example.com/signals".to_string(),
1669 supported_events: vec![
1670 "security_advisory".to_string(),
1671 "account_disabled".to_string(),
1672 "credential_change".to_string(),
1673 "session_revoked".to_string(),
1674 ],
1675 max_event_age: 3600, verify_events: true,
1677 }
1678 }
1679}
1680
1681#[derive(Debug, Clone)]
1683pub struct VerificationSession {
1684 pub session_id: String,
1685 pub user_id: String,
1686 pub requested_ial: IdentityAssuranceLevel,
1687 pub status: String,
1688 pub required_methods: Vec<VerificationMethod>,
1689 pub completed_verifications: Vec<VerificationMethod>,
1690 pub created_at: SystemTime,
1691}
1692
1693impl IdentityAssuranceLevel {
1694 pub fn from_u8(level: u8) -> Self {
1695 match level {
1696 1 => IdentityAssuranceLevel::IAL1,
1697 2 => IdentityAssuranceLevel::IAL2,
1698 3 => IdentityAssuranceLevel::IAL3,
1699 _ => IdentityAssuranceLevel::IAL1,
1700 }
1701 }
1702}
1703
1704pub struct EventTransmitter {
1706 pub endpoint: String,
1707 pub public_key: String,
1708}
1709
1710impl EventTransmitter {
1711 pub async fn send_event(&self, event_jwt: &str, receiver_url: &str) -> Result<()> {
1712 log::info!("Sending event JWT to {}: {}", receiver_url, event_jwt);
1713 Ok(())
1715 }
1716}
1717
1718impl Default for EkycConfig {
1719 fn default() -> Self {
1720 Self {
1721 verification_provider: "example-kyc-provider".to_string(),
1722 required_ial: IdentityAssuranceLevel::IAL2,
1723 verification_methods: vec![VerificationMethod::Document, VerificationMethod::Database],
1724 document_verification: true,
1725 biometric_verification: false,
1726 }
1727 }
1728}
1729
1730impl Default for FastFedConfig {
1731 fn default() -> Self {
1732 Self {
1733 metadata_endpoint: "https://example.com/.well-known/fastfed".to_string(),
1734 supported_protocols: vec!["OIDC".to_string(), "SAML2".to_string()],
1735 auto_provisioning: false, trusted_partners: Vec::new(), trust_anchor: "example-trust-anchor".to_string(),
1738 }
1739 }
1740}
1741
1742#[cfg(test)]
1743mod tests {
1744 use super::*;
1745
1746 #[tokio::test]
1747 async fn test_oidc_extensions_creation() {
1748 let config = OidcExtensionsConfig::default();
1749
1750 assert!(config.enable_heart);
1752 assert!(config.enable_shared_signals);
1753 assert!(config.enable_ekyc);
1754 assert!(config.enable_fastfed);
1755
1756 assert!(!config.enable_modrna);
1758 assert!(!config.enable_igov);
1759 assert!(!config.enable_authzen);
1760 }
1761
1762 #[tokio::test]
1763 async fn test_heart_session_creation() {
1764 let config = HeartConfig::default();
1765 let heart_manager = HeartManager::new(config);
1766
1767 let session_id = heart_manager
1768 .create_session(
1769 "provider123",
1770 Some("patient456"),
1771 vec!["patient/*.read".to_string()],
1772 )
1773 .await
1774 .unwrap();
1775
1776 assert!(!session_id.is_empty());
1777 }
1778
1779 #[tokio::test]
1780 async fn test_ekyc_verification() {
1781 let config = EkycConfig::default();
1782 let ekyc_manager = EkycManager::new(config);
1783
1784 let session_id = ekyc_manager.start_verification("user123").await.unwrap();
1785
1786 assert!(!session_id.is_empty());
1787 }
1788
1789 #[tokio::test]
1790 async fn test_fastfed_federation() {
1791 let config = FastFedConfig::default();
1792 let fastfed_manager = FastFedManager::new(config);
1793
1794 let relationship_id = fastfed_manager
1795 .establish_federation("partner-org")
1796 .await
1797 .unwrap();
1798
1799 assert!(!relationship_id.is_empty());
1800 }
1801}
1802
1803