Skip to main content

Crate saml_rs

Crate saml_rs 

Source
Expand description

saml-rs - SAML 2.0 Service Provider and Identity Provider support.

§Start here

Start new browser SSO/SLO integrations with Saml. The typed facade keeps local role state in Saml<Sp> or Saml<Idp>, accepts peer metadata through typed descriptors, and returns pending transaction values that callers can store with browser session state.

The dependency-free config builders use strict typed defaults. Opt into compatibility policy by name when a legacy peer requires unsigned protocol messages. Where the compact flow examples below use ReplayPolicy::DisabledForCompatibility or unsigned metadata, treat those as explicit interoperability choices. Production-shaped inbound flows should use ReplayPolicy::RequireCache with a caller-owned ReplayCache and, when protocol timestamps are not enough for expiry, SamlValidationContext::with_replay_retention.

use saml_rs::{AcsEndpoint, EntityId, SpConfig, SpValidationPolicy};

let config = SpConfig::builder(EntityId::try_new("https://sp.example.com/metadata")?)
    .acs_endpoint(AcsEndpoint::post("https://sp.example.com/acs")?)
    .validation(SpValidationPolicy::compatibility())
    .build()?;

assert_eq!(config.entity_id.as_str(), "https://sp.example.com/metadata");

§SP-initiated SSO

Saml<Sp>::start_sso creates the browser action and PendingAuthnRequest. Store the pending value and pass it back to Saml<Sp>::finish_sso when the ACS endpoint receives the SAML response.

use saml_rs::{
    AcsEndpoint, BrowserInput, EntityId, FormField, IdpDescriptor,
    MetadataTrustPolicy, ReplayPolicy, Saml, SamlValidationContext, SpConfig,
    SpValidationPolicy, SsoResponse, StartSso,
};
use std::time::SystemTime;

let sp = Saml::sp(
    SpConfig::builder(EntityId::try_new("https://sp.example.com/metadata")?)
        .acs_endpoint(AcsEndpoint::post("https://sp.example.com/acs")?)
        .validation(SpValidationPolicy::compatibility())
        .build()?,
)?;
let idp = IdpDescriptor::from_metadata_xml_for(
    EntityId::try_new("https://idp.example.com/metadata")?,
    idp_metadata_xml,
    MetadataTrustPolicy::UnsignedForCompatibility,
)?;

let started = sp.start_sso(&idp, StartSso::redirect())?;
let redirect_url = started.outbound.redirect_url()?;

let validation = SamlValidationContext::new(
    SystemTime::now(),
    ReplayPolicy::DisabledForCompatibility,
);
let session = sp.finish_sso(
    &idp,
    &started.pending,
    BrowserInput::<SsoResponse>::post(form_fields),
    validation,
)?;
let name_id = session.name_id().value();

§IdP-initiated SSO

Use Saml<Sp>::accept_unsolicited_sso for IdP-initiated responses. This method is separate from finish_sso so unsolicited responses are an explicit caller choice rather than a missing pending request.

use saml_rs::{
    BrowserInput, FormField, IdpDescriptor, ReplayPolicy, Saml,
    SamlValidationContext, SsoResponse,
};
use std::time::SystemTime;

let validation = SamlValidationContext::new(
    SystemTime::now(),
    ReplayPolicy::DisabledForCompatibility,
);
let session = sp.accept_unsolicited_sso(
    idp,
    BrowserInput::<SsoResponse>::post(form_fields),
    validation,
)?;
let issuer = session.issuer().as_str();

§Identity Provider flows

Saml<Idp>::receive_sso parses an SP AuthnRequest; Saml<Idp>::respond_sso returns the typed browser response.

use saml_rs::{
    AuthnRequest, BrowserInput, FormField, NameId, ReplayPolicy, RespondSso,
    Saml, SamlValidationContext, SpDescriptor, Subject,
};
use std::time::SystemTime;

let validation = SamlValidationContext::new(
    SystemTime::now(),
    ReplayPolicy::DisabledForCompatibility,
);
let request = idp.receive_sso(
    sp,
    BrowserInput::<AuthnRequest>::post(request_fields),
    validation,
)?;
let response = idp.respond_sso(
    sp,
    &request,
    Subject::new(NameId::new("alice@example.com", None), Vec::new()),
    RespondSso::post(),
)?;
let form = response.post_form()?;

