How do you parse the Signature element from a SAML response using xmlcrypto?
-
21-12-2019 - |
Question
I am trying to use xmlcrypto to parse out and validate the <ds:Signature>
element from a SAML response. The response was received from my SSOCircle test Identity Provider (see below for complete SAML Response) and appears to be a standard samlp
response which contains an Assertion that has been correctly signed using an xml digital signature.
Here is the code I am using. This has been taken from the xmlcrypto help on github.
CoffeeScript
validateSignature: (saml) ->
doc = new @xmldom.DOMParser().parseFromString saml
signature = @xmlCrypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0]
signed = new @xmlCrypto.SignedXml null, idAttribute: 'AssertionID'
signed.loadSignature signature.toString() # this line fails as signature is undefined
As you can see, the code above uses the xmlCrypto.xpath()
function to retrieve the <ds:Signature>
element from the parsed xml document, however the result of this function is always undefined
SAML Response
<samlp:Response ID="s208442fc7db110e1a6e9df3f6f1c66ff8cd64219c" InResponseTo="_de666b2c-1b3c-de17-1cde-0d97211b1ddd" Version="2.0" IssueInstant="2014-07-29T14:33:45Z" Destination="https://localhost/security/saml2/response" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://idp.ssocircle.com</saml:Issuer>
<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
</samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
</samlp:Status>
<saml:Assertion ID="s2b6bb561a07e30465057af94c7aff92f8b0e11143" IssueInstant="2014-07-29T14:33:45Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://idp.ssocircle.com</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#s2b6bb561a07e30465057af94c7aff92f8b0e11143">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>Lvm7MFE/Chy3gR97omBDlkNmwO0=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>GUBxQmOF0yWvC [...] YslXU=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICjDCCAXSg [...] WjeU5FLwDZR0Q=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="http://idp.ssocircle.com">biofractal@gmail.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="_de666b2c-1b3c-de17-1cde-0d97211b1ddd" NotOnOrAfter="2014-07-29T14:43:45Z" Recipient="https://localhost/security/saml2/response" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2014-07-29T14:23:45Z" NotOnOrAfter="2014-07-29T14:43:45Z">
<saml:AudienceRestriction>
<saml:Audience>gp-sso-localhost</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-07-29T08:47:22Z" SessionIndex="s2cd309df973ca61fd0b359e968208375f65d35b01">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
</samlp:Response>
Solution
The problem was with the xpath, which is specific for saml that contains its signature in the root. To find the signature within the inner assertion you need to use the following line, with the xpath updated:
signature = @xmlCrypto.xpath(doc, ".//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0]