#[cfg(test)]
mod tests {
use auth_framework::{
saml_assertions::{SamlAssertionBuilder, SamlAssertionValidator, SamlNameId, SamlSubject},
ws_security::{PasswordType, WsSecurityClient, WsSecurityConfig},
ws_trust::{
AuthenticationContext, RequestSecurityToken, SecurityTokenService, StsConfig,
TokenLifetime,
},
};
use chrono::{Duration, Utc};
use std::collections::HashMap;
#[test]
fn test_complete_enterprise_auth_flow() {
let issuer = "https://idp.enterprise.com";
let subject = "enterprise_user@company.com";
let audience = "https://app.enterprise.com";
let now = Utc::now();
let subject_obj = SamlSubject {
name_id: Some(SamlNameId {
value: subject.to_string(),
format: Some("urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress".to_string()),
name_qualifier: None,
sp_name_qualifier: None,
}),
subject_confirmations: vec![],
};
let assertion = SamlAssertionBuilder::new(issuer)
.with_subject(subject_obj)
.with_audience(audience)
.with_validity_period(now, now + Duration::hours(1))
.with_attribute("role", "manager")
.with_attribute("department", "finance")
.with_attribute("clearance_level", "confidential")
.build();
let assertion_xml = assertion.to_xml().unwrap();
assert!(assertion_xml.contains("<saml:Assertion"));
assert!(assertion_xml.contains("enterprise_user@company.com"));
assert!(assertion_xml.contains("https://app.enterprise.com"));
assert!(assertion_xml.contains("manager"));
assert!(assertion_xml.contains("finance"));
assert!(assertion_xml.contains("confidential"));
println!("✅ SAML 2.0 Assertion created successfully");
let validator = SamlAssertionValidator::new();
let validation_result = validator.validate(&assertion);
assert!(validation_result.is_ok());
println!("✅ SAML 2.0 Assertion validation passed");
let ws_config = WsSecurityConfig::default();
let ws_client = WsSecurityClient::new(ws_config);
let header = ws_client
.create_username_token_header(
"ws_user",
Some("ws_password"),
PasswordType::PasswordDigest,
)
.unwrap();
let header_xml = ws_client.header_to_xml(&header).unwrap();
assert!(header_xml.contains("<wsse:Security"));
assert!(header_xml.contains("<wsse:UsernameToken"));
assert!(header_xml.contains("ws_user"));
assert!(header_xml.contains("#PasswordDigest\">"));
assert!(header_xml.contains("<wsu:Timestamp"));
println!("✅ WS-Security 1.1 header created successfully");
let sts_config = StsConfig::default();
let mut sts = SecurityTokenService::new(sts_config);
let auth_context = AuthenticationContext {
username: subject.to_string(),
auth_method: "saml_assertion".to_string(),
claims: {
let mut claims = HashMap::new();
claims.insert("role".to_string(), "manager".to_string());
claims.insert("department".to_string(), "finance".to_string());
claims.insert("clearance_level".to_string(), "confidential".to_string());
claims
},
};
let token_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue".to_string(),
token_type: "urn:oasis:names:tc:SAML:2.0:assertion".to_string(),
applies_to: Some(audience.to_string()),
lifetime: Some(TokenLifetime {
created: now,
expires: now + Duration::hours(2),
}),
key_type: Some("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer".to_string()),
key_size: None,
existing_token: None,
auth_context: Some(auth_context),
};
let token_response = sts.process_request(token_request).unwrap();
assert_eq!(
token_response.token_type,
"urn:oasis:names:tc:SAML:2.0:assertion"
);
assert!(
token_response
.requested_security_token
.contains("<saml:Assertion")
);
assert!(
token_response
.requested_security_token
.contains("enterprise_user@company.com")
);
assert!(
token_response
.applies_to
.as_ref()
.unwrap()
.contains("app.enterprise.com")
);
println!("✅ WS-Trust 1.3 token issuance successful");
let soap_request = sts
.create_rst_soap_request(&RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue".to_string(),
token_type: "urn:oasis:names:tc:SAML:2.0:assertion".to_string(),
applies_to: Some("https://service.enterprise.com".to_string()),
lifetime: None,
key_type: Some(
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer".to_string(),
),
key_size: None,
existing_token: None,
auth_context: None,
})
.unwrap();
assert!(soap_request.contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
assert!(soap_request.contains("<soap:Envelope"));
assert!(soap_request.contains("<wsse:Security"));
assert!(soap_request.contains("<wst:RequestSecurityToken"));
assert!(soap_request.contains("https://service.enterprise.com"));
assert!(soap_request.contains("</soap:Envelope>"));
println!("✅ Complete SOAP request with WS-Security and WS-Trust created");
let renewal_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Renew".to_string(),
token_type: "urn:oasis:names:tc:SAML:2.0:assertion".to_string(),
applies_to: Some(audience.to_string()),
lifetime: None,
key_type: None,
key_size: None,
existing_token: Some(token_response.requested_unattached_reference.unwrap()),
auth_context: None,
};
let renewal_response = sts.process_request(renewal_request).unwrap();
assert_eq!(
renewal_response.token_type,
"urn:oasis:names:tc:SAML:2.0:assertion"
);
println!("✅ WS-Trust token renewal successful");
println!("\n🎉 Complete Enterprise Authentication Stack Test PASSED!");
println!(" ✅ SAML 2.0 Assertions");
println!(" ✅ WS-Security 1.1 Headers");
println!(" ✅ WS-Trust 1.3 Security Token Service");
println!(" ✅ SOAP Message Integration");
println!(" ✅ Token Lifecycle Management");
}
#[test]
fn test_ws_security_password_types() {
let ws_config = WsSecurityConfig::default();
let ws_client = WsSecurityClient::new(ws_config);
let header_text = ws_client
.create_username_token_header("user1", Some("password123"), PasswordType::PasswordText)
.unwrap();
let xml_text = ws_client.header_to_xml(&header_text).unwrap();
assert!(xml_text.contains("#PasswordText\">"));
assert!(xml_text.contains("password123"));
let header_digest = ws_client
.create_username_token_header(
"user1",
Some("password123"),
PasswordType::PasswordDigest,
)
.unwrap();
let xml_digest = ws_client.header_to_xml(&header_digest).unwrap();
assert!(xml_digest.contains("#PasswordDigest\">"));
assert!(!xml_digest.contains("password123")); assert!(xml_digest.contains("<wsse:Nonce"));
println!("✅ WS-Security password types test passed");
}
#[test]
fn test_saml_assertion_attributes() {
let test_subject = SamlSubject {
name_id: Some(SamlNameId {
value: "test_user".to_string(),
format: Some("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified".to_string()),
name_qualifier: None,
sp_name_qualifier: None,
}),
subject_confirmations: vec![],
};
let assertion = SamlAssertionBuilder::new("https://test.idp.com")
.with_subject(test_subject)
.with_audience("https://test.app.com")
.with_attribute("email", "test@example.com")
.with_attribute("role", "admin")
.with_attribute("groups", "administrators,users")
.with_attribute("security_clearance", "top_secret")
.build();
let xml = assertion.to_xml().unwrap();
assert!(xml.contains("test@example.com"));
assert!(xml.contains("admin"));
assert!(xml.contains("administrators,users"));
assert!(xml.contains("top_secret"));
assert!(xml.contains("<saml:AttributeStatement>"));
assert!(xml.contains("<saml:Attribute Name=\"email\""));
assert!(xml.contains("<saml:Attribute Name=\"role\""));
assert!(xml.contains("<saml:Attribute Name=\"groups\""));
assert!(xml.contains("<saml:Attribute Name=\"security_clearance\""));
println!("✅ SAML assertion attributes test passed");
}
#[test]
fn test_ws_trust_jwt_tokens() {
let sts_config = StsConfig::default();
let mut sts = SecurityTokenService::new(sts_config);
let auth_context = AuthenticationContext {
username: "jwt_user".to_string(),
auth_method: "client_certificate".to_string(),
claims: {
let mut claims = HashMap::new();
claims.insert("scope".to_string(), "read write admin".to_string());
claims.insert("client_id".to_string(), "enterprise_app_123".to_string());
claims
},
};
let jwt_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue".to_string(),
token_type: "urn:ietf:params:oauth:token-type:jwt".to_string(),
applies_to: Some("https://api.enterprise.com".to_string()),
lifetime: None,
key_type: Some("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer".to_string()),
key_size: None,
existing_token: None,
auth_context: Some(auth_context),
};
let jwt_response = sts.process_request(jwt_request).unwrap();
assert_eq!(
jwt_response.token_type,
"urn:ietf:params:oauth:token-type:jwt"
);
let jwt_parts: Vec<&str> = jwt_response.requested_security_token.split('.').collect();
assert_eq!(jwt_parts.len(), 3);
use base64::{Engine, engine::general_purpose};
let payload_json = general_purpose::URL_SAFE
.decode(jwt_parts[1])
.unwrap_or_else(|_| {
general_purpose::URL_SAFE_NO_PAD
.decode(jwt_parts[1])
.unwrap()
});
let payload_str = String::from_utf8(payload_json).unwrap();
assert!(payload_str.contains("jwt_user"));
assert!(payload_str.contains("client_certificate"));
assert!(payload_str.contains("api.enterprise.com"));
println!("✅ WS-Trust JWT token issuance test passed");
}
#[test]
fn test_token_validation_and_cancellation() {
let sts_config = StsConfig::default();
let mut sts = SecurityTokenService::new(sts_config);
let auth_context = AuthenticationContext {
username: "validation_user".to_string(),
auth_method: "password".to_string(),
claims: HashMap::new(),
};
let issue_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue".to_string(),
token_type: "urn:oasis:names:tc:SAML:2.0:assertion".to_string(),
applies_to: Some("https://validation.test.com".to_string()),
lifetime: None,
key_type: None,
key_size: None,
existing_token: None,
auth_context: Some(auth_context),
};
let issue_response = sts.process_request(issue_request).unwrap();
let token_id = issue_response.requested_unattached_reference.unwrap();
let validate_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Validate".to_string(),
token_type: "".to_string(),
applies_to: None,
lifetime: None,
key_type: None,
key_size: None,
existing_token: Some(token_id.clone()),
auth_context: None,
};
let validate_response = sts.process_request(validate_request).unwrap();
assert!(validate_response.requested_security_token.contains("Valid"));
let cancel_request = RequestSecurityToken {
request_type: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Cancel".to_string(),
token_type: "".to_string(),
applies_to: None,
lifetime: None,
key_type: None,
key_size: None,
existing_token: Some(token_id.clone()),
auth_context: None,
};
let cancel_response = sts.process_request(cancel_request).unwrap();
assert!(
cancel_response
.requested_security_token
.contains("cancelled")
);
println!("✅ Token validation and cancellation test passed");
}
}