SAML Signature Basics
SAML Responses are protected with XML Signatures. This page covers how signatures are structured, what to check when verifying them, and how to run certificate operations safely.
🔏 Signature Structure
Signatures live under ds:Signature and may target the Assertion or the entire Response. Verification uses the IdP-provided X.509 certificate.
Core elements
- 📌 The target can be the Assertion or the full Response (sometimes both).
- 📌 Signature is stored in ds:Signature and verified with an X.509 certificate.
- 📌 A wrong Reference URI (scope) causes verification to fail.
🛡️ Verification Tips
Check not only the signature itself but also the conditions and certificate state.
Common checks
- ✅ Time drift causes NotBefore / NotOnOrAfter failures.
- ✅ Audience must match the expected EntityID.
- ✅ Ensure the signature covers the expected element (Assertion/Response).
- ✅ Watch for expired or malformed certificates.
Certificate operations
- 🔁 Track rotation schedules and update metadata in advance.
- 🔁 Use CRL/OCSP if provided to check revocation.
- 🔁 If key pinning is used, deploy new keys in the right order to avoid lockouts.
- 🔁 Keep test and production certificates separate to avoid mix-ups.
🧯 Common Errors and Fixes
Signature failures have recurring patterns; knowing them speeds up troubleshooting.
Typical cases
- ⚠️ Signature verification errors: wrong certificate, wrong reference, possible tampering.
- ⚠️ XML parsing errors: Deflate/Base64 decoding failures.
- ⚠️ Condition mismatch: time drift or audience mismatch.
How to troubleshoot
- 🧭 Check the Reference URI and certificate fingerprint shown in logs.
- 🧭 Verify NTP/timezone to rule out clock skew.
- 🧭 Re-import IdP/SP metadata to eliminate mismatches.
SubjectConfirmation / Conditions checks
SubjectConfirmation (especially Bearer) and Conditions must be validated; mismatches mean the assertion is not intended for the recipient.
- SubjectConfirmationData Recipient matches the ACS URL.
- NotBefore/NotOnOrAfter are within the current time window.
- Conditions > AudienceRestriction matches the expected EntityID.