test/response_test.rb in ruby-saml-0.8.13 vs test/response_test.rb in ruby-saml-0.8.14
- old
+ new
@@ -2,11 +2,14 @@
class ResponseTest < Minitest::Test
describe "Response" do
it "raise an exception when response is initialized with nil" do
- assert_raises(ArgumentError) { OneLogin::RubySaml::Response.new(nil) }
+ err = assert_raises(ArgumentError) do
+ OneLogin::RubySaml::Response.new(nil)
+ end
+ assert_equal "Response cannot be nil", err.message
end
it "be able to parse a document which contains ampersands" do
XMLSecurity::SignedDocument.any_instance.stubs(:digests_match?).returns(true)
OneLogin::RubySaml::Response.any_instance.stubs(:validate_conditions).returns(true)
@@ -43,16 +46,75 @@
assert response.name_id.nil?
end
end
describe "#validate!" do
+ it "raise when settings not initialized" do
+ response = OneLogin::RubySaml::Response.new(response_document)
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.validate!
+ end
+ assert_equal "No settings on response", err.message
+ end
+
it "raise when encountering a condition that prevents the document from being valid" do
response = OneLogin::RubySaml::Response.new(response_document)
- assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.settings = settings
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
response.validate!
end
+ assert_equal "Current time is on or after NotOnOrAfter condition", err.message
end
+
+ it "raises an exception when no cert or fingerprint provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = nil
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.validate!
+ end
+ assert_equal "No fingerprint or certificate on settings", err.message
+ end
+
+ it "raise when no signature" do
+ response_no_signed_elements = OneLogin::RubySaml::Response.new(read_invalid_response("no_signature.xml.base64"))
+ settings.idp_cert_fingerprint = signature_fingerprint_1
+ response_no_signed_elements.settings = settings
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response_no_signed_elements.validate!
+ end
+ assert_equal "Found an unexpected number of Signature Element. SAML Response rejected", err.message
+ end
+
+ it "raise when multiple signatures" do
+ response_multiple_signed = OneLogin::RubySaml::Response.new(read_invalid_response("multiple_signed.xml.base64"))
+ settings.idp_cert_fingerprint = signature_fingerprint_1
+ response_multiple_signed.settings = settings
+ response_multiple_signed.stubs(:validate_structure).returns(true)
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response_multiple_signed.validate!
+ end
+ assert_equal "Duplicated ID. SAML Response rejected", err.message
+ end
+
+ it "raise when fingerprint missmatch" do
+ resp_xml = Base64.decode64(response_document_valid_signed)
+ response = OneLogin::RubySaml::Response.new(Base64.encode64(resp_xml))
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ settings.idp_cert_fingerprint = signature_fingerprint_1
+ response.settings = settings
+
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.validate!
+ end
+ assert_equal 'Fingerprint mismatch', err.message
+ end
+
end
describe "#is_valid?" do
it "return false when response is initialized with blank data" do
response = OneLogin::RubySaml::Response.new('')
@@ -62,10 +124,20 @@
it "return false if settings have not been set" do
response = OneLogin::RubySaml::Response.new(response_document)
assert !response.is_valid?
end
+ it "return false when no cert or fingerprint provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = nil
+ assert !response.is_valid?
+ end
+
it "return true when the response is initialized with valid data" do
response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
response.stubs(:conditions).returns(nil)
assert !response.is_valid?
settings = OneLogin::RubySaml::Settings.new
@@ -78,11 +150,11 @@
it "should be idempotent when the response is initialized with invalid data" do
response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
response.stubs(:conditions).returns(nil)
settings = OneLogin::RubySaml::Settings.new
- response.settings = settings
+ response.settings = settings
assert !response.is_valid?
assert !response.is_valid?
end
it "should be idempotent when the response is initialized with valid data" do
@@ -93,15 +165,25 @@
response.settings.idp_cert_fingerprint = signature_fingerprint_valid_res
assert response.is_valid?
assert response.is_valid?
end
- it "return true when using certificate instead of fingerprint" do
+ it "return true when valid response and using fingerprint" do
response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
response.stubs(:conditions).returns(nil)
settings = OneLogin::RubySaml::Settings.new
response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = "4B:68:C4:53:C7:D9:94:AA:D9:02:5C:99:D5:EF:CF:56:62:87:FE:8D"
+ assert response.is_valid?
+ end
+
+ it "return true when valid response using certificate" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
settings.idp_cert = valid_cert
assert response.is_valid?
end
it "not allow signature wrapping attack" do
@@ -124,40 +206,54 @@
assert !response_wrapped.is_valid?
assert_nil response_wrapped.name_id
end
- it "raise when no signature" do
- response_no_signed_elements = OneLogin::RubySaml::Response.new(read_invalid_response("no_signature.xml.base64"))
- settings.idp_cert_fingerprint = signature_fingerprint_1
- response_no_signed_elements.settings = settings
- error_msg = "Found an unexpected number of Signature Element. SAML Response rejected"
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
- response_no_signed_elements.validate!
- end
- end
-
- it "raise when multiple signatures" do
- response_multiple_signed = OneLogin::RubySaml::Response.new(read_invalid_response("multiple_signed.xml.base64"))
- settings.idp_cert_fingerprint = signature_fingerprint_1
- response_multiple_signed.settings = settings
- error_msg = "Duplicated ID. SAML Response rejected"
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
- response_multiple_signed.validate!
- end
- end
-
it "support dynamic namespace resolution on signature elements" do
response = OneLogin::RubySaml::Response.new(fixture("no_signature_ns.xml"))
response.stubs(:conditions).returns(nil)
settings = OneLogin::RubySaml::Settings.new
response.settings = settings
settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true)
assert response.validate!
end
+ it "support signature elements with no KeyInfo if cert provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = ruby_saml_cert
+ settings.idp_cert_fingerprint = nil
+ XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true)
+ assert response.validate!
+ end
+
+ it "returns an error if the signature contains no KeyInfo, cert is not provided and soft" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
+ assert !response.is_valid?
+ end
+
+ it "raises an exception if the signature contains no KeyInfo, cert is not provided and no soft" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate)
+ response.stubs(:conditions).returns(nil)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.validate!
+ end
+ assert_equal "Certificate element missing in response (ds:X509Certificate) and not cert provided at settings", err.message
+ end
+
it "validate ADFS assertions" do
response = OneLogin::RubySaml::Response.new(fixture(:adfs_response_sha256))
response.stubs(:conditions).returns(nil)
settings = OneLogin::RubySaml::Settings.new
settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
@@ -172,20 +268,10 @@
settings.idp_cert = Base64.decode64(r1_signature_2)
response.settings = settings
assert response.validate!
end
- it "validate SAML 2.0 XML structure" do
- resp_xml = Base64.decode64(response_document_valid_signed).gsub(/emailAddress/,'test')
- response = OneLogin::RubySaml::Response.new(Base64.encode64(resp_xml))
- response.stubs(:conditions).returns(nil)
- settings = OneLogin::RubySaml::Settings.new
- settings.idp_cert_fingerprint = signature_fingerprint_1
- response.settings = settings
- assert_raises(OneLogin::RubySaml::ValidationError, 'Digest mismatch'){ response.validate! }
- end
-
it "Prevent node text with comment (VU#475445) attack" do
response_doc = File.read(File.join(File.dirname(__FILE__), "responses", 'response_node_text_attack.xml.base64'))
response = OneLogin::RubySaml::Response.new(response_doc)
assert_equal "support@onelogin.com", response.name_id
@@ -270,10 +356,58 @@
response = OneLogin::RubySaml::Response.new(response_document_5, :allowed_clock_drift => 0.516)
assert response.send(:validate_conditions, true)
end
end
+ describe "validate_signature" do
+ it "raises an exception when no cert or fingerprint provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = nil
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.send(:validate_signature, false)
+ end
+ assert_equal "No fingerprint or certificate on settings", err.message
+ end
+
+ it "raises an exception when wrong cert provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = ruby_saml_cert2
+ settings.idp_cert_fingerprint = nil
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.send(:validate_signature, false)
+ end
+ assert_equal "Fingerprint mismatch", err.message
+ end
+
+ it "raises an exception when wrong fingerprint provided" do
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
+ settings = OneLogin::RubySaml::Settings.new
+ response.settings = settings
+ settings.idp_cert = nil
+ settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response.send(:validate_signature, false)
+ end
+ assert_equal "Fingerprint mismatch", err.message
+ end
+
+ it "raises an exception when no signature" do
+ response_no_signed_elements = OneLogin::RubySaml::Response.new(read_invalid_response("no_signature.xml.base64"))
+ settings.idp_cert_fingerprint = signature_fingerprint_1
+ response_no_signed_elements.settings = settings
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response_no_signed_elements.validate!
+ end
+ assert_equal "Found an unexpected number of Signature Element. SAML Response rejected", err.message
+ end
+ end
+
describe "#attributes" do
before do
@response = OneLogin::RubySaml::Response.new(response_document)
end
@@ -462,10 +596,14 @@
response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
response_wrapped.stubs(:conditions).returns(nil)
response_wrapped.stubs(:validate_subject_confirmation).returns(true)
settings.idp_cert_fingerprint = "385b1eec71143f00db6af936e2ea12a28771d72c"
assert !response_wrapped.is_valid?
+ err = assert_raises(OneLogin::RubySaml::ValidationError) do
+ response_wrapped.validate!
+ end
+ assert_equal "Found an invalid Signed Element. SAML Response rejected", err.message
end
end
describe "signature wrapping attack - concealed SAML response body" do
it "should not be valid" do
@@ -473,11 +611,12 @@
signature_wrapping_attack = read_response("response_with_concealed_signed_assertion.xml")
response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
settings.idp_cert_fingerprint = '4b68c453c7d994aad9025c99d5efcf566287fe8d'
response_wrapped.stubs(:conditions).returns(nil)
response_wrapped.stubs(:validate_subject_confirmation).returns(true)
+ response_wrapped.stubs(:validate_structure).returns(true)
assert !response_wrapped.is_valid?
- assert_raises(OneLogin::RubySaml::ValidationError, "SAML Response must contain 1 assertion"){ response_wrapped.validate! }
+ assert !response_wrapped.validate!
end
end
describe "signature wrapping attack - doubled signed assertion SAML response" do
it "should not be valid" do