§Single Logout

Typed SLO uses the same pattern: start with a LogoutSubject, store the returned PendingLogoutRequest, and finish only with the matching LogoutResponse. Receiving and responding to peer-initiated logout uses Received<LogoutRequest> instead of free-form request ID strings.

use saml_rs::{
    BrowserInput, FormField, IdpDescriptor, LogoutResponse, ReplayPolicy,
    Saml, SamlValidationContext, SsoSession, StartSlo,
};
use std::time::SystemTime;

if let Some(subject) = session.logout_subject() {
    let started = sp.start_slo(idp, subject, StartSlo::post())?;
    let validation = SamlValidationContext::new(
        SystemTime::now(),
        ReplayPolicy::DisabledForCompatibility,
    );
    let completed = sp.finish_slo(
        idp,
        &started.pending,
        BrowserInput::<LogoutResponse>::post(response_fields),
        validation,
    )?;
    let peer = completed.peer_entity_id().as_str();
}

§Compile-time flow boundaries

SSO and SLO pending values are different types. A logout pending value cannot be used to finish Web SSO:

use saml_rs::{
    BrowserInput, IdpDescriptor, PendingLogoutRequest, Saml,
    SamlValidationContext, SsoResponse,
};

fn wrong(
    sp: &Saml<saml_rs::Sp>,
    idp: &IdpDescriptor,
    pending: &PendingLogoutRequest,
    input: BrowserInput<SsoResponse>,
    validation: SamlValidationContext<'_>,
) -> Result<(), saml_rs::SamlError> {
    let _ = sp.finish_sso(idp, pending, input, validation)?;
    Ok(())
}

SLO responses are correlated through Received<LogoutRequest>, not arbitrary request ID strings:

use saml_rs::{RespondSlo, Saml, SpDescriptor};

fn wrong(
    idp: &Saml<saml_rs::Idp>,
    sp: &SpDescriptor,
    request_id: &str,
) -> Result<(), saml_rs::SamlError> {
    let _ = idp.respond_slo(sp, request_id, RespondSlo::post())?;
    Ok(())
}

§Metadata trust

Metadata trust is explicit and caller-pinned. MetadataTrustPolicy can accept unsigned metadata for explicit legacy compatibility or require a signature from caller-provided certificates with MetadataTrustPolicy::RequireSignature. Prefer signed metadata with pinned certificates for production trust decisions; the crate does not treat the public web PKI CA store as SAML metadata trust.

§Raw compatibility API

The raw module contains the low-level compatibility API and protocol helpers. Advanced callers should import raw::ServiceProvider, raw::IdentityProvider, raw::HttpRequest, and raw::BindingContext from there rather than using root compatibility exports.

Visible docs.rs modules and crate-root re-exports are the supported public documentation surface. The raw module is supported for compatibility; hidden modules are lower-level implementation or compatibility paths and should not be the first choice for new integrations.

§Unsupported profiles

The high-level Saml API focuses on browser Web SSO, metadata-driven SP/IdP setup, XML signature/encryption through bergshamra, and Single Logout. It does not yet implement Artifact resolution, SOAP/back-channel profiles, ECP/PAOS, SAML query protocols, NameID management, or metadata federation. If you need one of those profiles for a real interoperability target, please open an issue with the profile, binding, IdP/SP product, and a minimal expected flow so we can consider the implementation.

XML cryptography (XML-DSig sign/verify with anti-wrapping, XML-Enc, detached message signatures) is delegated to bergshamra behind the crypto-bergshamra feature, which is on by default. Configure assertion encryption and XML-Enc compatibility exceptions through XmlEncryptionPolicy. Disable default features to build the crypto-free protocol layer; crypto operations then fail closed with SamlError::Unsupported.

Re-exports§

pub use browser::AcsEndpoint;
pub use browser::BrowserInput;
pub use browser::EndpointUrl;
pub use browser::FormField;
pub use browser::LogoutBinding;
pub use browser::Outbound;
pub use browser::Pending;
pub use browser::PendingAuthnRequest;
pub use browser::PendingLogoutRequest;
pub use browser::PendingSnapshot;
pub use browser::PostForm;
pub use browser::SloEndpoint;
pub use browser::SsoEndpoint;
pub use browser::SsoRequestBinding;
pub use browser::SsoResponseBinding;
pub use browser::Started;
pub use config::AlgorithmPolicy;
pub use config::AssertionEncryptionPolicy;
pub use config::AssertionSignaturePolicy;
pub use config::AudienceValidationPolicy;
pub use config::AuthnRequestSigningPolicy;
pub use config::AuthnRequestValidationPolicy;
pub use config::CertificatePem;
pub use config::Credentials;
pub use config::DataEncryptionAlgorithm;
pub use config::DigestAlgorithm;
pub use config::EntityId;
pub use config::IdpConfig;
pub use config::IdpConfigBuilder;
pub use config::IdpDescriptor;
pub use config::IdpMetadataConfig;
pub use config::IdpValidationPolicy;
pub use config::KeyEncryptionAlgorithm;
pub use config::LogoutPolicy;
pub use config::LogoutSignaturePolicy;
pub use config::MessageSignaturePolicy;
pub use config::MetadataTrustPolicy;
pub use config::NameIdCreationPolicy;
pub use config::NameIdFormat;
pub use config::Passphrase;
pub use config::PrivateKeyPem;
pub use config::SignatureAlgorithm;
pub use config::SpConfig;
pub use config::SpConfigBuilder;
pub use config::SpDescriptor;
pub use config::SpMetadataConfig;
pub use config::SpValidationPolicy;
pub use config::TemplatePolicy;
pub use config::TransformAlgorithm;
pub use config::XmlEncryptionPolicy;
pub use config::XmlPolicy;
pub use metadata::MetadataSignatureVerification;
pub use model::Assertion;
pub use model::AssertionId;
pub use model::Attribute;
pub use model::AttributeValue;
pub use model::Attributes;
pub use model::AuthnRequest;
pub use model::AuthnSession;
pub use model::ClockSkew;
pub use model::LogoutCompleted;
pub use model::LogoutRequest;
pub use model::LogoutResponse;
pub use model::LogoutSubject;
pub use model::MessageId;
pub use model::NameId;
pub use model::NameIdCreationRequest;
pub use model::NameIdPolicy;
pub use model::Received;
pub use model::RelayState;
pub use model::RelayStateParam;
pub use model::ReplayCache;
pub use model::ReplayKey;
pub use model::ReplayPolicy;
pub use model::SamlInstant;
pub use model::SamlValidationContext;
pub use model::SessionIndex;
pub use model::SsoResponse;
pub use model::SsoSession;
pub use model::Subject;
pub use model::SubjectConfirmation;
pub use model::MAX_RELAY_STATE_BYTES;

Modules§

browser
Typed browser binding, endpoint, outbound, inbound, and pending-state APIs.
config
Typed configuration building blocks for high-level SAML APIs.
constants
SAML 2.0 URN constants and keywords.
error
Error types for saml-rs.
metadata
SAML metadata parsing and shared SP/IdP metadata accessors.
model
Typed SAML domain models built from validated raw flow results.
raw
Compatibility API and low-level protocol helpers.

Structs§

EntitySetting
Compatibility export for older crate-root imports. Use Saml for new integrations; advanced raw callers should import raw::EntitySetting. Runtime configuration for an entity (keys, algorithms, flags).
IdentityProvider
Compatibility export for older crate-root imports. Use Saml for new integrations; advanced raw callers should import raw::IdentityProvider. A SAML 2.0 Identity Provider: runtime EntitySetting plus parsed IdpMetadata.
Idp
Marker role for an Identity Provider facade.
RespondSlo
Options for issuing a LogoutResponse.
RespondSso
Options for issuing SAML Responses from an IdP.
Saml
Typed SAML facade for high-level browser SSO/SLO flows.
ServiceProvider
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.
Sp
Marker role for a Service Provider facade.
StartSlo
Options for issuing a LogoutRequest.
StartSso
Options for starting SP-initiated Web SSO.

Enums§

ForceAuthn
Explicit ForceAuthn value for outbound AuthnRequests.
LogoutSigning
Explicit signing choice for typed Single Logout messages.
Unknown
Marker role used before a facade has been configured as an SP or IdP.

Type Aliases§

SamlError
Error type returned by the typed SAML API.