Skip to main content

ServiceProvider

Struct ServiceProvider 

Source
pub struct ServiceProvider {
    pub setting: EntitySetting,
    pub metadata: SpMetadata,
}
Expand description

Compatibility export for older crate-root imports. Use Saml for new integrations; advanced raw callers should import raw::ServiceProvider. A SAML 2.0 Service Provider: runtime EntitySetting plus parsed SpMetadata.

Fields§

§setting: EntitySetting

Runtime configuration (keys, algorithms, flags).

§metadata: SpMetadata

Parsed SP metadata.

Implementations§

Source§

impl ServiceProvider

Source

pub fn from_metadata( xml: &str, setting: EntitySetting, ) -> Result<Self, SamlError>

Build from SP metadata XML, merging the metadata-declared flags into setting.

§Errors

Returns an error when xml is malformed, exceeds XML limits, or cannot be parsed as SP metadata. Metadata parser errors include invalid entity, endpoint, certificate, or signing flag declarations.

Source

pub fn from_config( config: &SpMetadataConfig, setting: EntitySetting, ) -> Result<Self, SamlError>

Build by generating SP metadata from config, then importing it.

§Errors

Returns an error if the generated metadata cannot be parsed back into SP metadata, including invalid endpoint or certificate declarations.

Examples found in repository?
examples/raw_compat.rs (lines 39-52)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9    use saml_rs::constants::signature_algorithm::RSA_SHA256;
10    use saml_rs::raw::metadata::{Endpoint, IdpMetadataConfig, SpMetadataConfig};
11    use saml_rs::raw::{
12        Binding, EntitySetting, HttpRequest, IdentityProvider, LoginResponseOptions,
13        ServiceProvider, User,
14    };
15
16    let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
17    let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
18    let signing = || {
19        let mut setting = EntitySetting::default();
20        setting.private_key = Some(privkey.into());
21        setting.signing_cert = Some(cert.into());
22        setting.request_signature_algorithm = RSA_SHA256.into();
23        setting
24    };
25
26    let idp = IdentityProvider::from_config(
27        &IdpMetadataConfig {
28            entity_id: "https://idp.example.com/metadata".into(),
29            signing_certs: vec![cert.into()],
30            want_authn_requests_signed: true,
31            single_sign_on_service: vec![Endpoint::new(
32                Binding::Post,
33                "https://idp.example.com/sso",
34            )],
35            ..Default::default()
36        },
37        signing(),
38    )?;
39    let sp = ServiceProvider::from_config(
40        &SpMetadataConfig {
41            entity_id: "https://sp.example.com/metadata".into(),
42            authn_requests_signed: true,
43            want_assertions_signed: true,
44            signing_certs: vec![cert.into()],
45            assertion_consumer_service: vec![Endpoint::new(
46                Binding::Post,
47                "https://sp.example.com/acs",
48            )],
49            ..Default::default()
50        },
51        signing(),
52    )?;
53
54    let request = sp.create_login_request(&idp, Binding::Post, None)?;
55    let parsed = idp.parse_login_request(
56        &sp,
57        Binding::Post,
58        &HttpRequest::post(vec![("SAMLRequest".into(), request.context.clone())]),
59    )?;
60    let response = idp.create_login_response(
61        &sp,
62        Binding::Post,
63        &User::new("alice@example.com"),
64        &LoginResponseOptions {
65            in_response_to: parsed.extract.get_str("request.id"),
66            ..Default::default()
67        },
68    )?;
69    let result = sp.parse_login_response_with_request_id(
70        &idp,
71        Binding::Post,
72        &HttpRequest::post(vec![("SAMLResponse".into(), response.context)]),
73        &request.id,
74    )?;
75    println!(
76        "raw compatibility authenticated = {:?}",
77        result.extract.get_str("nameID")
78    );
79    Ok(())
80}
Source

pub fn metadata_xml(&self) -> &str

The SP metadata XML.

Source

