1use crate::errors::{AuthError, Result};
92use crate::server::oidc::oidc_session_management::SessionManager;
93use crate::server::token_exchange::token_exchange_common::{
94 ServiceComplexityLevel, TokenExchangeCapabilities, TokenExchangeService, TokenValidationResult,
95 ValidationUtils,
96};
97
98use async_trait::async_trait;
99use chrono::{DateTime, Duration, Utc};
100use jsonwebtoken::{DecodingKey, EncodingKey};
101use serde::{Deserialize, Serialize};
102use std::collections::{HashMap, HashSet};
103use std::str::FromStr;
104use std::sync::Arc;
105use uuid::Uuid;
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
109pub enum AuthLevel {
110 Basic = 1,
112 Mfa = 2,
114 High = 3,
116}
117
118impl FromStr for AuthLevel {
119 type Err = AuthError;
120
121 fn from_str(s: &str) -> Result<Self, Self::Err> {
122 match s.to_lowercase().as_str() {
123 "basic" => Ok(AuthLevel::Basic),
124 "mfa" => Ok(AuthLevel::Mfa),
125 "high" => Ok(AuthLevel::High),
126 _ => Err(AuthError::InvalidRequest(format!(
127 "Invalid auth level: {}",
128 s
129 ))),
130 }
131 }
132}
133
134impl std::fmt::Display for AuthLevel {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 let level_str = match self {
137 AuthLevel::Basic => "basic",
138 AuthLevel::Mfa => "mfa",
139 AuthLevel::High => "high",
140 };
141 write!(f, "{}", level_str)
142 }
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct AdvancedTokenExchangeConfig {
148 pub enable_multi_party_chains: bool,
150
151 pub max_delegation_depth: usize,
153
154 pub require_audit_trail: bool,
156
157 pub enable_context_preservation: bool,
159
160 pub default_token_lifetime: Duration,
162
163 pub supported_subject_token_types: Vec<String>,
165
166 pub supported_requested_token_types: Vec<String>,
168
169 pub exchange_policies: Vec<TokenExchangePolicy>,
171
172 pub cross_domain_settings: CrossDomainExchangeSettings,
174
175 pub jwt_signing_key: String,
177
178 pub jwt_verification_key: String,
180
181 pub trusted_issuers: Vec<String>,
183}
184
185impl Default for AdvancedTokenExchangeConfig {
186 fn default() -> Self {
187 Self {
188 enable_multi_party_chains: true,
189 max_delegation_depth: 3,
190 require_audit_trail: true,
191 enable_context_preservation: true,
192 default_token_lifetime: Duration::try_hours(1).unwrap_or(Duration::zero()),
193 supported_subject_token_types: vec![
194 "urn:ietf:params:oauth:token-type:jwt".to_string(),
195 "urn:ietf:params:oauth:token-type:access_token".to_string(),
196 "urn:ietf:params:oauth:token-type:refresh_token".to_string(),
197 "urn:ietf:params:oauth:token-type:id_token".to_string(),
198 "urn:ietf:params:oauth:token-type:saml2".to_string(),
199 ],
200 supported_requested_token_types: vec![
201 "urn:ietf:params:oauth:token-type:jwt".to_string(),
202 "urn:ietf:params:oauth:token-type:access_token".to_string(),
203 "urn:ietf:params:oauth:token-type:refresh_token".to_string(),
204 ],
205 exchange_policies: Vec::new(),
206 cross_domain_settings: CrossDomainExchangeSettings::default(),
207 jwt_signing_key: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA...".to_string(), jwt_verification_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0B...".to_string(), trusted_issuers: vec![
210 "https://auth.example.com".to_string(),
211 "https://login.example.org".to_string(),
212 ],
213 }
214 }
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct AdvancedTokenExchangeRequest {
220 pub grant_type: String,
222
223 pub subject_token: String,
225
226 pub subject_token_type: String,
228
229 pub actor_token: Option<String>,
231
232 pub actor_token_type: Option<String>,
234
235 pub requested_token_type: String,
237
238 pub scope: Option<String>,
240
241 pub audience: Vec<String>,
243
244 pub resource: Vec<String>,
246
247 pub exchange_context: Option<ExchangeContext>,
249
250 pub policy_requirements: Vec<String>,
252
253 pub custom_parameters: HashMap<String, serde_json::Value>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct ExchangeContext {
260 pub transaction_id: String,
262
263 pub business_context: serde_json::Value,
265
266 pub delegation_chain: Vec<DelegationLink>,
268
269 pub original_request: Option<RequestMetadata>,
271
272 pub security_context: Option<SecurityContext>,
274
275 pub custom_fields: HashMap<String, serde_json::Value>,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct DelegationLink {
282 pub delegator: String,
284
285 pub delegatee: String,
287
288 pub delegated_at: DateTime<Utc>,
290
291 pub delegation_reason: String,
293
294 pub delegated_scopes: Vec<String>,
296
297 pub restrictions: Vec<DelegationRestriction>,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
303#[serde(tag = "type", rename_all = "snake_case")]
304pub enum DelegationRestriction {
305 TimeLimit { expires_at: DateTime<Utc> },
307
308 UsageLimit { max_uses: u32, current_uses: u32 },
310
311 IpRestriction { allowed_ips: Vec<String> },
313
314 ScopeRestriction { restricted_scopes: Vec<String> },
316
317 Custom {
319 restriction_type: String,
320 parameters: HashMap<String, serde_json::Value>,
321 },
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
326pub struct RequestMetadata {
327 pub client_id: String,
329
330 pub user_agent: Option<String>,
332
333 pub ip_address: Option<String>,
335
336 pub timestamp: DateTime<Utc>,
338
339 pub headers: HashMap<String, String>,
341}
342
343#[derive(Debug, Clone, Serialize, Deserialize)]
345pub struct SecurityContext {
346 pub session_id: Option<String>,
348
349 pub authentication_level: String,
351
352 pub mfa_completed: bool,
354
355 pub risk_score: f64,
357
358 pub device_info: Option<DeviceContext>,
360
361 pub location_info: Option<LocationContext>,
363}
364
365#[derive(Debug, Clone, Serialize, Deserialize)]
367pub struct DeviceContext {
368 pub device_id: String,
370
371 pub device_type: String,
373
374 pub trust_level: String,
376
377 pub fingerprint: Option<String>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct LocationContext {
384 pub country: Option<String>,
386
387 pub city: Option<String>,
389
390 pub geo_data: Option<serde_json::Value>,
392
393 pub network_info: Option<String>,
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct TokenExchangePolicy {
400 pub id: String,
402
403 pub name: String,
405
406 pub conditions: Vec<PolicyCondition>,
408
409 pub actions: Vec<PolicyAction>,
411
412 pub mandatory: bool,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
418#[serde(tag = "type", rename_all = "snake_case")]
419pub enum PolicyCondition {
420 SubjectTokenType { allowed_types: Vec<String> },
422
423 ScopeRequirement {
425 required_scopes: Vec<String>,
426 all_required: bool,
427 },
428
429 DelegationDepth { max_depth: usize },
431
432 ClientAuthorization { authorized_clients: Vec<String> },
434
435 TimeRestriction {
437 allowed_hours: Vec<u8>,
438 timezone: String,
439 },
440
441 Custom {
443 condition_type: String,
444 parameters: HashMap<String, serde_json::Value>,
445 },
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
450#[serde(tag = "type", rename_all = "snake_case")]
451pub enum PolicyAction {
452 Allow,
454
455 Deny { reason: String },
457
458 RequireStepUp { required_level: String },
460
461 RestrictScopes { allowed_scopes: Vec<String> },
463
464 RestrictLifetime { max_lifetime: Duration },
466
467 Custom {
469 action_type: String,
470 parameters: HashMap<String, serde_json::Value>,
471 },
472}
473
474#[derive(Debug, Clone, Serialize, Deserialize)]
476pub struct CrossDomainExchangeSettings {
477 pub enabled: bool,
479
480 pub trusted_domains: Vec<String>,
482
483 pub cross_domain_policies: Vec<CrossDomainPolicy>,
485
486 pub require_domain_validation: bool,
488}
489
490impl Default for CrossDomainExchangeSettings {
491 fn default() -> Self {
492 Self {
493 enabled: false,
494 trusted_domains: Vec::new(),
495 cross_domain_policies: Vec::new(),
496 require_domain_validation: true,
497 }
498 }
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize)]
503pub struct CrossDomainPolicy {
504 pub id: String,
506
507 pub source_domain: String,
509
510 pub target_domain: String,
512
513 pub allowed_token_types: Vec<String>,
515
516 pub required_claims: Vec<String>,
518
519 pub scope_mappings: HashMap<String, String>,
521}
522
523#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct AdvancedTokenExchangeResponse {
526 pub access_token: String,
528
529 pub issued_token_type: String,
531
532 pub token_type: String,
534
535 pub expires_in: Option<u64>,
537
538 pub scope: Option<String>,
540
541 pub refresh_token: Option<String>,
543
544 pub exchange_audit: Option<ExchangeAuditInfo>,
546
547 pub preserved_context: Option<ExchangeContext>,
549
550 pub additional_parameters: HashMap<String, serde_json::Value>,
552}
553
554#[derive(Debug, Clone, Serialize, Deserialize)]
556pub struct ExchangeAuditInfo {
557 pub exchange_id: Uuid,
559
560 pub timestamp: DateTime<Utc>,
562
563 pub exchange_type: TokenExchangeType,
565
566 pub subject_info: SubjectInfo,
568
569 pub actor_info: Option<ActorInfo>,
571
572 pub policy_decisions: Vec<PolicyDecision>,
574
575 pub security_assessments: Vec<SecurityAssessment>,
577}
578
579#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
581#[serde(rename_all = "snake_case")]
582pub enum TokenExchangeType {
583 Impersonation,
585
586 Delegation,
588
589 Translation,
591
592 ContextExchange,
594
595 Federation,
597
598 PrivilegeEscalation,
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct SubjectInfo {
605 pub subject: String,
607
608 pub subject_type: String,
610
611 pub original_token_info: TokenInfo,
613
614 pub attributes: HashMap<String, serde_json::Value>,
616}
617
618#[derive(Debug, Clone, Serialize, Deserialize)]
620pub struct ActorInfo {
621 pub actor: String,
623
624 pub actor_type: String,
626
627 pub actor_token_info: TokenInfo,
629
630 pub attributes: HashMap<String, serde_json::Value>,
632}
633
634#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct TokenInfo {
637 pub token_type: String,
639
640 pub issuer: String,
642
643 pub audience: Vec<String>,
645
646 pub scopes: Vec<String>,
648
649 pub expires_at: Option<DateTime<Utc>>,
651
652 pub metadata: HashMap<String, serde_json::Value>,
654}
655
656#[derive(Debug, Clone, Serialize, Deserialize)]
658pub struct PolicyDecision {
659 pub policy_id: String,
661
662 pub decision: PolicyDecisionResult,
664
665 pub reason: String,
667
668 pub applied_modifications: Vec<String>,
670}
671
672#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
674#[serde(rename_all = "snake_case")]
675pub enum PolicyDecisionResult {
676 Allow,
678
679 Deny,
681
682 Modify,
684
685 RequireVerification,
687}
688
689#[derive(Debug, Clone, Serialize, Deserialize)]
691pub struct SecurityAssessment {
692 pub assessment_type: String,
694
695 pub result: SecurityAssessmentResult,
697
698 pub risk_score: f64,
700
701 pub details: HashMap<String, serde_json::Value>,
703}
704
705#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
707#[serde(rename_all = "snake_case")]
708pub enum SecurityAssessmentResult {
709 Pass,
711
712 Fail,
714
715 RequiresReview,
717
718 Inconclusive,
720}
721
722#[async_trait]
724pub trait TokenExchangeProcessor: Send + Sync {
725 async fn process_exchange(
727 &self,
728 request: &AdvancedTokenExchangeRequest,
729 context: &ExchangeContext,
730 ) -> Result<AdvancedTokenExchangeResponse>;
731
732 async fn validate_subject_token(&self, token: &str, token_type: &str) -> Result<TokenInfo>;
734
735 async fn validate_actor_token(&self, token: &str, token_type: &str) -> Result<TokenInfo>;
737
738 async fn generate_exchanged_token(
740 &self,
741 subject_info: &SubjectInfo,
742 actor_info: Option<&ActorInfo>,
743 request: &AdvancedTokenExchangeRequest,
744 ) -> Result<String>;
745}
746
747pub struct AdvancedTokenExchangeManager {
749 config: AdvancedTokenExchangeConfig,
751
752 session_manager: Arc<SessionManager>,
754
755 processors: HashMap<String, Arc<dyn TokenExchangeProcessor>>,
757
758 exchange_audit: Arc<tokio::sync::RwLock<Vec<ExchangeAuditInfo>>>,
760
761 encoding_key: EncodingKey,
763
764 decoding_key: DecodingKey,
766}
767
768impl AdvancedTokenExchangeManager {
769 pub fn new(
771 config: AdvancedTokenExchangeConfig,
772 session_manager: Arc<SessionManager>,
773 ) -> Result<Self> {
774 let encoding_key = EncodingKey::from_rsa_pem(config.jwt_signing_key.as_bytes())?;
776 let decoding_key = DecodingKey::from_rsa_pem(config.jwt_verification_key.as_bytes())?;
777
778 Ok(Self {
779 config,
780 session_manager,
781 processors: HashMap::new(),
782 exchange_audit: Arc::new(tokio::sync::RwLock::new(Vec::new())),
783 encoding_key,
784 decoding_key,
785 })
786 }
787
788 pub fn register_processor(
790 &mut self,
791 token_type: String,
792 processor: Arc<dyn TokenExchangeProcessor>,
793 ) {
794 self.processors.insert(token_type, processor);
795 }
796
797 pub async fn exchange_token(
799 &self,
800 request: AdvancedTokenExchangeRequest,
801 ) -> Result<AdvancedTokenExchangeResponse> {
802 self.validate_exchange_request(&request).await?;
804
805 let context = request
807 .exchange_context
808 .clone()
809 .unwrap_or_else(|| ExchangeContext {
810 transaction_id: Uuid::new_v4().to_string(),
811 business_context: serde_json::Value::Null,
812 delegation_chain: Vec::new(),
813 original_request: None,
814 security_context: None,
815 custom_fields: HashMap::new(),
816 });
817
818 if context.delegation_chain.len() > self.config.max_delegation_depth {
820 return Err(AuthError::InvalidRequest(
821 "Maximum delegation depth exceeded".to_string(),
822 ));
823 }
824
825 self.apply_exchange_policies(&request, &context).await?;
827
828 let subject_info = self.validate_and_extract_subject_info(&request).await?;
830
831 let actor_info = if request.actor_token.is_some() {
833 Some(self.validate_and_extract_actor_info(&request).await?)
834 } else {
835 None
836 };
837
838 let exchange_type = self.determine_exchange_type(&request, &subject_info, &actor_info);
840
841 let processor = self.get_processor(&request.requested_token_type)?;
843 let mut response = processor.process_exchange(&request, &context).await?;
844
845 let audit_info = self
847 .create_audit_info(
848 exchange_type,
849 &subject_info,
850 &actor_info,
851 &request,
852 &context,
853 )
854 .await?;
855
856 {
858 let mut audit_log = self.exchange_audit.write().await;
859 audit_log.push(audit_info.clone());
860 }
861
862 if self.config.require_audit_trail {
864 response.exchange_audit = Some(audit_info.clone());
865
866 let audit_token = self.generate_audit_token(&audit_info)?;
868 response.additional_parameters.insert(
869 "audit_token".to_string(),
870 serde_json::Value::String(audit_token),
871 );
872 }
873
874 if self.config.enable_context_preservation {
876 let preserved_context = context.clone();
877 response.preserved_context = Some(preserved_context.clone());
878
879 let delegation_token = self.generate_delegation_token(&preserved_context)?;
881 response.additional_parameters.insert(
882 "delegation_token".to_string(),
883 serde_json::Value::String(delegation_token),
884 );
885 }
886
887 Ok(response)
888 }
889
890 pub async fn get_exchange_audit(&self) -> Vec<ExchangeAuditInfo> {
892 let audit_log = self.exchange_audit.read().await;
893 audit_log.clone()
894 }
895
896 async fn validate_exchange_request(
898 &self,
899 request: &AdvancedTokenExchangeRequest,
900 ) -> Result<()> {
901 if request.grant_type != "urn:ietf:params:oauth:grant-type:token-exchange" {
903 return Err(AuthError::InvalidRequest(
904 "Invalid grant type for token exchange".to_string(),
905 ));
906 }
907
908 if !self
910 .config
911 .supported_subject_token_types
912 .contains(&request.subject_token_type)
913 {
914 return Err(AuthError::InvalidRequest(format!(
915 "Unsupported subject token type: {}",
916 request.subject_token_type
917 )));
918 }
919
920 if !self
922 .config
923 .supported_requested_token_types
924 .contains(&request.requested_token_type)
925 {
926 return Err(AuthError::InvalidRequest(format!(
927 "Unsupported requested token type: {}",
928 request.requested_token_type
929 )));
930 }
931
932 if let Some(ref actor_token_type) = request.actor_token_type
934 && !self
935 .config
936 .supported_subject_token_types
937 .contains(actor_token_type)
938 {
939 return Err(AuthError::InvalidRequest(format!(
940 "Unsupported actor token type: {}",
941 actor_token_type
942 )));
943 }
944
945 Ok(())
946 }
947
948 async fn apply_exchange_policies(
950 &self,
951 request: &AdvancedTokenExchangeRequest,
952 context: &ExchangeContext,
953 ) -> Result<()> {
954 if request.subject_token_type == "urn:ietf:params:oauth:token-type:jwt" {
956 match self.introspect_jwt_token(&request.subject_token) {
957 Ok(token_claims) => {
958 if let Some(iss) = token_claims.get("iss").and_then(|v| v.as_str())
960 && !self.config.trusted_issuers.contains(&iss.to_string())
961 {
962 return Err(AuthError::InvalidRequest(format!(
963 "Token issued by untrusted issuer: {}",
964 iss
965 )));
966 }
967 }
968 Err(_) => {
969 }
972 }
973 }
974
975 for policy in &self.config.exchange_policies {
976 let policy_applies = self.evaluate_policy_conditions(policy, request, context)?;
977
978 if policy_applies {
979 for action in &policy.actions {
980 match action {
981 PolicyAction::Deny { reason } => {
982 return Err(AuthError::InvalidRequest(format!(
983 "Exchange denied by policy '{}': {}",
984 policy.name, reason
985 )));
986 }
987 PolicyAction::RequireStepUp { required_level } => {
988 let auth_level = required_level.parse::<AuthLevel>().map_err(|_| {
990 AuthError::InvalidRequest(format!(
991 "Invalid authentication level: {}",
992 required_level
993 ))
994 })?;
995 return self
996 .handle_step_up_authentication(auth_level, context)
997 .await;
998 }
999 _ => {
1000 }
1002 }
1003 }
1004 }
1005 }
1006
1007 Ok(())
1008 }
1009
1010 fn evaluate_policy_conditions(
1012 &self,
1013 policy: &TokenExchangePolicy,
1014 request: &AdvancedTokenExchangeRequest,
1015 context: &ExchangeContext,
1016 ) -> Result<bool> {
1017 for condition in &policy.conditions {
1018 match condition {
1019 PolicyCondition::SubjectTokenType { allowed_types } => {
1020 if !allowed_types.contains(&request.subject_token_type) {
1021 return Ok(false);
1022 }
1023 }
1024 PolicyCondition::DelegationDepth { max_depth } => {
1025 if context.delegation_chain.len() > *max_depth {
1026 return Ok(false);
1027 }
1028 }
1029 PolicyCondition::ScopeRequirement {
1030 required_scopes,
1031 all_required,
1032 } => {
1033 if let Some(ref scope) = request.scope {
1034 let request_scopes: HashSet<&str> = scope.split(' ').collect();
1035 let required: HashSet<&str> =
1036 required_scopes.iter().map(|s| s.as_str()).collect();
1037
1038 if *all_required {
1039 if !required.is_subset(&request_scopes) {
1040 return Ok(false);
1041 }
1042 } else if required.is_disjoint(&request_scopes) {
1043 return Ok(false);
1044 }
1045 }
1046 }
1047 _ => {
1048 }
1050 }
1051 }
1052
1053 Ok(true)
1054 }
1055
1056 async fn validate_and_extract_subject_info(
1058 &self,
1059 request: &AdvancedTokenExchangeRequest,
1060 ) -> Result<SubjectInfo> {
1061 let processor = self.get_processor(&request.subject_token_type)?;
1062 let token_info = processor
1063 .validate_subject_token(&request.subject_token, &request.subject_token_type)
1064 .await?;
1065
1066 Ok(SubjectInfo {
1067 subject: token_info
1068 .metadata
1069 .get("sub")
1070 .and_then(|v| v.as_str())
1071 .unwrap_or("unknown")
1072 .to_string(),
1073 subject_type: "user".to_string(), original_token_info: token_info,
1075 attributes: HashMap::new(),
1076 })
1077 }
1078
1079 async fn validate_and_extract_actor_info(
1081 &self,
1082 request: &AdvancedTokenExchangeRequest,
1083 ) -> Result<ActorInfo> {
1084 let actor_token = request.actor_token.as_ref().unwrap();
1085 let actor_token_type = request.actor_token_type.as_ref().unwrap();
1086
1087 let processor = self.get_processor(actor_token_type)?;
1088 let token_info = processor
1089 .validate_actor_token(actor_token, actor_token_type)
1090 .await?;
1091
1092 Ok(ActorInfo {
1093 actor: token_info
1094 .metadata
1095 .get("sub")
1096 .and_then(|v| v.as_str())
1097 .unwrap_or("unknown")
1098 .to_string(),
1099 actor_type: "service".to_string(), actor_token_info: token_info,
1101 attributes: HashMap::new(),
1102 })
1103 }
1104
1105 fn determine_exchange_type(
1107 &self,
1108 request: &AdvancedTokenExchangeRequest,
1109 _subject_info: &SubjectInfo,
1110 actor_info: &Option<ActorInfo>,
1111 ) -> TokenExchangeType {
1112 if actor_info.is_some() {
1113 TokenExchangeType::Delegation
1114 } else if request.exchange_context.is_some() {
1115 TokenExchangeType::ContextExchange
1116 } else if request.subject_token_type != request.requested_token_type {
1117 TokenExchangeType::Translation
1118 } else {
1119 TokenExchangeType::Impersonation
1120 }
1121 }
1122
1123 fn get_processor(&self, token_type: &str) -> Result<Arc<dyn TokenExchangeProcessor>> {
1125 self.processors.get(token_type).cloned().ok_or_else(|| {
1126 AuthError::InvalidRequest(format!(
1127 "No processor registered for token type: {}",
1128 token_type
1129 ))
1130 })
1131 }
1132
1133 async fn create_audit_info(
1135 &self,
1136 exchange_type: TokenExchangeType,
1137 _subject_info: &SubjectInfo,
1138 actor_info: &Option<ActorInfo>,
1139 _request: &AdvancedTokenExchangeRequest,
1140 _context: &ExchangeContext,
1141 ) -> Result<ExchangeAuditInfo> {
1142 Ok(ExchangeAuditInfo {
1143 exchange_id: Uuid::new_v4(),
1144 timestamp: Utc::now(),
1145 exchange_type,
1146 subject_info: _subject_info.clone(),
1147 actor_info: actor_info.clone(),
1148 policy_decisions: Vec::new(), security_assessments: Vec::new(), })
1151 }
1152
1153 pub async fn cleanup_old_audit_entries(&self, older_than: DateTime<Utc>) -> usize {
1155 let mut audit_log = self.exchange_audit.write().await;
1156 let original_len = audit_log.len();
1157
1158 audit_log.retain(|entry| entry.timestamp > older_than);
1159
1160 original_len - audit_log.len()
1161 }
1162
1163 pub fn generate_audit_token(&self, audit_info: &ExchangeAuditInfo) -> Result<String> {
1165 use jsonwebtoken::{Algorithm, Header, encode};
1166 use serde_json::json;
1167
1168 let header = Header::new(Algorithm::HS256);
1169
1170 let claims = json!({
1171 "iss": "advanced-token-exchange",
1172 "sub": audit_info.subject_info.subject,
1173 "aud": "audit-verification",
1174 "exp": (Utc::now() + Duration::seconds(3600)).timestamp(),
1175 "iat": Utc::now().timestamp(),
1176 "exchange_id": audit_info.exchange_id,
1177 "exchange_type": audit_info.exchange_type,
1178 "timestamp": audit_info.timestamp,
1179 "policy_decisions": audit_info.policy_decisions.len(),
1180 "security_assessments": audit_info.security_assessments.len()
1181 });
1182
1183 encode(&header, &claims, &self.encoding_key).map_err(|e| {
1184 AuthError::TokenGeneration(format!("Failed to generate audit token: {}", e))
1185 })
1186 }
1187
1188 pub fn validate_delegation_token(&self, token: &str) -> Result<serde_json::Value> {
1190 use jsonwebtoken::{Algorithm, Validation, decode};
1191
1192 let mut validation = Validation::new(Algorithm::HS256);
1193 validation.set_audience(&["delegation-context"]);
1194 validation.set_issuer(&["advanced-token-exchange"]);
1195
1196 let token_data = decode::<serde_json::Value>(token, &self.decoding_key, &validation)
1197 .map_err(|e| AuthError::InvalidToken(format!("Invalid delegation token: {}", e)))?;
1198
1199 Ok(token_data.claims)
1200 }
1201
1202 pub fn generate_delegation_token(&self, context: &ExchangeContext) -> Result<String> {
1204 use jsonwebtoken::{Algorithm, Header, encode};
1205 use serde_json::json;
1206
1207 let header = Header::new(Algorithm::RS256);
1208
1209 let claims = json!({
1210 "iss": "advanced-token-exchange",
1211 "aud": "delegation-context",
1212 "exp": (Utc::now() + Duration::seconds(1800)).timestamp(), "iat": Utc::now().timestamp(),
1214 "transaction_id": context.transaction_id,
1215 "delegation_chain_length": context.delegation_chain.len(),
1216 "delegation_chain": context.delegation_chain,
1217 "business_context": context.business_context,
1218 "custom_fields": context.custom_fields
1219 });
1220
1221 encode(&header, &claims, &self.encoding_key).map_err(|e| {
1222 AuthError::TokenGeneration(format!("Failed to generate delegation token: {}", e))
1223 })
1224 }
1225
1226 pub fn introspect_jwt_token(&self, token: &str) -> Result<serde_json::Value> {
1228 use jsonwebtoken::{Algorithm, Validation, decode};
1229
1230 let mut validation = Validation::new(Algorithm::RS256);
1231 validation.insecure_disable_signature_validation(); let token_data = decode::<serde_json::Value>(token, &self.decoding_key, &validation)
1234 .map_err(|e| AuthError::InvalidToken(format!("Token introspection failed: {}", e)))?;
1235
1236 Ok(token_data.claims)
1237 }
1238
1239 async fn handle_step_up_authentication(
1241 &self,
1242 required_level: AuthLevel,
1243 context: &ExchangeContext,
1244 ) -> Result<()> {
1245 if let Some(session_id) = context
1247 .security_context
1248 .as_ref()
1249 .and_then(|sc| sc.session_id.as_ref())
1250 {
1251 match self.session_manager.get_session(session_id) {
1253 Some(session) => {
1254 if let Some(current_level) = session
1256 .metadata
1257 .get("auth_level")
1258 .map(|v| v.as_str())
1259 .and_then(|s| s.parse::<AuthLevel>().ok())
1260 && current_level >= required_level
1261 {
1262 return Ok(());
1264 }
1265
1266 Err(AuthError::StepUpRequired {
1268 current_level: session
1269 .metadata
1270 .get("auth_level")
1271 .map(|v| v.as_str())
1272 .unwrap_or("basic")
1273 .to_string(),
1274 required_level: required_level.to_string(),
1275 step_up_url: format!(
1276 "/auth/step-up?session_id={}&level={}",
1277 session_id, required_level
1278 ),
1279 })
1280 }
1281 None => {
1282 Err(AuthError::Unauthorized(
1284 "No active session found".to_string(),
1285 ))
1286 }
1287 }
1288 } else {
1289 Err(AuthError::Unauthorized(
1291 "No session context available".to_string(),
1292 ))
1293 }
1294 }
1295}
1296
1297#[async_trait]
1299impl TokenExchangeService for AdvancedTokenExchangeManager {
1300 type Request = AdvancedTokenExchangeRequest;
1301 type Response = AdvancedTokenExchangeResponse;
1302 type Config = AdvancedTokenExchangeConfig;
1303
1304 async fn exchange_token(&self, request: Self::Request) -> Result<Self::Response> {
1306 self.exchange_token(request).await
1307 }
1308
1309 async fn validate_token(&self, token: &str, token_type: &str) -> Result<TokenValidationResult> {
1311 let supported_types = self.supported_subject_token_types();
1313 ValidationUtils::validate_token_type(token_type, &supported_types)?;
1314
1315 if ValidationUtils::is_jwt_token_type(token_type) {
1317 match self.introspect_jwt_token(token) {
1318 Ok(claims) => {
1319 let subject = ValidationUtils::extract_subject(
1321 &claims
1322 .as_object()
1323 .unwrap_or(&serde_json::Map::new())
1324 .iter()
1325 .map(|(k, v)| (k.clone(), v.clone()))
1326 .collect(),
1327 );
1328
1329 let scopes = ValidationUtils::extract_scopes(
1330 &claims
1331 .as_object()
1332 .unwrap_or(&serde_json::Map::new())
1333 .iter()
1334 .map(|(k, v)| (k.clone(), v.clone()))
1335 .collect(),
1336 None,
1337 );
1338
1339 Ok(TokenValidationResult {
1340 is_valid: true,
1341 subject,
1342 issuer: claims
1343 .get("iss")
1344 .and_then(|v| v.as_str())
1345 .map(|s| s.to_string()),
1346 audience: claims
1347 .get("aud")
1348 .and_then(|v| v.as_str())
1349 .map(|s| vec![s.to_string()])
1350 .unwrap_or_default(),
1351 scopes,
1352 expires_at: claims.get("exp").and_then(|v| v.as_i64()).and_then(|exp| {
1353 use chrono::{TimeZone, Utc};
1354 Utc.timestamp_opt(exp, 0).single()
1355 }),
1356 metadata: claims
1357 .as_object()
1358 .unwrap_or(&serde_json::Map::new())
1359 .iter()
1360 .map(|(k, v)| (k.clone(), v.clone()))
1361 .collect(),
1362 validation_messages: Vec::new(),
1363 })
1364 }
1365 Err(e) => Ok(TokenValidationResult {
1366 is_valid: false,
1367 subject: None,
1368 issuer: None,
1369 audience: Vec::new(),
1370 scopes: Vec::new(),
1371 expires_at: None,
1372 metadata: std::collections::HashMap::new(),
1373 validation_messages: vec![format!("JWT validation failed: {}", e)],
1374 }),
1375 }
1376 } else {
1377 Ok(TokenValidationResult {
1379 is_valid: true, subject: None,
1381 issuer: None,
1382 audience: Vec::new(),
1383 scopes: Vec::new(),
1384 expires_at: None,
1385 metadata: std::collections::HashMap::new(),
1386 validation_messages: vec![format!(
1387 "Basic validation for token type: {}",
1388 token_type
1389 )],
1390 })
1391 }
1392 }
1393
1394 fn supported_subject_token_types(&self) -> Vec<String> {
1396 self.config.supported_subject_token_types.clone()
1397 }
1398
1399 fn supported_requested_token_types(&self) -> Vec<String> {
1401 self.config.supported_requested_token_types.clone()
1402 }
1403
1404 fn capabilities(&self) -> TokenExchangeCapabilities {
1406 TokenExchangeCapabilities {
1407 basic_exchange: true,
1408 multi_party_chains: self.config.enable_multi_party_chains,
1409 context_preservation: self.config.enable_context_preservation,
1410 audit_trail: self.config.require_audit_trail,
1411 session_integration: true, jwt_operations: true, policy_control: true, cross_domain_exchange: self.config.cross_domain_settings.enabled,
1415 max_delegation_depth: self.config.max_delegation_depth,
1416 complexity_level: ServiceComplexityLevel::Advanced,
1417 }
1418 }
1419}
1420
1421#[cfg(test)]
1422mod tests {
1423 use super::*;
1424
1425 #[tokio::test]
1426 async fn test_config_creation() {
1427 let config = AdvancedTokenExchangeConfig::default();
1428 assert!(config.enable_multi_party_chains);
1429 assert!(!config.supported_subject_token_types.is_empty());
1430 assert!(!config.supported_requested_token_types.is_empty());
1431 assert!(!config.trusted_issuers.is_empty());
1432 }
1433
1434 #[test]
1435 fn test_jwt_key_functionality() {
1436 use crate::server::oidc::oidc_session_management::SessionManager;
1437 use jsonwebtoken::{DecodingKey, EncodingKey};
1438
1439 let secret = b"test-secret-key-32-bytes-minimum!";
1441 let encoding_key = EncodingKey::from_secret(secret);
1442 let decoding_key = DecodingKey::from_secret(secret);
1443
1444 let config = AdvancedTokenExchangeConfig {
1445 jwt_signing_key: "test-secret-key-32-bytes-minimum!".to_string(),
1446 jwt_verification_key: "test-secret-key-32-bytes-minimum!".to_string(),
1447 ..Default::default()
1448 };
1449
1450 let session_manager = Arc::new(SessionManager::new(Default::default()));
1451
1452 let manager = AdvancedTokenExchangeManager {
1454 config,
1455 session_manager,
1456 processors: HashMap::new(),
1457 exchange_audit: Arc::new(tokio::sync::RwLock::new(Vec::new())),
1458 encoding_key,
1459 decoding_key,
1460 };
1461
1462 let audit_info = ExchangeAuditInfo {
1464 exchange_id: Uuid::new_v4(),
1465 timestamp: Utc::now(),
1466 exchange_type: TokenExchangeType::Delegation,
1467 subject_info: SubjectInfo {
1468 subject: "test_user".to_string(),
1469 subject_type: "user".to_string(),
1470 original_token_info: TokenInfo {
1471 token_type: "jwt".to_string(),
1472 issuer: "test".to_string(),
1473 audience: vec!["test".to_string()],
1474 scopes: vec!["read".to_string()],
1475 expires_at: None,
1476 metadata: HashMap::new(),
1477 },
1478 attributes: HashMap::new(),
1479 },
1480 actor_info: None,
1481 policy_decisions: Vec::new(),
1482 security_assessments: Vec::new(),
1483 };
1484
1485 let result = manager.generate_audit_token(&audit_info);
1487 assert!(
1488 result.is_ok(),
1489 "JWT keys should be properly initialized for signing"
1490 );
1491 }
1492
1493 #[test]
1494 fn test_exchange_request_creation() {
1495 let request = AdvancedTokenExchangeRequest {
1496 grant_type: "urn:ietf:params:oauth:grant-type:token-exchange".to_string(),
1497 subject_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9".to_string(),
1498 subject_token_type: "urn:ietf:params:oauth:token-type:jwt".to_string(),
1499 requested_token_type: "urn:ietf:params:oauth:token-type:access_token".to_string(),
1500 actor_token: None,
1501 actor_token_type: None,
1502 scope: Some("read write".to_string()),
1503 audience: vec!["https://api.example.com".to_string()],
1504 resource: Vec::new(),
1505 exchange_context: None,
1506 policy_requirements: Vec::new(),
1507 custom_parameters: HashMap::new(),
1508 };
1509
1510 assert_eq!(
1511 request.grant_type,
1512 "urn:ietf:params:oauth:grant-type:token-exchange"
1513 );
1514 assert_eq!(
1515 request.subject_token_type,
1516 "urn:ietf:params:oauth:token-type:jwt"
1517 );
1518 }
1519
1520 #[test]
1521 fn test_exchange_context_creation() {
1522 let context = ExchangeContext {
1523 transaction_id: "txn_123".to_string(),
1524 business_context: serde_json::json!({
1525 "operation": "payment",
1526 "amount": 100.0
1527 }),
1528 delegation_chain: Vec::new(),
1529 original_request: None,
1530 security_context: None,
1531 custom_fields: HashMap::new(),
1532 };
1533
1534 assert_eq!(context.transaction_id, "txn_123");
1535 assert_eq!(context.business_context["operation"], "payment");
1536 }
1537
1538 #[test]
1539 fn test_delegation_link_creation() {
1540 let link = DelegationLink {
1541 delegator: "service_a".to_string(),
1542 delegatee: "service_b".to_string(),
1543 delegated_at: Utc::now(),
1544 delegation_reason: "API call forwarding".to_string(),
1545 delegated_scopes: vec!["read".to_string(), "write".to_string()],
1546 restrictions: Vec::new(),
1547 };
1548
1549 assert_eq!(link.delegator, "service_a");
1550 assert_eq!(link.delegated_scopes.len(), 2);
1551 }
1552}
1553
1554