Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 9 additions & 5 deletions lib/saml2.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,17 @@ certificate_to_keyinfo = (use, certificate) ->
check_saml_signature = (xml, certificate, cb) ->
doc = (new xmldom.DOMParser()).parseFromString(xml)

signature = xmlcrypto.xpath(doc, ".//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")
return false unless signature.length is 1
signatures = xmlcrypto.xpath(doc, ".//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")
return false unless signatures.length

sig = new xmlcrypto.SignedXml()
sig.keyInfoProvider = getKey: -> format_pem(certificate, 'CERTIFICATE')
sig.loadSignature signature[0].toString()
return sig.checkSignature xml

for signature in signatures
sig.loadSignature signature.toString()
return false unless sig.checkSignature(xml)

return true

# Takes in an xml @dom containing a SAML Status and returns true if at least one status is Success.
check_status_success = (dom) ->
Expand Down Expand Up @@ -541,4 +546,3 @@ if process.env.NODE_ENV is "test"
module.exports.get_session_index = get_session_index
module.exports.parse_assertion_attributes = parse_assertion_attributes
module.exports.set_option_defaults = set_option_defaults

1 change: 1 addition & 0 deletions test/data/good_assertion_multiple.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<root><book><name Id="name">Harry Potter</name><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="#name"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>vfIC/QjiDGknywC9PImPk1nEbr4=</DigestValue></Reference></SignedInfo><SignatureValue>gv0nnrEvrQg8P8apOJGGwkANWyCnkbIID0Ds8pUNMayP1Jh23VLRli+J983RpXa8haPfHpPJB72ByXp/ElpFdFaHL5wh2GmsIKgMpWPshFi9Xu/S7zTTZ87I/ax1eo0hA07dS4GGZGrWXKjNEQrllYsYyhxGm3V11F0gYruNgwGwUoFSpL59KbpbQi4yfKjqesS8jRTAREzEhalyUvy2IgrZ9chFIxtqyylhaRSxWY2NbdsmC+cbMf2BQb52FEYQmQmtS6stRrRpJUIlFAHUz0lHTWgzGibqWwc5AHLuN1fyVr0CyqTZs2/jxeYt/czn/pxZQLOXIfI9OsRbHIgqXA==</SignatureValue></Signature></book><banana><age Id="age">22</age><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="#age"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>zQy/Rr+zKlp9CcZvPmWaskedAMM=</DigestValue></Reference></SignedInfo><SignatureValue>dazQQsLS8kyLAl30KL/ntwJ0Cg59w9rL2V4iXypAsecJ33AsCiN+5KEZTgb/+aj04/R3Y/HXjKw8qq9zQUTiXs6uJYI+cMBNrm3hNNSVF7yZ6QbeIe6WRREyQM0xNa2q6GMBqhgcF35Chwtf8Y93pYKYFQ301QZXCiM0WqnFXMA7UrwsuNTgWkC2u89fKk3kVDjDUenwHCAsplvt5q7MwnMd9+vOJGWyQMme0pBZ6liTxsVUwcLa7ximhYXtWCqdPrkqy7XZB60MoOAYBlmxqT+ZFb+cxWVRp0K+LjLlXpAS39lrVhZZ75rgjFYIyUuZTQ2PLC/ILBod4LgICUGzLg==</SignatureValue></Signature></banana></root>
11 changes: 7 additions & 4 deletions test/saml2.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ describe 'saml2', ->
it 'rejects xml with an invalid signature', ->
assert.equal false, saml2.check_saml_signature(get_test_file("good_assertion.xml"), get_test_file("test2.crt"))

it 'validates all signatures if more than one exist', ->
assert saml2.check_saml_signature(get_test_file("good_assertion_multiple.xml"), get_test_file("test.crt"))

describe 'check_status_success', =>
it 'accepts a valid success status', =>
assert saml2.check_status_success(@good_response_dom), "Did not get 'true' for valid response."
Expand Down Expand Up @@ -344,7 +347,7 @@ describe 'saml2', ->
'http://schemas.xmlsoap.org/claims/CommonName': [ 'Test Student' ]
assert.deepEqual response, expected_response
# make sure response can be deflated, since redirect requests need to be inflated
zlib.deflateRaw new Buffer(response, 'base64'), (err, deflated) =>
zlib.deflateRaw new Buffer(JSON.stringify(response), 'base64'), (err, deflated) =>
assert not err?, "Got error: #{err}"
done()

Expand Down Expand Up @@ -412,7 +415,7 @@ describe 'saml2', ->
sso_login_url: 'https://idp.example.com/login'
sso_logout_url: 'https://idp.example.com/logout'
certificates: 'other_service_cert'
request_options =
request_options =
assert_endpoint: 'https://sp.example.com/assert'
relay_state: 'Some Relay State!'
nameid_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
Expand All @@ -438,7 +441,7 @@ describe 'saml2', ->
sso_login_url: 'https://idp.example.com/login'
sso_logout_url: 'https://idp.example.com/logout'
certificates: 'other_service_cert'
request_options =
request_options =
assert_endpoint: 'https://sp.example.com/assert'
relay_state: 'Some Relay State!'

Expand Down Expand Up @@ -492,7 +495,7 @@ describe 'saml2', ->
name_id: 'name_id'
session_index: 'session_index'
sign_get_request: true

sp = new saml2.ServiceProvider sp_options
idp = new saml2.IdentityProvider idp_options

Expand Down