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

Add workaround for inclusive namespaces #68

Merged
merged 2 commits into from
Jun 24, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion lib/saml2.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,35 @@ pretty_assertion_attributes = (assertion_attributes) ->
.object()
.value()

# takes in an XML string, returns an XML string
# applies all inclusive namespaces for signature assertions onto assertion tag
# used as recommended workaround for xml-crypto library limitation with inclusive namespaces
# see https://github.com/yaronn/xml-crypto/issues/48#issuecomment-129705816
add_namespaces_to_child_assertions = (xml_string) ->
doc = new xmldom.DOMParser().parseFromString xml_string

response_elements = doc.getElementsByTagNameNS "urn:oasis:names:tc:SAML:2.0:protocol", "Response"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the constant XMLNS.SAMLP

return xml_string if response_elements.length isnt 1
response_element = response_elements[0]

assertion_elements = response_element.getElementsByTagNameNS "urn:oasis:names:tc:SAML:2.0:assertion", "Assertion"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XMLNS.SAML

return xml_string if assertion_elements.length isnt 1
assertion_element = assertion_elements[0]

inclusive_namespaces = assertion_element.getElementsByTagNameNS("http://www.w3.org/2001/10/xml-exc-c14n#", "InclusiveNamespaces")[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be better to add this to the constant list above and use that here.

return xml_string if not inclusive_namespaces
return xml_string if assertion_element.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").length is 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XMLNS.DS

prefix_list = inclusive_namespaces.getAttribute("PrefixList")

# add the namespaces that are present in response and missing in assertion.
for ns in prefix_list.split " "
if response_element.getAttribute("xmlns:" + ns) and !assertion_element.getAttribute("xmlns:" + ns)
new_attribute = doc.createAttribute "xmlns:" + ns
new_attribute.value = response_element.getAttribute "xmlns:" + ns
assertion_element.setAttributeNode new_attribute

return new xmldom.XMLSerializer().serializeToString response_element

# Takes a DOM of a saml_response, private keys with which to attempt decryption and the
# certificate(s) of the identity provider that issued it and will return a user object containing
# the attributes or an error if keys are incorrect or the response is invalid.
Expand Down Expand Up @@ -522,7 +551,8 @@ module.exports.ServiceProvider =

(response_buffer, cb_wf) =>
debug saml_response
saml_response = (new xmldom.DOMParser()).parseFromString(response_buffer.toString())
saml_response_abnormalized = add_namespaces_to_child_assertions(response_buffer.toString())
saml_response = (new xmldom.DOMParser()).parseFromString(saml_response_abnormalized)

try
response = { response_header: parse_response_header(saml_response) }
Expand Down