pub fn create_login_request( &self, idp: &IdentityProvider, binding: Binding, custom: Option<CustomTagReplacement<'_>>, ) -> Result<BindingContext, SamlError>

Build a login <AuthnRequest> for idp over binding.

When both sides require signing, the request is signed (requires the crypto-bergshamra feature and the SP’s private_key/signing_cert). custom overrides template rendering, receiving the resolved template and returning (id, xml).

§Errors

Returns an error if SP and IdP signing requirements conflict, the IdP metadata has no SSO endpoint for binding, the SP metadata has no ACS endpoint for the requested response binding, or binding is unsupported for AuthnRequest generation. When signing is required, key loading, missing private_key/signing_cert, unsupported crypto features, XML signature construction, and detached-signature construction errors are propagated.

Examples found in repository?
examples/raw_compat.rs (line 54)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9    use saml_rs::constants::signature_algorithm::RSA_SHA256;
10    use saml_rs::raw::metadata::{Endpoint, IdpMetadataConfig, SpMetadataConfig};
11    use saml_rs::raw::{
12        Binding, EntitySetting, HttpRequest, IdentityProvider, LoginResponseOptions,
13        ServiceProvider, User,
14    };
15
16    let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
17    let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
18    let signing = || {
19        let mut setting = EntitySetting::default();
20        setting.private_key = Some(privkey.into());
21        setting.signing_cert = Some(cert.into());
22        setting.request_signature_algorithm = RSA_SHA256.into();
23        setting
24    };
25
26    let idp = IdentityProvider::from_config(
27        &IdpMetadataConfig {
28            entity_id: "https://idp.example.com/metadata".into(),
29            signing_certs: vec![cert.into()],
30            want_authn_requests_signed: true,
31            single_sign_on_service: vec![Endpoint::new(
32                Binding::Post,
33                "https://idp.example.com/sso",
34            )],
35            ..Default::default()
36        },
37        signing(),
38    )?;
39    let sp = ServiceProvider::from_config(
40        &SpMetadataConfig {
41            entity_id: "https://sp.example.com/metadata".into(),
42            authn_requests_signed: true,
43            want_assertions_signed: true,
44            signing_certs: vec![cert.into()],
45            assertion_consumer_service: vec![Endpoint::new(
46                Binding::Post,
47                "https://sp.example.com/acs",
48            )],
49            ..Default::default()
50        },
51        signing(),
52    )?;
53
54    let request = sp.create_login_request(&idp, Binding::Post, None)?;
55    let parsed = idp.parse_login_request(
56        &sp,
57        Binding::Post,
58        &HttpRequest::post(vec![("SAMLRequest".into(), request.context.clone())]),
59    )?;
60    let response = idp.create_login_response(
61        &sp,
62        Binding::Post,
63        &User::new("alice@example.com"),
64        &LoginResponseOptions {
65            in_response_to: parsed.extract.get_str("request.id"),
66            ..Default::default()
67        },
68    )?;
69    let result = sp.parse_login_response_with_request_id(
70        &idp,
71        Binding::Post,
72        &HttpRequest::post(vec![("SAMLResponse".into(), response.context)]),
73        &request.id,
74    )?;
75    println!(
76        "raw compatibility authenticated = {:?}",
77        result.extract.get_str("nameID")
78    );
79    Ok(())
80}
Source

