Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failure to handle "saml2" and "saml2p" xml namespaces #189

Closed
ghost opened this issue Apr 17, 2017 · 7 comments
Closed

Failure to handle "saml2" and "saml2p" xml namespaces #189

ghost opened this issue Apr 17, 2017 · 7 comments

Comments

@ghost
Copy link

ghost commented Apr 17, 2017

Google Suite Admin tools allows for Google to be used as an Identity Provider. I'm able to successfully authenticate and get a SAML response back. However, the response xml has saml2 and saml2p xml namespaces on the tags. From what I read this format is allowed but discouraged in the 2.0 spec. Source

Looking through the project it appears that all xpath selectors explicitly use saml and samlp namespaces and cannot support the format that google uses.

Here is a condensed response.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response Destination="https://<mydomain.com>/saml/"
                 ID="_5ae2bf4c3ca0049f029c2747fc676160"
                 InResponseTo="ONELOGIN_4aba72b5fe53a808e61200700dd8c9cc37440786"
                 IssueInstant="2017-04-17T15:51:16.076Z" Version="2.0"
                 xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid</saml2:Issuer>
    <saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status>
    <saml2:Assertion ID="_3a4c773d07ced002defb661ac1b728c7" IssueInstant="2017-04-17T15:51:16.076Z"
                     Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        .......
        .......
</saml2p:Response>

Has anyone used this library with Google or do you have suggestions about how I can get around this?

@pitbulk
Copy link
Contributor

pitbulk commented Apr 17, 2017

The toolkit works with Google IdP and saml2 / saml2p namespace.

@ghost
Copy link
Author

ghost commented Apr 18, 2017

Maybe I'm misinterpreting what I'm seeing but take this function for example.

    def validate_num_assertions(self):
        """
        Verifies that the document only contains a single Assertion (encrypted or not)

        :returns: True if only 1 assertion encrypted or not
        :rtype: bool
        """
        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(self.document, '//saml:EncryptedAssertion')
        assertion_nodes = OneLogin_Saml2_Utils.query(self.document, '//saml:Assertion')

        valid = len(encrypted_assertion_nodes) + len(assertion_nodes) == 1

        if (self.encrypted):
            assertion_nodes = OneLogin_Saml2_Utils.query(self.decrypted_document, '//saml:Assertion')
            valid = valid and len(assertion_nodes) == 1

        return valid

This is the first place validating my response fails. The xpath query explicitly uses saml namespace. When I look at my saml response I do have an assertion but it fails when it doesn't find the tag. When I look at the xpath query wrapper it utils.py it specifies a namespace map but that map doesn't include saml2 or saml2p.

    @staticmethod
    def query(dom, query, context=None):
        """
        Extracts nodes that match the query from the Element

        :param dom: The root of the lxml objet
        :type: Element

        :param query: Xpath Expresion
        :type: string

        :param context: Context Node
        :type: DOMElement

        :returns: The queried nodes
        :rtype: list
        """
        if context is None:
            return dom.xpath(query, namespaces=OneLogin_Saml2_Constants.NSMAP)
        else:
            return context.xpath(query, namespaces=OneLogin_Saml2_Constants.NSMAP)
    # Namespaces
    NSMAP = {
        'samlp': NS_SAMLP,
        'saml': NS_SAML,
        'md': NS_MD,
        'ds': NS_DS,
        'xenc': NS_XENC
    }

@pitbulk
Copy link
Contributor

pitbulk commented Apr 18, 2017

I tested in the past and the toolkit Is able to process saml2p / saml2 namespaces

Check this response example with saml2p /saml2 namespace

Is used on that test and you can see is able to extract the nameid value that internally uses the query method.

You can try to modify that test and use:

    def testResponseSignedAssertionNot(self):
        """
        Tests the getNameId method of the OneLogin_Saml2_Response
        Case valid signed response, unsigned assertion
        """
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
        message = self.file_contents(join(self.data_path, 'responses', 'open_saml_response.xml'))
        response = OneLogin_Saml2_Response(settings, b64encode(message))

        self.assertEquals('[email protected]', response.get_nameid())
        from onelogin.saml2.utils import OneLogin_Saml2_Utils
        assertion_nodes = OneLogin_Saml2_Utils.query(response.document, '//saml:Assertion')
        self.assertEquals(len(assertion_nodes), 1)

