Skip to main content

raw_compat/
raw_compat.rs

1//! Low-level raw compatibility SSO example.
2//!
3//! New browser integrations should start with `examples/sso.rs`. This example
4//! is for callers that need direct access to raw `ServiceProvider`,
5//! `IdentityProvider`, `HttpRequest`, or `FlowResult` values.
6
7#[cfg(any(
8    feature = "crypto-rustcrypto",
9    feature = "crypto-aws-lc",
10    feature = "crypto-fips"
11))]
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13    use saml_rs::constants::signature_algorithm::RSA_SHA256;
14    use saml_rs::raw::metadata::{Endpoint, IdpMetadataConfig, SpMetadataConfig};
15    use saml_rs::raw::{
16        Binding, EntitySetting, HttpRequest, IdentityProvider, LoginResponseOptions,
17        ServiceProvider, User,
18    };
19
20    let privkey = include_str!("../tests/fixtures/key/sp_privkey.pem");
21    let cert = include_str!("../tests/fixtures/key/sp_signing_cert.cer");
22    let signing = || {
23        let mut setting = EntitySetting::default();
24        setting.private_key = Some(privkey.into());
25        setting.signing_cert = Some(cert.into());
26        setting.request_signature_algorithm = RSA_SHA256.into();
27        setting
28    };
29
30    let idp = IdentityProvider::from_config(
31        &IdpMetadataConfig {
32            entity_id: "https://idp.example.com/metadata".into(),
33            signing_certs: vec![cert.into()],
34            want_authn_requests_signed: true,
35            single_sign_on_service: vec![Endpoint::new(
36                Binding::Post,
37                "https://idp.example.com/sso",
38            )],
39            ..Default::default()
40        },
41        signing(),
42    )?;
43    let sp = ServiceProvider::from_config(
44        &SpMetadataConfig {
45            entity_id: "https://sp.example.com/metadata".into(),
46            authn_requests_signed: true,
47            want_assertions_signed: true,
48            signing_certs: vec![cert.into()],
49            assertion_consumer_service: vec![Endpoint::new(
50                Binding::Post,
51                "https://sp.example.com/acs",
52            )],
53            ..Default::default()
54        },
55        signing(),
56    )?;
57
58    let request = sp.create_login_request(&idp, Binding::Post, None)?;
59    let parsed = idp.parse_login_request(
60        &sp,
61        Binding::Post,
62        &HttpRequest::post(vec![("SAMLRequest".into(), request.context.clone())]),
63    )?;
64    let response = idp.create_login_response(
65        &sp,
66        Binding::Post,
67        &User::new("alice@example.com"),
68        &LoginResponseOptions {
69            in_response_to: parsed.extract.get_str("request.id"),
70            ..Default::default()
71        },
72    )?;
73    let result = sp.parse_login_response_with_request_id(
74        &idp,
75        Binding::Post,
76        &HttpRequest::post(vec![("SAMLResponse".into(), response.context)]),
77        &request.id,
78    )?;
79    println!(
80        "raw compatibility authenticated = {:?}",
81        result.extract.get_str("nameID")
82    );
83    Ok(())
84}
85
86#[cfg(not(any(
87    feature = "crypto-rustcrypto",
88    feature = "crypto-aws-lc",
89    feature = "crypto-fips"
90)))]
91fn main() {
92    eprintln!("Enable a crypto provider feature (`crypto-bergshamra` is on by default).");
93}