pub fn create_login_request_with_options( &self, idp: &IdentityProvider, binding: Binding, options: &LoginRequestOptions<'_>, ) -> Result<BindingContext, SamlError>

Build a login <AuthnRequest> for idp over binding with per-call options.

§Errors

Returns an error if SP and IdP signing requirements conflict, the IdP metadata has no SSO endpoint for binding, the SP metadata has no ACS endpoint for options.response_binding when ACS index mode is not used, or binding is unsupported. When signing is required, key loading, missing private_key/signing_cert, unsupported crypto features, XML signature construction, and detached-signature construction errors are propagated.

Source

pub fn parse_login_response( &self, idp: &IdentityProvider, binding: Binding, request: &HttpRequest, ) -> Result<FlowResult, SamlError>

Parse and validate an unsolicited IdP login <Response> (signature required).

This mode is for IdP-initiated SSO. It rejects a non-empty InResponseTo; for SP-initiated SSO use Self::parse_login_response_with_request_id to bind the response to the AuthnRequest ID you issued.

When setting.validate_audience is set, the assertion’s <Audience> must include this SP’s entity ID.

§Errors

Returns an error for all unsolicited-response validation failures from Self::parse_unsolicited_login_response, including malformed browser input, unsupported bindings, missing ACS metadata, XML parsing failures, missing or invalid signatures, untrusted signing certificates, issuer, destination, recipient, audience, status, time-window, and unexpected InResponseTo failures.

Source

pub fn parse_unsolicited_login_response( &self, idp: &IdentityProvider, binding: Binding, request: &HttpRequest, ) -> Result<FlowResult, SamlError>

Parse and validate an IdP-initiated login <Response> that is not bound to an outbound AuthnRequest.

§Errors

Returns an error if the SP metadata has no ACS endpoint for binding, binding is unsupported, the request is missing required binding parameters, the SAML payload cannot be base64/DEFLATE decoded, XML parsing or extraction fails, the status is not success, the required signature is missing or invalid, no trusted IdP signing key is available, or issuer, destination, bearer recipient, audience, subject-confirmation, or time-window validation fails. Because this path is unsolicited, any non-empty response or bearer InResponseTo also returns an error.

Source

pub fn parse_login_response_with_request_id( &self, idp: &IdentityProvider, binding: Binding, request: &HttpRequest, request_id: &str, ) -> Result<FlowResult, SamlError>

Like Self::parse_login_response but also requires InResponseTo to equal request_id (anti-replay: bind the response to a request you sent).

An empty caller-provided request_id is rejected as SamlError::InvalidInResponseTo. A non-empty request_id that does not match the SAML response returns SamlError::InResponseToMismatch.

§Errors

Returns an error if request_id is empty, the SP metadata has no ACS endpoint for binding, binding is unsupported, the request is missing required binding parameters, the SAML payload cannot be base64/DEFLATE decoded, XML parsing or extraction fails, the status is not success, the required signature is missing or invalid, no trusted IdP signing key is available, or issuer, destination, bearer recipient, audience, InResponseTo, subject-confirmation, or time-window validation fails.

Examples found in repository?
examples/raw_compat.rs (lines 69-74)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9    use saml_rs::constants::signature_algorithm::RSA_SHA256;
10    use saml_rs::raw::metadata::{Endpoint, IdpMetadataConfig, SpMetadataConfig};
11    use saml_rs::raw::{
12        Binding, EntitySetting, HttpRequest, IdentityProvider, LoginResponseOptions,
13        ServiceProvider, User,
14    };
15
16    let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
17    let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
18    let signing = || {
19        let mut setting = EntitySetting::default();
20        setting.private_key = Some(privkey.into());
21        setting.signing_cert = Some(cert.into());
22        setting.request_signature_algorithm = RSA_SHA256.into();
23        setting
24    };
25
26    let idp = IdentityProvider::from_config(
27        &IdpMetadataConfig {
28            entity_id: "https://idp.example.com/metadata".into(),
29            signing_certs: vec![cert.into()],
30            want_authn_requests_signed: true,
31            single_sign_on_service: vec![Endpoint::new(
32                Binding::Post,
33                "https://idp.example.com/sso",
34            )],
35            ..Default::default()
36        },
37        signing(),
38    )?;
39    let sp = ServiceProvider::from_config(
40        &SpMetadataConfig {
41            entity_id: "https://sp.example.com/metadata".into(),
42            authn_requests_signed: true,
43            want_assertions_signed: true,
44            signing_certs: vec![cert.into()],
45            assertion_consumer_service: vec![Endpoint::new(
46                Binding::Post,
47                "https://sp.example.com/acs",
48            )],
49            ..Default::default()
50        },
51        signing(),
52    )?;
53
54    let request = sp.create_login_request(&idp, Binding::Post, None)?;
55    let parsed = idp.parse_login_request(
56        &sp,
57        Binding::Post,
58        &HttpRequest::post(vec![("SAMLRequest".into(), request.context.clone())]),
59    )?;
60    let response = idp.create_login_response(
61        &sp,
62        Binding::Post,
63        &User::new("alice@example.com"),
64        &LoginResponseOptions {
65            in_response_to: parsed.extract.get_str("request.id"),
66            ..Default::default()
67        },
68    )?;
69    let result = sp.parse_login_response_with_request_id(
70        &idp,
71        Binding::Post,
72        &HttpRequest::post(vec![("SAMLResponse".into(), response.context)]),
73        &request.id,
74    )?;
75    println!(
76        "raw compatibility authenticated = {:?}",
77        result.extract.get_str("nameID")
78    );
79    Ok(())
80}

Trait Implementations§

Source§

impl Clone for ServiceProvider

Source§

fn clone(&self) -> ServiceProvider

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ServiceProvider

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V