And you will see how the test pass and the assertion node is found.

If you want send me to my mail your SAMLResponse... and I will try to review if I find something wrong...

@zshauli
Copy link

zshauli commented May 9, 2017

Hi, I just encountered the same exact issue, trying to work with a SAMLResponse from Okta's SSO service.

Here is the response structure:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response Destination="http://localhost:8000/?acs" ID="id22940872238742692662900027" InResponseTo="ONELOGIN_f3c135eb1bcfff5f2478c9f18c5d2a35343d114b" IssueInstant="2017-05-09T08:10:41.616Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/exkaad9tdgNdcPTcu0h7</saml2: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/2001/04/xmldsig-more#rsa-sha256"/>
            <ds:Reference URI="#id22940872238742692662900027">
                <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/2001/04/xmlenc#sha256"/>
                <ds:DigestValue>pvXgG0Me77AKhrAgy2feOOFCX5LqNGWOJNjTeqXRUVc=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>...</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>...</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </saml2p:Status>
    <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        <xenc:EncryptedData Id="_d1a2d16c7d590487bd641ef5083f7604" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:RetrievalMethod Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey" URI="#_4a2a5a0d0bdb360327fb8dc041925b2c"/>
            </ds:KeyInfo>
            <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                <xenc:CipherValue>...</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
        <xenc:EncryptedKey Id="_4a2a5a0d0bdb360327fb8dc041925b2c" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
            </xenc:EncryptionMethod>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:X509Data>
                    <ds:X509Certificate>...</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
            <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                <xenc:CipherValue>...</xenc:CipherValue>
            </xenc:CipherData>
            <xenc:ReferenceList>
                <xenc:DataReference URI="#_d1a2d16c7d590487bd641ef5083f7604"/>
            </xenc:ReferenceList>
        </xenc:EncryptedKey>
    </saml2:EncryptedAssertion>
</saml2p:Response>

@pitbulk
Copy link
Contributor

pitbulk commented May 9, 2017

@zshauli what error have you experienced?

@zshauli
Copy link

zshauli commented May 9, 2017

@pitbulk I'm sorry, I just tried to re-investigate the issue I encountered and I think it is not related to the namespace issue that @kingoftheknoll raised.

Here's the debug print from xmlsec:

x509vfy.c:360(xmlSecOpenSSLX509StoreVerify) obj=x509-store subject=X509_verify_cert msg=subj=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd;err=18;msg=self signed certificate errno=4
x509vfy.c:408(xmlSecOpenSSLX509StoreVerify) obj=x509-store msg=err=18;msg=self signed certificate errno=71
keys.c:1370(xmlSecKeysMngrGetKey) subject=xmlSecKeysMngrFindKey
xmlenc.c:957(xmlSecEncCtxEncDataNodeRead) errno=45
xmlenc.c:715(xmlSecEncCtxDecryptToBuffer) subject=xmlSecEncCtxEncDataNodeRead
keyinfo.c:1414(xmlSecKeyDataEncryptedKeyXmlRead) obj=enc-key msg=cur=1;max=1 errno=61
keyinfo.c:114(xmlSecKeyInfoNodeRead) obj=enc-key subject=xmlSecKeyDataXmlRead msg=node=EncryptedKey
keys.c:1349(xmlSecKeysMngrGetKey) subject=xmlSecKeyInfoNodeRead msg=node=KeyInfo
xmlenc.c:957(xmlSecEncCtxEncDataNodeRead) errno=45
xmlenc.c:715(xmlSecEncCtxDecryptToBuffer) subject=xmlSecEncCtxEncDataNodeRead
xmlenc.c:623(xmlSecEncCtxDecrypt) subject=xmlSecEncCtxDecryptToBuffer

I'll try to debug some more to get to the bottom of this. Thanks.

@pitbulk
Copy link
Contributor

pitbulk commented May 9, 2017

I just recorded a SAMLResponse from Okta with saml2p/saml2 namespace and I was able to validate it with strict = True, and I was able to retrieve NameID and Attributes.

I'm closing now that ticket because I was not able to reproduce any issue related with namespaces with the provided info.

@zshauli If you experience an issue, open a new ticket. Maybe you have some issues with your xmlsec instalation, review #30

@pitbulk pitbulk closed this as completed May 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants