Skip to content

workday web-service x509 SignatureVerificationFailed  #1084

Description

@talktome02

Hello folks,

This is my first post. Please bear with me if I have made a mistake.

I am trying to connect to workday web-services with X509 signature. On the workday side, they have enabled the X509 only auth. The workday guy tested this using workday studio. It works there. I couldn't make it work in SOAP UI and below zeep too.

Below is the code snippet.

digest_method = xmlsec.Transform.SHA256
user_name_token = UsernameToken(username)
signature = Signature('priv.pem','cert.pem','password',digest_method=digest_method)

res = client.service.Maintain_Contact_Information(request_data)

I specified the digest_method as the one being generated by zeep in the soap header is different from another envelope (working - generated by workday studio). However, I am still experiencing the below error.

signature.py", line 323, in _verify_envelope_with_key
    raise SignatureVerificationFailed()
zeep.exceptions.SignatureVerificationFailed

Note that I did change the code by following this link which I was earlier experiencing https://github.com/mvantellingen/python-zeep/pull/1077/files.

This is my security tag being generated. For security reasons, I have partially removed some info.

<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><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="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>oX/HaArYLbmqI.....</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>cJRXH66/BqUhiCIXJYjitaK+cZCrHLNdpEJDQHTdfrIE3XjYHcYh7SttM2STQzah.....
hEXtSrnZR1Wpl0myk1LqQ==</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference><X509Data>
<X509IssuerSerial>
<X509IssuerName>CN=Test Certificate generated by Workday Studio</X509IssuerName>
<X509SerialNumber>1588598576028</X509SerialNumber>
</X509IssuerSerial>
<X509Certificate>MIIC5zCCAc8CBgFx39qTnDANBgkqhkiG9w0BAQsFADA3MTUwMwYDVQQDEyxUZXN0
IENlcnRpZmljYXRlIGdlbmVyYXRlZCBieSBXb3JrZGF5IFN0dWRpbzAeFw0yMDA1
MDQxMzIyNTZaFw0zMDA1MTIxMz........</X509Certificate>
</X509Data>
</wsse:SecurityTokenReference></KeyInfo>
</Signature><wsse:UsernameToken><wsse:Username>ISU_accountname@workdaytenant</wsse:Username></wsse:UsernameToken>
</wsse:Security>

One thing I did observe in the soap header (working in workday studio) is that the wsse:SecurityTokenReference is absent. Not sure what it means at this time.

Please help !

Activity

talktome02 commented on May 20, 2020

@talktome02
Author

I finally managed to connect to workday. However, I had to patch the source code.

Here is some info on the same

  1. I encountered the 'list' object has no attribute 'verify'. I follow the simple bug fix 1077.
if client.wsse: 
    # client.wsse.verify(doc) 
    if isinstance(client.wsse, list): 
        for wsse in client.wsse: 
            wsse.verify(doc) 
    else: 
        client.wsse.verify(doc) 
  1. I also encountered zeep.exceptions.SignatureVerificationFailed. Upon verification, it seems the code is checking for security information in the response header which workday was not providing. Had to comment the below line of code in /zeep/wsse/signature.py at line 71
def verify(self, envelope): 
    key = _make_verify_key(self.cert_data) 
    # _verify_envelope_with_key(envelope, key) 
    return envelope 
  1. Like I mentioned in my problem statement, the payload being generated by zeep contained the
    wsse:SecurityTokenReference which the workday studio tester payload was not. So, I reverse engineered to see if I can match the payload to what workday studio tester was generating. Below is the change I had to do /zeep/wsse/signature.py
 # sec_token_ref = etree.SubElement(key_info, QName(ns.WSSE, "SecurityTokenReference"))
    sec_token_ref = []
    return security, sec_token_ref, x509_data
  1. There were a couple more edits I had to do based on link. Below is the change I made in signature.py
# xmlsec.template.add_transform(ref, xmlsec.Transform.EXCL_C14N)
    xmlsec.template.add_transform(ref, xmlsec.Transform.ENVELOPED)

another here

    ref = xmlsec.template.add_reference(
        # signature, digest_method or xmlsec.Transform.SHA1, uri="#" + node_id
        signature, digest_method or xmlsec.Transform.SHA1, uri=""
    )

I was finally able to generate the payload and got a successful response.

@mvantellingen - Could you take a look at these changes and vet them? I am a noob in making changes to the source code. However, if you could take a look a look, I'd really be grateful to you. I would like to understand if by doing these above changes, I am not compromising the security of the zeep package as we intend to go ahead use it with X509 auth.

@erwaller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions