saml-rs
Pure-Rust SAML 2.0 service provider and identity provider support for browser
Web SSO, metadata, and Single Logout. XML-DSig, XML-Enc, C14N, and detached
message signatures go through
bergshamra. The crate does not need
libxml2, xmlsec1, or an OpenSSL build chain.
The Cargo package is saml-rs. The Rust import path is saml_rs. Source and
issues live in salasebas/saml-rs.
Status: pre-1.0. A minor release can change the API or runtime behaviour. There has been no external security audit. Review the crate, your configuration, and the peer metadata trust model before production use.
Help: open an issue. Before a minor upgrade, follow the migration guides.
Install
[]
= "0.5"
# Protocol layer only, with signing and encryption disabled:
# saml-rs = { version = "0.5", default-features = false }
Rust 1.88 or newer is required.
How to add service-provider SSO
This guide adds browser single sign-on for a service provider that already has a peer identity provider and an assertion consumer endpoint.
Use the typed Saml facade. Build local state with SpConfig::builder,
import the peer from metadata, and keep the returned Pending<_> value with
the browser session until the round trip finishes.
- Build
SpConfigand callSaml::sp. - Import peer IdP metadata into
IdpDescriptor. - Call
sp.start_sso(...)and storestarted.pendingwith the browser session. - In the assertion consumer service, pass the posted fields and that pending
value to
sp.finish_sso(...).
Run that SP to IdP to SP round trip:
Source: examples/sso.rs. The same calls, checked by
cargo test --doc, are in the
crate-root SSO example.
Those snippets use ReplayPolicy::DisabledForCompatibility and, where noted,
MetadataTrustPolicy::UnsignedForCompatibility so they compile alone. Both
names preserve a raw or samlify-port choice: no replay cache, and an unsigned
metadata import. recommended() does not turn either one on.
If inbound responses need replay protection, pass ReplayPolicy::RequireCache
with a caller-owned replay cache. Choose the metadata policy in
metadata trust and
SamlValidationContext.
If you want the preset for claimed features, start from
SpValidationPolicy::recommended or IdpValidationPolicy::recommended. Add a
direct Assertion signature or the RSA-SHA2 XML-DSig profile by name when you
want that hardening. Neither is implied by recommended(), and strict()
does not gain the RSA-SHA2 profile. compatibility() is the legacy permissive
preset. Default, new, and try_new stay on that preset. Config builders
still start on the deprecated strict() bundle. Why those presets differ is
in validation presets.
finish_sso returns an SsoSession. Read embedded XML signature evidence from
verified_xml_signatures(): one item per verified signature over the Response
root or the consumed Assertion, including its SignatureMethod@Algorithm URI.
sig_alg() is only the detached SigAlg from HTTP-Redirect or
HTTP-POST-SimpleSign. Neither value applies an application algorithm allowlist.
If you receive and respond as an identity provider, follow
examples/sso.rs and the
Identity Provider flows.
If you need logout, follow examples/slo.rs and
Single Logout.
Issuance lifetime and Session Authority logout expiration are on
Saml<Idp>::start_slo.
If an existing integration still calls ServiceProvider, IdentityProvider,
HttpRequest, or BindingContext, use saml_rs::raw
(examples/raw_compat.rs).
What the typed API covers
| Area | Support |
|---|---|
| Web SSO | Signed AuthnRequest and Response over HTTP-POST, HTTP-Redirect, and HTTP-POST-SimpleSign |
| Metadata | Parse peer metadata, generate SP and IdP descriptors, verify signed metadata |
| Single Logout | Create and parse LogoutRequest and LogoutResponse on the same three bindings |
| Validation | Issuer, audience, destination, recipient, bearer confirmation, status, time windows, and request correlation |
| Crypto | XML-DSig, XML-Enc, detached signatures, and metadata key pinning through bergshamra |
| Parsing | quick-xml DOM with local-name extraction, bounded before authentication |
Artifact resolution, SOAP and other back-channel profiles, ECP/PAOS, SAML query
protocols, NameID management, and metadata federation are outside the typed
Saml API. A request for one of them needs the profile, binding, peer
product, and a minimal expected flow on
an issue.
Where to read next
| Need | Start here |
|---|---|
| Run a full flow | examples/sso.rs and examples/slo.rs |
| Change an existing integration | Migration guides |
| Look up a type or method | docs.rs |
| Choose metadata trust or replay policy | Metadata trust and SamlValidationContext |
| See which rules a flow claims | Conformance records |
| See why the presets differ | Validation presets |
Features
[]
= ["crypto-bergshamra"]
= [
"crypto-rustcrypto",
"crypto-legacy-algorithms",
"crypto-post-quantum",
"crypto-pkcs11",
]
= ["dep:bergshamra", "bergshamra/rustcrypto"]
= ["dep:bergshamra", "bergshamra/aws-lc"]
= ["dep:bergshamra", "bergshamra/fips"]
With default-features = false, the crate still builds messages, parses
metadata, and extracts fields. Signing, verification, and encryption return
SamlError::Unsupported.
At most one of crypto-rustcrypto, crypto-aws-lc, and crypto-fips can be
selected. Combinations are rejected at compile time. AWS-LC and FIPS are
selected with the default features off. crypto-legacy-algorithms,
crypto-post-quantum, and crypto-pkcs11 forward Bergshamra capabilities
and do not select a provider. The default crypto-bergshamra feature enables
those capabilities together with RustCrypto.
Bergshamra supports AWS-LC and FIPS on Linux x86_64 and aarch64. This
repository's provider tests run on Linux x86_64. saml-rs initialises
Bergshamra before the first crypto operation.
Initialisation, attestation, unsupported-algorithm, and key-import failures
map to SamlError::Crypto. crypto-fips means the selected AWS-LC provider
attested FIPS mode. It does not certify the consuming binary or deployment.
FIPS policy rejects algorithms outside its approved set, including SHA-1
RSA_OAEP_MGF1P key transport and both signing and verifying RSA_SHA1.
Non-FIPS AWS-LC still verifies inbound RSA-SHA1 Redirect and XML-DSig
signatures. AWS-LC has a narrower algorithm set than RustCrypto. Custom
algorithm URIs are listed in Bergshamra's
provider capabilities.
With crypto-bergshamra enabled:
- XML signatures can be verified against metadata-declared keys.
- Signed-reference placement checks help mitigate XML Signature Wrapping.
- XML-Enc is available. On RustCrypto, software RSA key-transport decryption
stays off until the caller opts in through
XmlEncryptionPolicy. AWS-LC decrypts RSA-OAEP with the default options.
How to surface provider initialisation at startup
Call initialize_crypto_provider during startup when that failure should
appear before the first SAML operation:
Security
#![forbid(unsafe_code)]on the crate root.- DOCTYPE and XXE rejection, with bounded XML parsing before authentication.
- XML escaping for generated templates, metadata endpoint locations, and SAML attribute values.
- Response checks for issuer, status, assertion time window, audience,
destination, recipient, bearer subject confirmation, and
InResponseTo. - Logout checks for issuer and request/response correlation.
- Signed metadata must cover the signed root.
- Signed
AuthnRequestmessages must cover the request root when signed requests are required. - Detached Redirect and SimpleSign signatures are bound to the fields the flow parser consumes.
- HTTP-Redirect raw DEFLATE output is limited.
- Software RSA key-transport decryption is disabled by default on RustCrypto
because that backend, reached through
bergshamraandkryptering, is affected by RUSTSEC-2023-0071. AWS-LC and FIPS do not use that gate.
Schema validation is optional defence in depth through
context::set_schema_validator.
Compatibility crates
New code depends on saml-rs. This repository also publishes four
compatibility packages that re-export the same API:
| Package | Import | docs.rs |
|---|---|---|
opensaml |
opensaml |
docs |
samlify |
samlify |
docs |
rustsaml |
rustsaml |
docs |
samlet |
samlet |
docs |
opensaml still exports the deprecated OpenSamlError alias of SamlError.
opensaml, samlify, and samlet are maintained with saml-rs.
rustsaml is no longer maintained. These packages are separate from
Shibboleth OpenSAML and from the Node.js samlify project.
samael is the other established Rust SAML
crate; it commonly uses the native xmlsec stack.
How to check a change
Follow Contributing.
License
MIT.