0

I have a Python Flask web app. I am integrating OKTA SAML in this app for authentication.

I have followed the steps in:

However the validation always fails. When I run verify_signature(), it always gives me 0.

My Code:

def verify_signature(signed_info, cert, signature):
    x509 = X509.load_cert_string(base64.decodestring(cert), X509.FORMAT_DER)
    pubkey = x509.get_pubkey().get_rsa()
    verify_EVP = EVP.PKey()
    verify_EVP.assign_rsa(pubkey)
    verify_EVP.reset_context(md='sha256')
    verify_EVP.verify_init()
    verify_EVP.verify_update(signed_info)

    return verify_EVP.verify_final(signature.decode('base64'))

def decode_response(resp):
    return base64.b64decode(resp)

def get_xmldoc(xmlstring):
    return XML.fromstring(xmlstring)

def get_signature(doc):
    return doc.find('{http://www.w3.org/2000/09/xmldsig#}Signature')

def get_signed_info(signature):
    signed_info = signature.find(
        '{http://www.w3.org/2000/09/xmldsig#}SignedInfo')
    signed_info_str = str(signed_info)
    # return parse(StringIO(signed_info_str))
    return signed_info_str

def get_cert(signature):
    ns = '{http://www.w3.org/2000/09/xmldsig#}'
    keyinfo = signature.find('{}KeyInfo'.format(ns))
    keydata = keyinfo.find('{}X509Data'.format(ns))
    certelem = keydata.find('{}X509Certificate'.format(ns))
    return certelem.text

def get_signature_value(signature):
    return signature.find(
        '{http://www.w3.org/2000/09/xmldsig#}SignatureValue').text

# Main Function
dec_resp = decode_response(saml)
xml = get_xmldoc(dec_resp)
signature = get_signature(xml)
signed_info = get_signed_info(signature)
cert = get_cert(signature)
signature_value = get_signature_value(signature)
is_valid = verify_signature(signed_info, cert, signature_value)
print is_valid # ALWAYS PRINTS 0.
Community
  • 1
  • 1

2 Answers2

1

Unless you have a firm grasp of XML parsing, the XML Signature specification, cryptographic hashing, and public key encryption, I strongly urge you not to write your own SAML validation routine.

For some concrete examples of how difficult it is to properly parse SAML, I suggest reading "On Breaking SAML: Be Whoever You Want to Be" which is an excellent academic paper covering the various ways that SAML validation can be bypassed. Additionally, a good recent example of a large company getting SAML validation wrong is "The road to hell is paved with SAML Assertions".

At a high level, I would suggest putting in the effort to learn the idiosyncrasies of an established SAML validation library like PySAML2, that way you can benefit from the work that others have done to avoid common security mistakes in SAML. For PySAML2, the validate_signature method in the saml2/sigver.py file is a good place to start.

If you are still interested in doing your own SAML validation after all of my warnings, then I suggest looking at the signxml library, or using the xmlsec1 binary directly.

Joël Franusic
  • 1,178
  • 8
  • 18
0

I wanted to direct you towards our instructions for Python apps: http://developer.okta.com/docs/guides/pysaml2 In addition, please follow the example for PySAML2 here: https://github.com/jpf/okta-pysaml2-example Do you have a method for handling logout requests?

  • I got my app working using pysaml2. I was also trying to do the signature verification manually for which the above code is being used. But it keeps failing. – Narayan Gowraj Jul 20 '16 at 22:30