From 049ca2ef037bd5d6f6babed2acbaf9acf535d055 Mon Sep 17 00:00:00 2001 From: Xavier Talpe Date: Mon, 27 Jun 2016 11:02:16 +0200 Subject: [PATCH 1/2] Prevent "SAML Assertion not found error" when an EncryptedAssertion is next to the Signature in the document root. --- lib/saml2.coffee | 56 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/lib/saml2.coffee b/lib/saml2.coffee index afe255c..3809260 100644 --- a/lib/saml2.coffee +++ b/lib/saml2.coffee @@ -413,36 +413,54 @@ parse_authn_response = (saml_response, sp_private_keys, idp_certificates, allow_ async.waterfall [ (cb_wf) -> - decrypt_assertion saml_response, sp_private_keys, (err, result) -> - return cb_wf null, result unless err? - return cb_wf err, result unless allow_unencrypted - assertion = saml_response.getElementsByTagNameNS(XMLNS.SAML, 'Assertion') - unless assertion.length is 1 - return cb_wf new Error("Expected 1 Assertion or 1 EncryptedAssertion; found #{assertion.length}") - cb_wf null, assertion[0].toString() - (result, cb_wf) -> - debug result + unencrypted_assertions = saml_response.getElementsByTagNameNS( XMLNS.SAML, 'Assertion' ) + encrypted_assertions = saml_response.getElementsByTagNameNS( XMLNS.SAML, 'EncryptedAssertion' ) + + nb_assertions = unencrypted_assertions.length + encrypted_assertions.length + unless nb_assertions is 1 + return cb_wf new Error("Expected one Assertion or EncryptedAssertion. Found #{unencrypted_assertions.length} Assertions and #{encrypted_assertions.length} EncryptedAssertions") + + if encrypted_assertions.length == 1 + decrypt_assertion saml_response, sp_private_keys, (err, result) -> + return cb_wf err, result + else if unencrypted_assertions.length == 1 and allow_unencrypted + return cb_wf null, unencrypted_assertions[0].toString() + else + return cb_wf new Error("Found one unencrypted Assertion but flag 'allow_unencrypted' is set to false!") + (decrypted_assertion, cb_wf) -> + debug decrypted_assertion if ignore_signature - return cb_wf null, (new xmldom.DOMParser()).parseFromString(result) + return cb_wf null, (new xmldom.DOMParser()).parseFromString(decrypted_assertion) - saml_response_str = saml_response.toString() for cert in idp_certificates or [] - signed_data = check_saml_signature(result, cert) or check_saml_signature saml_response_str, cert + # Signature is either part of the assertion node or the root node. + signatures_from_assertion = check_saml_signature decrypted_assertion, cert + signatures_from_response = check_saml_signature saml_response.toString(), cert + + signed_data = signatures_from_assertion or signatures_from_response unless signed_data continue # Cert was not valid, try the next one for sd in signed_data signed_dom = (new xmldom.DOMParser()).parseFromString(sd) - assertion = signed_dom.getElementsByTagNameNS(XMLNS.SAML, 'Assertion') - if assertion.length is 1 - return cb_wf null, signed_dom + + if signatures_from_assertion + assertion = signed_dom.getElementsByTagNameNS( XMLNS.SAML, 'Assertion' ) + if assertion.length is 1 + return cb_wf null, signed_dom + else + return cb_wf new Error( "Signed data does not contain a SAML Assertion!" ) + else if signatures_from_response + decrypted_assertion_dom = (new xmldom.DOMParser()).parseFromString(decrypted_assertion) + return cb_wf null, decrypted_assertion_dom + return cb_wf new Error("Signed data did not contain a SAML Assertion!") return cb_wf new Error("SAML Assertion signature check failed! (checked #{idp_certificates.length} certificate(s))") - (decrypted_assertion, cb_wf) -> + (decrypted_assertion_dom, cb_wf) -> try - user.name_id = get_name_id decrypted_assertion - user.session_index = get_session_index decrypted_assertion - assertion_attributes = parse_assertion_attributes decrypted_assertion + user.name_id = get_name_id decrypted_assertion_dom + user.session_index = get_session_index decrypted_assertion_dom + assertion_attributes = parse_assertion_attributes decrypted_assertion_dom user = _.extend user, pretty_assertion_attributes(assertion_attributes) user = _.extend user, attributes: assertion_attributes cb_wf null, { user } From e90a9331bedb50b10b9c44604bb24ab1f9d7bfad Mon Sep 17 00:00:00 2001 From: Xavier Talpe Date: Mon, 27 Jun 2016 12:14:06 +0200 Subject: [PATCH 2/2] Unused variable. --- lib/saml2.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/saml2.coffee b/lib/saml2.coffee index 3809260..6dab172 100644 --- a/lib/saml2.coffee +++ b/lib/saml2.coffee @@ -556,7 +556,6 @@ module.exports.ServiceProvider = return setImmediate cb, new Error("Request body does not contain SAMLResponse or SAMLRequest.") saml_response = null - decrypted_assertion = null response = {} async.waterfall [