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>
Was it helpful?

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]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top