I am running into the problem with validating the signature for the SAML 2.0 Assertion XML. I am using the SAML2 library from simpleSAMLphp project, which in turn is using the PHP xmlseclibs
library for signing XML and verifying the signatures.
I am receiving the following assertion from my partner:
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_c43265fe-8cd5-410f-b63d-dac9f266d4c9" IssueInstant="2015-01-23T17:46:28.456Z"><saml:Issuer>uat.test.com/saml2.0</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="#_c43265fe-8cd5-410f-b63d-dac9f266d4c9"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>mFKEIdw+cEielORqscbHuAJhI58=</DigestValue></Reference></SignedInfo><SignatureValue>kEZHloxYJVqDg8oxLNpl+sbJYhv9r7yYU5yQi71gCNm/Cdtj9/P2LR5cnopKZZu+7j3PVimeZoir6RTTrdVKTLkp+PmvOmTlLH/LVtntQZ68TaUxUd3BvtQiKuJ8KFwWPmQ+W3RIKv4ySAsy6PUiWPcr8eIYpIiUA6rxCuSEpdA=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIICczCCAdygAwIBAgIEdWfFczANBgkqhkiG9w0BAQUFADB0MQswCQYDVQQIEwJNQTEQMA4GA1UEBxMHTm9yd29vZDEPMA0GA1UEChMGTWVyY2VyMRswGQYDVQQLExJNZXJjZXIgSFIgU2VydmljZXMxJTAjBgNVBAMTHE1lcmNlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNjI5MDI1NTQxWhcNMTcwNzI5MDQwMDAwWjB2MQswCQYDVQQIEwJNQTEQMA4GA1UEBxMHTm9yd29vZDEPMA0GA1UEChMGTWVyY2VyMRswGQYDVQQLExJNZXJjZXIgSFIgU2VydmljZXMxJzAlBgNVBAMTHk1lcmNlciBIdW1hbiBSZXNvdXJjZSBTZXJ2aWNlczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAm9KNx7UmRbWwJ0gmIV9sZzMDH4uz+o6ZmOxVRLvrO0Yzc9Qsc+7f+jIEGsVpbeaj5zx+4c8g46QqGam/Ap+4peewduVAN7GwK8UrmveASQH1Y/byTVGhyndfEtHfauresYpNDbgCn/iq/cXNapuFaTB4U0MPtz8Bqds1871hNasCAwEAAaMQMA4wDAYDVR0PBAUDAwf/gDANBgkqhkiG9w0BAQUFAAOBgQBR5wV43k1XcIM7z24SBvpEDWgEawXZ3TjTI9/54v/ZAdzXAiYfLKVV+hiyum+QP9jezDUH+Wz2bqzjlxOSU7HvUn4MwN+88a1hvSXpPxsp7y4d7juVt66aip/9NuSWbNqUPdhgK/KvMHrZpksCoxUJG2+Q1Jz7aNiBQvONRRPdTg==</X509Certificate></X509Data></KeyInfo></Signature><saml:Subject><saml:NameID>000786320</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-01-23T17:51:28.471Z" Recipient="https://test.com/sso"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-01-23T17:41:28.456Z" NotOnOrAfter="2015-01-23T17:51:28.456Z"><saml:AudienceRestriction><saml:Audience>test.com:saml2.0</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-01-23T17:46:28.456Z" SessionIndex="SI-8bd89651-62da-4b7d-9a54-04eb2eb90784"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="email"><saml:AttributeValue>[email protected]</saml:AttributeValue></saml:Attribute><saml:Attribute Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="firstName"><saml:AttributeValue>Diane</saml:AttributeValue></saml:Attribute><saml:Attribute Name="lastname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="lastname"><saml:AttributeValue>Test</saml:AttributeValue></saml:Attribute><saml:Attribute Name="zipCode" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="zipCode"><saml:AttributeValue>02062</saml:AttributeValue></saml:Attribute><saml:Attribute Name="businessUnit" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="businessUnit"><saml:AttributeValue>78945</saml:AttributeValue></saml:Attribute><saml:Attribute Name="employeeID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="employeeID"><saml:AttributeValue>000786320</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>
The signature element requests exclusive C14N canonicalization. The xmlseclibs
library library canonicalizes this as following:
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_c43265fe-8cd5-410f-b63d-dac9f266d4c9" IssueInstant="2015-01-23T17:46:28.456Z" Version="2.0"><saml:Issuer>uat.test.com/saml2.0</saml:Issuer><saml:Subject><saml:NameID>000786320</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-01-23T17:51:28.471Z" Recipient="https://test.com/sso"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-01-23T17:41:28.456Z" NotOnOrAfter="2015-01-23T17:51:28.456Z"><saml:AudienceRestriction><saml:Audience>test.com:saml2.0</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-01-23T17:46:28.456Z" SessionIndex="SI-8bd89651-62da-4b7d-9a54-04eb2eb90784"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute FriendlyName="email" Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>[email protected]</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="firstName" Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>Diane</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="lastname" Name="lastname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>Test</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="zipCode" Name="zipCode" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>02062</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="businessUnit" Name="businessUnit" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>78945</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="employeeID" Name="employeeID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>000786320</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>
However the element my partner actually signs is this:
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_c43265fe-8cd5-410f-b63d-dac9f266d4c9" IssueInstant="2015-01-23T17:46:28.456Z" Version="2.0"><saml:Issuer>uat.test.com/saml2.0</saml:Issuer><saml:Subject><saml:NameID>000786320</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-01-23T17:51:28.471Z" Recipient="https://test.com/sso"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-01-23T17:41:28.456Z" NotOnOrAfter="2015-01-23T17:51:28.456Z"><saml:AudienceRestriction><saml:Audience>test.com:saml2.0</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-01-23T17:46:28.456Z" SessionIndex="SI-8bd89651-62da-4b7d-9a54-04eb2eb90784"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute FriendlyName="email" Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>[email protected]</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="firstName" Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>Diane</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="lastname" Name="lastname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>Test</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="zipCode" Name="zipCode" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>02062</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="businessUnit" Name="businessUnit" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>78945</saml:AttributeValue></saml:Attribute><saml:Attribute FriendlyName="employeeID" Name="employeeID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>000786320</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>
Pretty much the same, however without the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
namespace. The xsi
namespace is mentioned in the signature Transform elements: <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/></Transform>
The SAML authentication fails because of this since the SHA1 digest in the signature does not match the digest xmlseclibs calculated on the element.
So I was wondering who is correct here -- does the xsi namespace have to be included (even though there are no elements in this namespace) because it is included in the InclusiveNamespaces, or if it is not, why does xmlseclibs
includes that namespace there with C14N canonicalization?
Canonicalization, which appears a couple of times above, is simply a way to convert an XML document into bytes so that "equivalent" XML documents produce the same sequence of bytes.
A SAML (Security Assertion Markup Language) attribute assertion contains information about a user in the form of a series of attributes. The Retrieve from SAML Attribute Assertion can retrieve these attributes and store them in the attribute. lookup.
A SAML (Security Assertions Markup Language) authentication assertion is issued as proof of an authentication event. Typically an end-user will authenticate to an intermediary, who generates a SAML authentication assertion to prove that it has authenticated the user.
Actually some further debugging showed that the problem was with a bug in the SAML2 library (which is a part of smipleSAMLphp project: https://github.com/simplesamlphp/saml2).
When decrypting element SAML2 library does this:
$xml = '<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" '.
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' .
$decrypted .
'</root>';
$newDoc = new DOMDocument();
(see https://github.com/simplesamlphp/saml2/blob/master/src/SAML2/Utils.php line 494)
This is a workaround in case there would be some orphan elements when only a subset of the document was serialized for encryption. Unfortunately this creates an extra xsi
namespace, which shows up in the canonicalization down the road if xsi
is included in the InclusiveNamespaces PrefixList.
Changing it to:
$xml = '<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">'.
$decrypted .
'</root>';
$newDoc = new DOMDocument();
actually does the trick in my case. However this is just a q quick hack and is not ideal since it may introduce some other errors for different implementations. I guess will need to work with the creators of the simpleSAMLphp library to find a more elegant solution for the long term.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With