mod config;
mod handler;
mod linking;
mod registry;
mod replay;
mod store;
mod verify;
pub use config::{
SamlAttributeMapping, SamlIdpConfig, SamlIdpConfigBuilder,
content_encryption_algorithm_allowed, key_transport_algorithm_allowed,
};
pub use handler::{SamlAuthState, saml_acs, saml_login, saml_metadata, saml_routes};
pub use linking::{effective_saml_email_verified, saml_provider_key};
pub use registry::{
CertExpiryWarning, DEFAULT_EXPIRY_WARNING_DAYS, DEFAULT_REFRESH_INTERVAL, IdpSource,
SamlIdpRegistry, SpKeyMaterial,
};
pub use replay::{PG_SAML_REPLAY_SCHEMA_SQL, PgSamlReplayStore, SamlReplayCache, SamlReplayStore};
pub use store::{PG_SAML_IDP_SCHEMA_SQL, PgSamlIdpStore, SamlIdpRecord, SamlIdpSpec, SamlIdpStore};
pub use verify::{VerifiedAssertion, verify_saml_response};
#[cfg(test)]
mod tests;
#[derive(Debug, thiserror::Error)]
pub enum SamlError {
#[error("SAML configuration error: {0}")]
Config(String),
#[error("malformed SAMLResponse: {0}")]
Malformed(String),
#[error("SAMLResponse contained a DOCTYPE or entity declaration; rejected (XXE defense)")]
DocTypeForbidden,
#[error("SAML assertion verification failed: {0}")]
Verification(String),
#[error("SAML assertion replay detected (assertion ID already consumed)")]
Replay,
#[error("SAML assertion missing required field: {0}")]
MissingField(&'static str),
#[error("SAML IdP store error: {0}")]
Store(String),
#[error(
"SAML IdP name '{0}' is already in use (names are never reissued, including after \
deletion, because the name is the account-store provider namespace)"
)]
NameTaken(String),
#[error("no such SAML IdP: {0}")]
NotFound(String),
}