pub struct Pending<Message: PendingMessage> { /* private fields */ }Expand description
Pending SAML message correlation state.
Implementations§
Source§impl<Message: PendingMessage> Pending<Message>
impl<Message: PendingMessage> Pending<Message>
Sourcepub fn with_issue_instant(self, issued_at: SamlInstant) -> Self
pub fn with_issue_instant(self, issued_at: SamlInstant) -> Self
Record an issue instant.
Sourcepub fn with_expiration(self, expires_at: SamlInstant) -> Self
pub fn with_expiration(self, expires_at: SamlInstant) -> Self
Record an expiration instant.
Sourcepub fn id(&self) -> &MessageId
pub fn id(&self) -> &MessageId
SAML protocol message ID.
Examples found in repository?
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 use saml_rs::{
9 AcsEndpoint, AuthnRequest, BrowserInput, CertificatePem, Credentials, EntityId, IdpConfig,
10 IdpDescriptor, IdpValidationPolicy, LogoutRequest, LogoutResponse, MetadataTrustPolicy,
11 NameId, PrivateKeyPem, ReplayPolicy, RespondSlo, RespondSso, Saml, SamlValidationContext,
12 SloEndpoint, SpConfig, SpDescriptor, SpValidationPolicy, SsoEndpoint, SsoResponse,
13 StartSlo, StartSso, Subject,
14 };
15 use std::time::SystemTime;
16
17 let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
18 let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
19 let credentials = || Credentials {
20 signing_key: Some(PrivateKeyPem::new(privkey)),
21 signing_certificate: Some(CertificatePem::new(cert)),
22 ..Credentials::default()
23 };
24 let validation =
25 || SamlValidationContext::new(SystemTime::now(), ReplayPolicy::DisabledForCompatibility);
26
27 let sp = Saml::sp(
28 SpConfig::builder(EntityId::try_new("https://sp.example.com/metadata")?)
29 .acs_endpoint(AcsEndpoint::post("https://sp.example.com/acs")?)
30 .slo_endpoint(SloEndpoint::post("https://sp.example.com/slo")?)
31 .credentials(credentials())
32 .validation(SpValidationPolicy::strict())
33 .build()?,
34 )?;
35 let idp = Saml::idp(
36 IdpConfig::builder(EntityId::try_new("https://idp.example.com/metadata")?)
37 .sso_endpoint(SsoEndpoint::post("https://idp.example.com/sso")?)
38 .slo_endpoint(SloEndpoint::post("https://idp.example.com/slo")?)
39 .credentials(credentials())
40 .validation(IdpValidationPolicy::strict())
41 .build()?,
42 )?;
43 let sp_descriptor = SpDescriptor::from_metadata_xml_for(
44 EntityId::try_new("https://sp.example.com/metadata")?,
45 sp.metadata_xml(),
46 MetadataTrustPolicy::UnsignedForCompatibility,
47 )?;
48 let idp_descriptor = IdpDescriptor::from_metadata_xml_for(
49 EntityId::try_new("https://idp.example.com/metadata")?,
50 idp.metadata_xml(),
51 MetadataTrustPolicy::UnsignedForCompatibility,
52 )?;
53
54 let sso = sp.start_sso(&idp_descriptor, StartSso::post())?;
55 let request = idp.receive_sso(
56 &sp_descriptor,
57 BrowserInput::<AuthnRequest>::post(sso.outbound.post_form()?.fields().to_vec()),
58 validation(),
59 )?;
60 let response = idp.respond_sso(
61 &sp_descriptor,
62 &request,
63 Subject::new(NameId::new("alice@example.com", None), Vec::new()),
64 RespondSso::post(),
65 )?;
66 let session = sp.finish_sso(
67 &idp_descriptor,
68 &sso.pending,
69 BrowserInput::<SsoResponse>::post(response.post_form()?.fields().to_vec()),
70 validation(),
71 )?;
72
73 let subject = session
74 .logout_subject()
75 .ok_or("session has no logout subject")?;
76 let logout = sp.start_slo(&idp_descriptor, subject, StartSlo::post())?;
77 println!("SP -> LogoutRequest id = {}", logout.pending.id().as_str());
78
79 let logout_request = idp.receive_slo(
80 &sp_descriptor,
81 BrowserInput::<LogoutRequest>::post(logout.outbound.post_form()?.fields().to_vec()),
82 validation(),
83 )?;
84 let logout_response = idp.respond_slo(
85 &sp_descriptor,
86 &logout_request,
87 RespondSlo::post().relay_state(logout.pending.relay_state().clone()),
88 )?;
89 let completed = sp.finish_slo(
90 &idp_descriptor,
91 &logout.pending,
92 BrowserInput::<LogoutResponse>::post(logout_response.post_form()?.fields().to_vec()),
93 validation(),
94 )?;
95 println!(
96 "SP <- LogoutResponse status = {}",
97 completed.status().unwrap_or("missing")
98 );
99 Ok(())
100}Sourcepub fn relay_state(&self) -> &RelayStateParam
pub fn relay_state(&self) -> &RelayStateParam
RelayState state.
Examples found in repository?
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 use saml_rs::{
9 AcsEndpoint, AuthnRequest, BrowserInput, CertificatePem, Credentials, EntityId, IdpConfig,
10 IdpDescriptor, IdpValidationPolicy, LogoutRequest, LogoutResponse, MetadataTrustPolicy,
11 NameId, PrivateKeyPem, ReplayPolicy, RespondSlo, RespondSso, Saml, SamlValidationContext,
12 SloEndpoint, SpConfig, SpDescriptor, SpValidationPolicy, SsoEndpoint, SsoResponse,
13 StartSlo, StartSso, Subject,
14 };
15 use std::time::SystemTime;
16
17 let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
18 let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
19 let credentials = || Credentials {
20 signing_key: Some(PrivateKeyPem::new(privkey)),
21 signing_certificate: Some(CertificatePem::new(cert)),
22 ..Credentials::default()
23 };
24 let validation =
25 || SamlValidationContext::new(SystemTime::now(), ReplayPolicy::DisabledForCompatibility);
26
27 let sp = Saml::sp(
28 SpConfig::builder(EntityId::try_new("https://sp.example.com/metadata")?)
29 .acs_endpoint(AcsEndpoint::post("https://sp.example.com/acs")?)
30 .slo_endpoint(SloEndpoint::post("https://sp.example.com/slo")?)
31 .credentials(credentials())
32 .validation(SpValidationPolicy::strict())
33 .build()?,
34 )?;
35 let idp = Saml::idp(
36 IdpConfig::builder(EntityId::try_new("https://idp.example.com/metadata")?)
37 .sso_endpoint(SsoEndpoint::post("https://idp.example.com/sso")?)
38 .slo_endpoint(SloEndpoint::post("https://idp.example.com/slo")?)
39 .credentials(credentials())
40 .validation(IdpValidationPolicy::strict())
41 .build()?,
42 )?;
43 let sp_descriptor = SpDescriptor::from_metadata_xml_for(
44 EntityId::try_new("https://sp.example.com/metadata")?,
45 sp.metadata_xml(),
46 MetadataTrustPolicy::UnsignedForCompatibility,
47 )?;
48 let idp_descriptor = IdpDescriptor::from_metadata_xml_for(
49 EntityId::try_new("https://idp.example.com/metadata")?,
50 idp.metadata_xml(),
51 MetadataTrustPolicy::UnsignedForCompatibility,
52 )?;
53
54 let sso = sp.start_sso(&idp_descriptor, StartSso::post())?;
55 let request = idp.receive_sso(
56 &sp_descriptor,
57 BrowserInput::<AuthnRequest>::post(sso.outbound.post_form()?.fields().to_vec()),
58 validation(),
59 )?;
60 let response = idp.respond_sso(
61 &sp_descriptor,
62 &request,
63 Subject::new(NameId::new("alice@example.com", None), Vec::new()),
64 RespondSso::post(),
65 )?;
66 let session = sp.finish_sso(
67 &idp_descriptor,
68 &sso.pending,
69 BrowserInput::<SsoResponse>::post(response.post_form()?.fields().to_vec()),
70 validation(),
71 )?;
72
73 let subject = session
74 .logout_subject()
75 .ok_or("session has no logout subject")?;
76 let logout = sp.start_slo(&idp_descriptor, subject, StartSlo::post())?;
77 println!("SP -> LogoutRequest id = {}", logout.pending.id().as_str());
78
79 let logout_request = idp.receive_slo(
80 &sp_descriptor,
81 BrowserInput::<LogoutRequest>::post(logout.outbound.post_form()?.fields().to_vec()),
82 validation(),
83 )?;
84 let logout_response = idp.respond_slo(
85 &sp_descriptor,
86 &logout_request,
87 RespondSlo::post().relay_state(logout.pending.relay_state().clone()),
88 )?;
89 let completed = sp.finish_slo(
90 &idp_descriptor,
91 &logout.pending,
92 BrowserInput::<LogoutResponse>::post(logout_response.post_form()?.fields().to_vec()),
93 validation(),
94 )?;
95 println!(
96 "SP <- LogoutResponse status = {}",
97 completed.status().unwrap_or("missing")
98 );
99 Ok(())
100}Sourcepub fn peer_entity_id(&self) -> &EntityId
pub fn peer_entity_id(&self) -> &EntityId
Peer entity ID.
Sourcepub fn issued_at(&self) -> Option<&SamlInstant>
pub fn issued_at(&self) -> Option<&SamlInstant>
Issue instant, if recorded.
Sourcepub fn expires_at(&self) -> Option<&SamlInstant>
pub fn expires_at(&self) -> Option<&SamlInstant>
Expiration instant, if recorded.
Source§impl Pending<AuthnRequest>
impl Pending<AuthnRequest>
Sourcepub fn try_new(
request_id: MessageId,
relay_state: RelayStateParam,
acs: AcsEndpoint,
response_binding: SsoResponseBinding,
idp_entity_id: EntityId,
) -> Result<Self, SamlError>
pub fn try_new( request_id: MessageId, relay_state: RelayStateParam, acs: AcsEndpoint, response_binding: SsoResponseBinding, idp_entity_id: EntityId, ) -> Result<Self, SamlError>
Create pending AuthnRequest state without storing keys or metadata.
§Errors
Returns SamlError::Invalid when the RelayState state is malformed,
the IdP entity ID is empty, or the selected ACS binding does not match
the expected response binding.
Sourcepub fn with_request_binding(self, request_binding: SsoRequestBinding) -> Self
pub fn with_request_binding(self, request_binding: SsoRequestBinding) -> Self
Record the outbound AuthnRequest binding selected for dispatch.
Sourcepub fn from_snapshot(
snapshot: PendingSnapshot<AuthnRequest>,
) -> Result<Self, SamlError>
pub fn from_snapshot( snapshot: PendingSnapshot<AuthnRequest>, ) -> Result<Self, SamlError>
Reconstruct pending AuthnRequest state from a snapshot.
§Errors
Returns SamlError when any snapshot field is malformed or
inconsistent.
§Examples
use saml_rs::{AuthnRequest, Pending, PendingSnapshot, RelayStateParam};
let snapshot = PendingSnapshot::<AuthnRequest>::authn_request(
"_request123",
RelayStateParam::absent(),
"https://idp.example.com/metadata",
"post",
"https://sp.example.com/acs",
"post",
);
let pending = Pending::<AuthnRequest>::from_snapshot(snapshot)?;
assert_eq!(pending.idp_entity_id().as_str(), "https://idp.example.com/metadata");Sourcepub fn snapshot(&self) -> PendingSnapshot<AuthnRequest>
pub fn snapshot(&self) -> PendingSnapshot<AuthnRequest>
Build a persistable snapshot.
Sourcepub fn request_id(&self) -> &MessageId
pub fn request_id(&self) -> &MessageId
Request ID.
Examples found in repository?
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 use saml_rs::{
10 AcsEndpoint, AuthnRequest, BrowserInput, CertificatePem, Credentials, EntityId, IdpConfig,
11 IdpDescriptor, IdpValidationPolicy, MetadataTrustPolicy, NameId, PrivateKeyPem,
12 RelayStateParam, ReplayPolicy, RespondSso, Saml, SamlValidationContext, SpConfig,
13 SpDescriptor, SpValidationPolicy, SsoEndpoint, SsoResponse, StartSso, Subject,
14 };
15 use std::time::SystemTime;
16
17 let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
18 let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
19 let credentials = || Credentials {
20 signing_key: Some(PrivateKeyPem::new(privkey)),
21 signing_certificate: Some(CertificatePem::new(cert)),
22 ..Credentials::default()
23 };
24 let validation =
25 || SamlValidationContext::new(SystemTime::now(), ReplayPolicy::DisabledForCompatibility);
26
27 let sp = Saml::sp(
28 SpConfig::builder(EntityId::try_new("https://sp.example.com/metadata")?)
29 .acs_endpoint(AcsEndpoint::post("https://sp.example.com/acs")?)
30 .credentials(credentials())
31 .validation(SpValidationPolicy::strict())
32 .build()?,
33 )?;
34 let idp = Saml::idp(
35 IdpConfig::builder(EntityId::try_new("https://idp.example.com/metadata")?)
36 .sso_endpoint(SsoEndpoint::post("https://idp.example.com/sso")?)
37 .credentials(credentials())
38 .validation(IdpValidationPolicy::strict())
39 .build()?,
40 )?;
41
42 let sp_descriptor = SpDescriptor::from_metadata_xml_for(
43 EntityId::try_new("https://sp.example.com/metadata")?,
44 sp.metadata_xml(),
45 MetadataTrustPolicy::UnsignedForCompatibility,
46 )?;
47 let idp_descriptor = IdpDescriptor::from_metadata_xml_for(
48 EntityId::try_new("https://idp.example.com/metadata")?,
49 idp.metadata_xml(),
50 MetadataTrustPolicy::UnsignedForCompatibility,
51 )?;
52
53 let relay_state = RelayStateParam::try_from_option(Some("demo-state".to_string()))?;
54 let started = sp.start_sso(&idp_descriptor, StartSso::post().relay_state(relay_state))?;
55 println!(
56 "SP -> AuthnRequest id = {}",
57 started.pending.request_id().as_str()
58 );
59
60 let request = idp.receive_sso(
61 &sp_descriptor,
62 BrowserInput::<AuthnRequest>::post(started.outbound.post_form()?.fields().to_vec()),
63 validation(),
64 )?;
65 println!(
66 "IdP <- request issuer = {}",
67 request.message().issuer().as_str()
68 );
69
70 let response = idp.respond_sso(
71 &sp_descriptor,
72 &request,
73 Subject::new(NameId::new("alice@example.com", None), Vec::new()),
74 RespondSso::post(),
75 )?;
76
77 let session = sp.finish_sso(
78 &idp_descriptor,
79 &started.pending,
80 BrowserInput::<SsoResponse>::post(response.post_form()?.fields().to_vec()),
81 validation(),
82 );
83 let session = session?;
84 println!("SP <- authenticated = {}", session.name_id().value());
85 Ok(())
86}Sourcepub fn request_binding(&self) -> Option<SsoRequestBinding>
pub fn request_binding(&self) -> Option<SsoRequestBinding>
Request binding, when tracked.
Sourcepub fn response_binding(&self) -> SsoResponseBinding
pub fn response_binding(&self) -> SsoResponseBinding
Expected response binding.
Sourcepub fn acs(&self) -> &AcsEndpoint
pub fn acs(&self) -> &AcsEndpoint
Selected ACS endpoint.
Sourcepub fn idp_entity_id(&self) -> &EntityId
pub fn idp_entity_id(&self) -> &EntityId
Selected IdP entity ID.
Source§impl Pending<LogoutRequest>
impl Pending<LogoutRequest>
Sourcepub fn try_new(
request_id: MessageId,
relay_state: RelayStateParam,
binding: LogoutBinding,
peer_entity_id: EntityId,
) -> Result<Self, SamlError>
pub fn try_new( request_id: MessageId, relay_state: RelayStateParam, binding: LogoutBinding, peer_entity_id: EntityId, ) -> Result<Self, SamlError>
Create pending LogoutRequest state without storing keys or metadata.
§Errors
Returns SamlError::Invalid when RelayState or peer entity ID are malformed.
Sourcepub fn from_snapshot(
snapshot: PendingSnapshot<LogoutRequest>,
) -> Result<Self, SamlError>
pub fn from_snapshot( snapshot: PendingSnapshot<LogoutRequest>, ) -> Result<Self, SamlError>
Reconstruct pending LogoutRequest state from a snapshot.
AuthnRequest-only ACS snapshot fields are ignored.
§Errors
Returns SamlError when any snapshot field is malformed or
inconsistent.
§Examples
use saml_rs::{LogoutBinding, LogoutRequest, Pending, PendingSnapshot, RelayStateParam};
let snapshot = PendingSnapshot::<LogoutRequest>::logout_request(
"_logout123",
RelayStateParam::absent(),
"https://idp.example.com/metadata",
LogoutBinding::Post,
);
let pending = Pending::<LogoutRequest>::from_snapshot(snapshot)?;
assert_eq!(pending.peer_entity_id().as_str(), "https://idp.example.com/metadata");Sourcepub fn snapshot(&self) -> PendingSnapshot<LogoutRequest>
pub fn snapshot(&self) -> PendingSnapshot<LogoutRequest>
Build a persistable snapshot.
Sourcepub fn request_binding(&self) -> LogoutBinding
pub fn request_binding(&self) -> LogoutBinding
Logout request binding selected for dispatch.
Sourcepub fn response_binding(&self) -> LogoutBinding
pub fn response_binding(&self) -> LogoutBinding
Expected logout response binding.