Guide
SSO and SAML Security: A Guide for SaaS Founders
SAML-based SSO is secure when implemented correctly, but common mistakes like weak certificate validation, improper XML parsing, and missing expiration checks introduce vulnerabilities. To secure SAML, enforce certificate pinning, validate signatures on every assertion, use strict XML parsing to prevent injection, and set short assertion lifetimes. Avoid accepting unsigned assertions or using insecure algorithms like SHA-1.
What Makes SAML Vulnerable?
SAML is an XML-based protocol that exchanges authentication and authorization data between an identity provider (IdP) and a service provider (your app). The security relies on digital signatures and encryption, but implementation flaws often break this trust. The most common vulnerabilities are:
- Missing signature validation, The app does not verify the XML signature on the SAML response.
- XML signature wrapping attacks, An attacker modifies the XML structure while keeping a valid signature on a benign part.
- Weak certificate trust, The app trusts any certificate from the IdP, or does not pin certificates.
- Replay attacks, An attacker captures a valid SAML response and reuses it later.
- Improper XML parsing, XXE (XML External Entity) attacks or injection via malformed XML.
Certificate and Signature Validation
Always validate the XML signature on the SAML response and assertion. Use the exact certificate you expect from your IdP, and pin it in your application. Do not accept self-signed certificates without verification and do not trust a certificate chain that includes unknown roots. Example: if your IdP uses a specific X.509 certificate, store its public key and verify the signature against that key, not just any certificate in the response. Also, verify that the signature algorithm is strong (e.g., RSA-SHA256, not SHA1).
Preventing XML Signature Wrapping
XML signature wrapping attacks exploit how the XML signature is associated with the signed element. The attacker moves the signed element to a different part of the document and inserts a new unsigned element with malicious content. To prevent this, after validating the signature, extract the assertion by its ID and verify that the signed element matches exactly the element you intend to use. Do not rely on the signature's reference URI alone. Use libraries that are known to resist wrapping attacks, such as OpenSAML (Java) or python3-saml with proper configuration.
Assertion Lifetime and Replay Prevention
Set a short NotOnOrAfter condition on the assertion (e.g., 5 minutes) and enforce it server-side. Also, check the NotBefore condition to prevent use of future-dated assertions. For replay protection, maintain a cache of assertion IDs that have been consumed. Reject any assertion with an ID that has already been seen. Use a distributed cache (like Redis) if you have multiple app servers to ensure consistency.
XML Parsing and Injection Defense
Always parse SAML XML with a secure parser that disables external entity resolution. This prevents XXE attacks that can leak files or cause denial of service. In Java, use DocumentBuilderFactory with setFeature("http://apache.org/xml/features/disallow-doctype-decl", true). In Python, use defusedxml library. Also, validate all fields extracted from the assertion (e.g., NameID, attributes) against expected patterns. For example, if you expect an email, reject values containing special characters like "|" or "&".
Configuration Hardening Checklist
| Check | Action |
|---|---|
| Signature required | Reject unsigned SAML responses and assertions. |
| Certificate pinning | Hardcode the IdP's public key or certificate fingerprint. |
| Strong algorithms | Only allow RSA-SHA256 or better; reject SHA-1, MD5. |
| Assertion expiry | Enforce NotOnOrAfter < 5 minutes; check NotBefore. |
| Unique ID tracking | Cache used assertion IDs for at least the lifetime of the assertion. |
| XML parser | Disable DOCTYPE, external entities, and DTD processing. |
| Input validation | Sanitize all SAML attribute values before use. |
Testing Your SAML Implementation
Use a test IdP like Samltool or Okta's test environment to craft malicious SAML responses. Try unsigned assertions, modified attributes, expired timestamps, and XML wrapping payloads. Also, perform a penetration test that specifically targets your SSO endpoint. If you want continuous automated testing, consider a tool that can simulate attacks on your SAML flow. Start a free scan with Kyro, an AI penetration tester that hunts for real vulnerabilities including SAML misconfigurations.
Find these bugs in your own app
Kyro runs an AI security hunter against your SaaS and emails you the moment it confirms a real, reproducible vulnerability.
Start a free scanFrequently asked questions
What is the biggest security risk with SAML SSO?
The biggest risk is not validating the XML signature on the SAML response. Attackers can forge a valid-looking response and impersonate any user.
How do I prevent SAML replay attacks?
Track assertion IDs in a cache and reject duplicates. Also set a short assertion lifetime (e.g., 5 minutes) to limit the window of reuse.
Should I use SAML or OAuth for SSO?
SAML is designed for enterprise SSO with strong security requirements. OAuth is better for delegated access to APIs. For user authentication, SAML is more mature but OIDC (built on OAuth 2.0) is simpler and modern.
Can I trust the IdP's certificate automatically?
No. You should pin the specific certificate or public key from your IdP. Trusting any certificate from the IdP's domain can allow man-in-the-middle attacks if the IdP's certificate authority is compromised.