ruby-saml 1.11.0 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

Files changed (158) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +14 -12
  3. data/README.md +76 -22
  4. data/changelog.md +27 -0
  5. data/lib/onelogin/ruby-saml/attributes.rb +24 -1
  6. data/lib/onelogin/ruby-saml/authrequest.rb +9 -4
  7. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +62 -24
  8. data/lib/onelogin/ruby-saml/logoutrequest.rb +7 -1
  9. data/lib/onelogin/ruby-saml/logoutresponse.rb +4 -0
  10. data/lib/onelogin/ruby-saml/metadata.rb +9 -1
  11. data/lib/onelogin/ruby-saml/response.rb +38 -16
  12. data/lib/onelogin/ruby-saml/saml_message.rb +6 -0
  13. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  14. data/lib/onelogin/ruby-saml/settings.rb +34 -2
  15. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +4 -0
  16. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -14
  17. data/lib/onelogin/ruby-saml/utils.rb +56 -0
  18. data/lib/onelogin/ruby-saml/version.rb +1 -1
  19. data/lib/xml_security.rb +34 -6
  20. data/ruby-saml.gemspec +8 -4
  21. metadata +22 -282
  22. data/test/certificates/certificate.der +0 -0
  23. data/test/certificates/certificate1 +0 -12
  24. data/test/certificates/certificate_without_head_foot +0 -1
  25. data/test/certificates/formatted_certificate +0 -14
  26. data/test/certificates/formatted_chained_certificate +0 -42
  27. data/test/certificates/formatted_private_key +0 -12
  28. data/test/certificates/formatted_rsa_private_key +0 -12
  29. data/test/certificates/invalid_certificate1 +0 -1
  30. data/test/certificates/invalid_certificate2 +0 -1
  31. data/test/certificates/invalid_certificate3 +0 -12
  32. data/test/certificates/invalid_chained_certificate1 +0 -1
  33. data/test/certificates/invalid_private_key1 +0 -1
  34. data/test/certificates/invalid_private_key2 +0 -1
  35. data/test/certificates/invalid_private_key3 +0 -10
  36. data/test/certificates/invalid_rsa_private_key1 +0 -1
  37. data/test/certificates/invalid_rsa_private_key2 +0 -1
  38. data/test/certificates/invalid_rsa_private_key3 +0 -10
  39. data/test/certificates/ruby-saml-2.crt +0 -15
  40. data/test/certificates/ruby-saml.crt +0 -14
  41. data/test/certificates/ruby-saml.key +0 -15
  42. data/test/idp_metadata_parser_test.rb +0 -594
  43. data/test/logging_test.rb +0 -62
  44. data/test/logout_requests/invalid_slo_request.xml +0 -6
  45. data/test/logout_requests/slo_request.xml +0 -4
  46. data/test/logout_requests/slo_request.xml.base64 +0 -1
  47. data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
  48. data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
  49. data/test/logout_requests/slo_request_with_session_index.xml +0 -5
  50. data/test/logout_responses/logoutresponse_fixtures.rb +0 -86
  51. data/test/logoutrequest_test.rb +0 -260
  52. data/test/logoutresponse_test.rb +0 -427
  53. data/test/metadata/idp_descriptor.xml +0 -26
  54. data/test/metadata/idp_descriptor_2.xml +0 -56
  55. data/test/metadata/idp_descriptor_3.xml +0 -14
  56. data/test/metadata/idp_descriptor_4.xml +0 -72
  57. data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
  58. data/test/metadata/idp_metadata_multi_certs.xml +0 -75
  59. data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
  60. data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
  61. data/test/metadata/idp_multiple_descriptors.xml +0 -59
  62. data/test/metadata/idp_multiple_descriptors_2.xml +0 -59
  63. data/test/metadata/no_idp_descriptor.xml +0 -21
  64. data/test/metadata_test.rb +0 -331
  65. data/test/request_test.rb +0 -340
  66. data/test/response_test.rb +0 -1629
  67. data/test/responses/adfs_response_sha1.xml +0 -46
  68. data/test/responses/adfs_response_sha256.xml +0 -46
  69. data/test/responses/adfs_response_sha384.xml +0 -46
  70. data/test/responses/adfs_response_sha512.xml +0 -46
  71. data/test/responses/adfs_response_xmlns.xml +0 -45
  72. data/test/responses/attackxee.xml +0 -13
  73. data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
  74. data/test/responses/invalids/empty_destination.xml.base64 +0 -1
  75. data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
  76. data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
  77. data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
  78. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  79. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  80. data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
  81. data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
  82. data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
  83. data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
  84. data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
  85. data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
  86. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  87. data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
  88. data/test/responses/invalids/no_conditions.xml.base64 +0 -1
  89. data/test/responses/invalids/no_id.xml.base64 +0 -1
  90. data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
  91. data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
  92. data/test/responses/invalids/no_nameid.xml.base64 +0 -1
  93. data/test/responses/invalids/no_saml2.xml.base64 +0 -1
  94. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  95. data/test/responses/invalids/no_status.xml.base64 +0 -1
  96. data/test/responses/invalids/no_status_code.xml.base64 +0 -1
  97. data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
  98. data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
  99. data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
  100. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  101. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  102. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  103. data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
  104. data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
  105. data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
  106. data/test/responses/no_signature_ns.xml +0 -48
  107. data/test/responses/open_saml_response.xml +0 -56
  108. data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
  109. data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
  110. data/test/responses/response_double_status_code.xml.base64 +0 -1
  111. data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
  112. data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
  113. data/test/responses/response_eval.xml +0 -7
  114. data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
  115. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  116. data/test/responses/response_node_text_attack2.xml.base64 +0 -1
  117. data/test/responses/response_node_text_attack3.xml.base64 +0 -1
  118. data/test/responses/response_unsigned_xml_base64 +0 -1
  119. data/test/responses/response_with_ampersands.xml +0 -139
  120. data/test/responses/response_with_ampersands.xml.base64 +0 -93
  121. data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
  122. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  123. data/test/responses/response_with_multiple_attribute_values.xml +0 -67
  124. data/test/responses/response_with_retrieval_method.xml +0 -26
  125. data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
  126. data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
  127. data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
  128. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  129. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  130. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  131. data/test/responses/response_without_attributes.xml.base64 +0 -79
  132. data/test/responses/response_without_reference_uri.xml.base64 +0 -1
  133. data/test/responses/response_wrapped.xml.base64 +0 -150
  134. data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
  135. data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  136. data/test/responses/signed_nameid_in_atts.xml +0 -47
  137. data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
  138. data/test/responses/simple_saml_php.xml +0 -71
  139. data/test/responses/starfield_response.xml.base64 +0 -1
  140. data/test/responses/test_sign.xml +0 -43
  141. data/test/responses/unsigned_encrypted_adfs.xml +0 -23
  142. data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
  143. data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
  144. data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
  145. data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
  146. data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
  147. data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
  148. data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  149. data/test/responses/valid_response.xml.base64 +0 -1
  150. data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
  151. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  152. data/test/saml_message_test.rb +0 -56
  153. data/test/settings_test.rb +0 -338
  154. data/test/slo_logoutrequest_test.rb +0 -467
  155. data/test/slo_logoutresponse_test.rb +0 -233
  156. data/test/test_helper.rb +0 -333
  157. data/test/utils_test.rb +0 -259
  158. data/test/xml_security_test.rb +0 -421
@@ -1,1629 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
-
3
- require 'onelogin/ruby-saml/response'
4
-
5
- class RubySamlTest < Minitest::Test
6
-
7
- describe "Response" do
8
-
9
- let(:settings) { OneLogin::RubySaml::Settings.new }
10
- let(:response) { OneLogin::RubySaml::Response.new(response_document_without_recipient) }
11
- let(:response_without_attributes) { OneLogin::RubySaml::Response.new(response_document_without_attributes) }
12
- let(:response_with_multiple_attribute_statements) { OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_statements)) }
13
- let(:response_without_reference_uri) { OneLogin::RubySaml::Response.new(response_document_without_reference_uri) }
14
- let(:response_with_signed_assertion) { OneLogin::RubySaml::Response.new(response_document_with_signed_assertion) }
15
- let(:response_with_ds_namespace_at_the_root) { OneLogin::RubySaml::Response.new(response_document_with_ds_namespace_at_the_root)}
16
- let(:response_unsigned) { OneLogin::RubySaml::Response.new(response_document_unsigned) }
17
- let(:response_wrapped) { OneLogin::RubySaml::Response.new(response_document_wrapped) }
18
- let(:response_multiple_attr_values) { OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values)) }
19
- let(:response_valid_signed) { OneLogin::RubySaml::Response.new(response_document_valid_signed) }
20
- let(:response_valid_signed_without_recipient) { OneLogin::RubySaml::Response.new(response_document_valid_signed, {:skip_recipient_check => true })}
21
- let(:response_valid_signed_without_x509certificate) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate) }
22
- let(:response_no_id) { OneLogin::RubySaml::Response.new(read_invalid_response("no_id.xml.base64")) }
23
- let(:response_no_version) { OneLogin::RubySaml::Response.new(read_invalid_response("no_saml2.xml.base64")) }
24
- let(:response_multi_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_assertions.xml.base64")) }
25
- let(:response_no_conditions) { OneLogin::RubySaml::Response.new(read_invalid_response("no_conditions.xml.base64")) }
26
- let(:response_no_conditions_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("no_conditions.xml.base64"), { :skip_conditions => true }) }
27
- let(:response_no_authnstatement) { OneLogin::RubySaml::Response.new(read_invalid_response("no_authnstatement.xml.base64")) }
28
- let(:response_no_authnstatement_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("no_authnstatement.xml.base64"), {:skip_authnstatement => true}) }
29
- let(:response_empty_destination) { OneLogin::RubySaml::Response.new(read_invalid_response("empty_destination.xml.base64")) }
30
- let(:response_empty_destination_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("empty_destination.xml.base64"), {:skip_destination => true}) }
31
- let(:response_no_status) { OneLogin::RubySaml::Response.new(read_invalid_response("no_status.xml.base64")) }
32
- let(:response_no_statuscode) { OneLogin::RubySaml::Response.new(read_invalid_response("no_status_code.xml.base64")) }
33
- let(:response_statuscode_responder) { OneLogin::RubySaml::Response.new(read_invalid_response("status_code_responder.xml.base64")) }
34
- let(:response_statuscode_responder_and_msg) { OneLogin::RubySaml::Response.new(read_invalid_response("status_code_responer_and_msg.xml.base64")) }
35
- let(:response_double_statuscode) { OneLogin::RubySaml::Response.new(response_document_double_status_code) }
36
- let(:response_encrypted_attrs) { OneLogin::RubySaml::Response.new(response_document_encrypted_attrs) }
37
- let(:response_no_signed_elements) { OneLogin::RubySaml::Response.new(read_invalid_response("no_signature.xml.base64")) }
38
- let(:response_multiple_signed) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_signed.xml.base64")) }
39
- let(:response_audience_self_closed) { OneLogin::RubySaml::Response.new(read_response("response_audience_self_closed_tag.xml.base64")) }
40
- let(:response_invalid_audience) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_audience.xml.base64")) }
41
- let(:response_invalid_signed_element) { OneLogin::RubySaml::Response.new(read_invalid_response("response_invalid_signed_element.xml.base64")) }
42
- let(:response_invalid_issuer_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_issuer_assertion.xml.base64")) }
43
- let(:response_invalid_issuer_message) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_issuer_message.xml.base64")) }
44
- let(:response_no_issuer_response) { OneLogin::RubySaml::Response.new(read_invalid_response("no_issuer_response.xml.base64")) }
45
- let(:response_no_issuer_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("no_issuer_assertion.xml.base64")) }
46
- let(:response_no_nameid) { OneLogin::RubySaml::Response.new(read_invalid_response("no_nameid.xml.base64")) }
47
- let(:response_empty_nameid) { OneLogin::RubySaml::Response.new(read_invalid_response("empty_nameid.xml.base64")) }
48
- let(:response_wrong_spnamequalifier) { OneLogin::RubySaml::Response.new(read_invalid_response("wrong_spnamequalifier.xml.base64")) }
49
- let(:response_duplicated_attributes) { OneLogin::RubySaml::Response.new(read_invalid_response("duplicated_attributes.xml.base64")) }
50
- let(:response_no_subjectconfirmation_data) { OneLogin::RubySaml::Response.new(read_invalid_response("no_subjectconfirmation_data.xml.base64")) }
51
- let(:response_no_subjectconfirmation_method) { OneLogin::RubySaml::Response.new(read_invalid_response("no_subjectconfirmation_method.xml.base64")) }
52
- let(:response_invalid_subjectconfirmation_inresponse) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_inresponse.xml.base64")) }
53
- let(:response_invalid_subjectconfirmation_recipient) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_recipient.xml.base64")) }
54
- let(:response_invalid_subjectconfirmation_nb) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_nb.xml.base64")) }
55
- let(:response_invalid_subjectconfirmation_noa) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_noa.xml.base64")) }
56
- let(:response_invalid_signature_position) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_signature_position.xml.base64")) }
57
- let(:response_encrypted_nameid) { OneLogin::RubySaml::Response.new(response_document_encrypted_nameid) }
58
-
59
- def generate_audience_error(expected, actual)
60
- s = actual.count > 1 ? 's' : '';
61
- return "Invalid Audience#{s}. The audience#{s} #{actual.join(',')}, did not match the expected audience #{expected}"
62
- end
63
-
64
- it "raise an exception when response is initialized with nil" do
65
- assert_raises(ArgumentError) { OneLogin::RubySaml::Response.new(nil) }
66
- end
67
-
68
- it "not filter available options only" do
69
- options = { :skip_destination => true, :foo => :bar }
70
- response = OneLogin::RubySaml::Response.new(response_document_valid_signed, options)
71
- assert_includes response.options.keys, :skip_destination
72
- assert_includes response.options.keys, :foo
73
- end
74
-
75
- it "be able to parse a document which contains ampersands" do
76
- XMLSecurity::SignedDocument.any_instance.stubs(:digests_match?).returns(true)
77
- OneLogin::RubySaml::Response.any_instance.stubs(:validate_conditions).returns(true)
78
-
79
- ampersands_response = OneLogin::RubySaml::Response.new(ampersands_document)
80
- ampersands_response.settings = settings
81
- ampersands_response.settings.idp_cert_fingerprint = 'c51985d947f1be57082025050846eb27f6cab783'
82
-
83
- assert !ampersands_response.is_valid?
84
- assert_includes ampersands_response.errors, "SAML Response must contain 1 assertion"
85
- end
86
-
87
- describe "Prevent node text with comment attack (VU#475445)" do
88
- before do
89
- @response = OneLogin::RubySaml::Response.new(read_response('response_node_text_attack.xml.base64'))
90
- end
91
-
92
- it "receives the full NameID when there is an injected comment" do
93
- assert_equal "support@onelogin.com", @response.name_id
94
- end
95
-
96
- it "receives the full AttributeValue when there is an injected comment" do
97
- assert_equal "smith", @response.attributes["surname"]
98
- end
99
- end
100
-
101
- describe "Another test to prevent with comment attack (VU#475445)" do
102
- before do
103
- @response = OneLogin::RubySaml::Response.new(read_response('response_node_text_attack2.xml.base64'), {:skip_recipient_check => true })
104
- @response.settings = settings
105
- @response.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
106
- end
107
-
108
- it "receives the full NameID when there is an injected comment, validates the response" do
109
- assert_equal "test@onelogin.com", @response.name_id
110
- end
111
- end
112
-
113
- describe "Another test with CDATA injected" do
114
- before do
115
- @response = OneLogin::RubySaml::Response.new(read_response('response_node_text_attack3.xml.base64'), {:skip_recipient_check => true })
116
- @response.settings = settings
117
- @response.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
118
- end
119
-
120
- it "it normalizes CDATA but reject SAMLResponse due signature invalidation" do
121
- assert_equal "test@onelogin.com.evil.com", @response.name_id
122
- assert !@response.is_valid?
123
- assert_includes @response.errors, "Invalid Signature on SAML Response"
124
- end
125
- end
126
-
127
- describe "Prevent XEE attack" do
128
- before do
129
- @response = OneLogin::RubySaml::Response.new(fixture(:attackxee))
130
- end
131
-
132
- it "false when evil attack vector is present, soft = true" do
133
- @response.soft = true
134
- assert !@response.send(:validate_structure)
135
- assert_includes @response.errors, "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd"
136
- end
137
-
138
- it "raise when evil attack vector is present, soft = false " do
139
- @response.soft = false
140
-
141
- assert_raises(OneLogin::RubySaml::ValidationError) do
142
- @response.send(:validate_structure)
143
- end
144
- end
145
- end
146
-
147
- it "adapt namespace" do
148
- refute_nil response.nameid
149
- refute_nil response_without_attributes.nameid
150
- refute_nil response_with_signed_assertion.nameid
151
- end
152
-
153
- it "default to raw input when a response is not Base64 encoded" do
154
- decoded = Base64.decode64(response_document_without_attributes)
155
- response_from_raw = OneLogin::RubySaml::Response.new(decoded)
156
- assert response_from_raw.document
157
- end
158
-
159
- describe "Assertion" do
160
- it "only retreive an assertion with an ID that matches the signature's reference URI" do
161
- response_wrapped.stubs(:conditions).returns(nil)
162
- settings.idp_cert_fingerprint = signature_fingerprint_1
163
- response_wrapped.settings = settings
164
- assert_nil response_wrapped.nameid
165
- end
166
- end
167
-
168
- describe "#is_valid?" do
169
- describe "soft = false" do
170
-
171
- before do
172
- response.soft = false
173
- response_valid_signed.soft = false
174
- end
175
-
176
- it "raise when response is initialized with blank data" do
177
- blank_response = OneLogin::RubySaml::Response.new('')
178
- blank_response.soft = false
179
- error_msg = "Blank response"
180
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
181
- blank_response.is_valid?
182
- end
183
- assert_includes blank_response.errors, error_msg
184
- end
185
-
186
- it "raise when settings have not been set" do
187
- error_msg = "No settings on response"
188
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
189
- response.is_valid?
190
- end
191
- assert_includes response.errors, error_msg
192
- end
193
-
194
- it "raise when No fingerprint or certificate on settings" do
195
- settings.idp_cert_fingerprint = nil
196
- settings.idp_cert = nil
197
- settings.idp_cert_multi = nil
198
- response.settings = settings
199
- error_msg = "No fingerprint or certificate on settings"
200
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
201
- response.is_valid?
202
- end
203
- assert_includes response.errors, error_msg
204
- end
205
-
206
- it "raise when signature wrapping attack" do
207
- response_wrapped.stubs(:conditions).returns(nil)
208
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
209
- settings.idp_cert_fingerprint = signature_fingerprint_1
210
- response_wrapped.settings = settings
211
- assert !response_wrapped.is_valid?
212
- end
213
-
214
- it "validate SAML 2.0 XML structure" do
215
- resp_xml = Base64.decode64(response_document_unsigned).gsub(/emailAddress/,'test')
216
- response_unsigned_mod = OneLogin::RubySaml::Response.new(Base64.encode64(resp_xml))
217
- response_unsigned_mod.stubs(:conditions).returns(nil)
218
- settings.idp_cert_fingerprint = signature_fingerprint_1
219
- response_unsigned_mod.settings = settings
220
- response_unsigned_mod.soft = false
221
- assert_raises(OneLogin::RubySaml::ValidationError, 'Digest mismatch') do
222
- response_unsigned_mod.is_valid?
223
- end
224
- end
225
-
226
- it "raise when encountering a condition that prevents the document from being valid" do
227
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
228
- response.settings = settings
229
- response.soft = false
230
- error_msg = "Current time is on or after NotOnOrAfter condition"
231
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
232
- response.is_valid?
233
- end
234
- assert_includes response.errors[0], error_msg
235
- end
236
-
237
- it "raise when encountering a SAML Response with bad formatted" do
238
- settings.idp_cert_fingerprint = signature_fingerprint_1
239
- response_without_attributes.settings = settings
240
- response_without_attributes.soft = false
241
- assert_raises(OneLogin::RubySaml::ValidationError) do
242
- response_without_attributes.is_valid?
243
- end
244
- end
245
-
246
- it "raise when the inResponseTo value does not match the Request ID" do
247
- settings.soft = false
248
- settings.idp_cert_fingerprint = signature_fingerprint_1
249
- opts = {}
250
- opts[:settings] = settings
251
- opts[:matches_request_id] = "invalid_request_id"
252
- response_valid_signed = OneLogin::RubySaml::Response.new(response_document_valid_signed, opts)
253
- error_msg = "The InResponseTo of the Response: _fc4a34b0-7efb-012e-caae-782bcb13bb38, does not match the ID of the AuthNRequest sent by the SP: invalid_request_id"
254
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
255
- response_valid_signed.is_valid?
256
- end
257
- assert_includes response_valid_signed.errors, error_msg
258
- end
259
-
260
- it "raise when there is no valid audience" do
261
- settings.idp_cert_fingerprint = signature_fingerprint_1
262
- settings.sp_entity_id = 'invalid'
263
- response_valid_signed.settings = settings
264
- response_valid_signed.soft = false
265
- error_msg = generate_audience_error(response_valid_signed.settings.sp_entity_id, ['https://someone.example.com/audience'])
266
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
267
- response_valid_signed.is_valid?
268
- end
269
- assert_includes response_valid_signed.errors, error_msg
270
- end
271
-
272
- it "raise when no ID present in the SAML Response" do
273
- settings.idp_cert_fingerprint = signature_fingerprint_1
274
- response_no_id.settings = settings
275
- response_no_id.soft = false
276
- error_msg = "Missing ID attribute on SAML Response"
277
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
278
- response_no_id.is_valid?
279
- end
280
- assert_includes response_no_id.errors, error_msg
281
- end
282
-
283
- it "raise when no 2.0 Version present in the SAML Response" do
284
- settings.idp_cert_fingerprint = signature_fingerprint_1
285
- response_no_version.settings = settings
286
- response_no_version.soft = false
287
- error_msg = "Unsupported SAML version"
288
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
289
- response_no_version.is_valid?
290
- end
291
- assert_includes response_no_version.errors, error_msg
292
- end
293
- end
294
-
295
- describe "soft = true" do
296
- before do
297
- response.soft = true
298
- response_valid_signed.soft = true
299
- end
300
-
301
- it "return true when the response is initialized with valid data" do
302
- response_valid_signed_without_recipient.stubs(:conditions).returns(nil)
303
- response_valid_signed_without_recipient.settings = settings
304
- response_valid_signed_without_recipient.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
305
- assert response_valid_signed_without_recipient.is_valid?
306
- assert_empty response_valid_signed_without_recipient.errors
307
- end
308
-
309
- it "return true when the response is initialized with valid data and using certificate instead of fingerprint" do
310
- response_valid_signed_without_recipient.stubs(:conditions).returns(nil)
311
- response_valid_signed_without_recipient.settings = settings
312
- response_valid_signed_without_recipient.settings.idp_cert = ruby_saml_cert_text
313
- assert response_valid_signed_without_recipient.is_valid?
314
- assert_empty response_valid_signed_without_recipient.errors
315
- end
316
-
317
- it "return false when response is initialized with blank data" do
318
- blank_response = OneLogin::RubySaml::Response.new('')
319
- blank_response.soft = true
320
- assert !blank_response.is_valid?
321
- assert_includes blank_response.errors, "Blank response"
322
- end
323
-
324
- it "return false if settings have not been set" do
325
- assert !response.is_valid?
326
- assert_includes response.errors, "No settings on response"
327
- end
328
-
329
- it "return false if fingerprint or certificate not been set on settings" do
330
- response.settings = settings
331
- assert !response.is_valid?
332
- assert_includes response.errors, "No fingerprint or certificate on settings"
333
- end
334
-
335
- it "should be idempotent when the response is initialized with invalid data" do
336
- response_unsigned.stubs(:conditions).returns(nil)
337
- response_unsigned.settings = settings
338
- assert !response_unsigned.is_valid?
339
- assert !response_unsigned.is_valid?
340
- end
341
-
342
- it "should be idempotent when the response is initialized with valid data" do
343
- response_valid_signed_without_recipient.stubs(:conditions).returns(nil)
344
- response_valid_signed_without_recipient.settings = settings
345
- response_valid_signed_without_recipient.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
346
- assert response_valid_signed_without_recipient.is_valid?
347
- assert response_valid_signed_without_recipient.is_valid?
348
- end
349
-
350
- it "not allow signature wrapping attack" do
351
- response_wrapped.stubs(:conditions).returns(nil)
352
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
353
- settings.idp_cert_fingerprint = signature_fingerprint_1
354
- response_wrapped.settings = settings
355
- assert !response_wrapped.is_valid?
356
- end
357
-
358
- it "support dynamic namespace resolution on signature elements" do
359
- no_signature_response = OneLogin::RubySaml::Response.new(fixture("no_signature_ns.xml"))
360
- no_signature_response.stubs(:conditions).returns(nil)
361
- no_signature_response.stubs(:validate_subject_confirmation).returns(true)
362
- no_signature_response.settings = settings
363
- no_signature_response.settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
364
- XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true)
365
- assert no_signature_response.is_valid?
366
- end
367
-
368
- it "validate ADFS assertions" do
369
- adfs_response = OneLogin::RubySaml::Response.new(fixture(:adfs_response_sha256))
370
- adfs_response.stubs(:conditions).returns(nil)
371
- adfs_response.stubs(:validate_subject_confirmation).returns(true)
372
- settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
373
- adfs_response.settings = settings
374
- adfs_response.soft = true
375
- assert adfs_response.is_valid?
376
- end
377
-
378
- it "validate SAML 2.0 XML structure" do
379
- resp_xml = Base64.decode64(response_document_unsigned).gsub(/emailAddress/,'test')
380
- response_unsigned_mod = OneLogin::RubySaml::Response.new(Base64.encode64(resp_xml))
381
- response_unsigned_mod.stubs(:conditions).returns(nil)
382
- settings.idp_cert_fingerprint = signature_fingerprint_1
383
- response_unsigned_mod.settings = settings
384
- response_unsigned_mod.soft = true
385
- assert !response_unsigned_mod.is_valid?
386
- end
387
-
388
- it "return false when encountering a condition that prevents the document from being valid" do
389
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
390
- response.settings = settings
391
- error_msg = "Current time is on or after NotOnOrAfter condition"
392
- assert !response.is_valid?
393
- assert_includes response.errors[0], "Current time is on or after NotOnOrAfter condition"
394
- end
395
-
396
- it "return false when encountering a SAML Response with bad formatted" do
397
- settings.idp_cert_fingerprint = signature_fingerprint_1
398
- response_without_attributes.settings = settings
399
- response_without_attributes.soft = true
400
- error_msg = "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd"
401
- response_without_attributes.is_valid?
402
- assert_includes response_without_attributes.errors, error_msg
403
- end
404
-
405
- it "return false when the inResponseTo value does not match the Request ID" do
406
- settings.soft = true
407
- settings.idp_cert_fingerprint = signature_fingerprint_1
408
- opts = {}
409
- opts[:settings] = settings
410
- opts[:matches_request_id] = "invalid_request_id"
411
- response_valid_signed = OneLogin::RubySaml::Response.new(response_document_valid_signed, opts)
412
- response_valid_signed.is_valid?
413
- assert_includes response_valid_signed.errors, "The InResponseTo of the Response: _fc4a34b0-7efb-012e-caae-782bcb13bb38, does not match the ID of the AuthNRequest sent by the SP: invalid_request_id"
414
- end
415
-
416
- it "return false when there is no valid audience" do
417
- settings.idp_cert_fingerprint = signature_fingerprint_1
418
- settings.sp_entity_id = 'invalid'
419
- response_valid_signed.settings = settings
420
- response_valid_signed.is_valid?
421
-
422
- assert_includes response_valid_signed.errors, generate_audience_error(response_valid_signed.settings.sp_entity_id, ['https://someone.example.com/audience'])
423
- end
424
-
425
- it "return false when no ID present in the SAML Response" do
426
- settings.idp_cert_fingerprint = signature_fingerprint_1
427
- response_no_id.settings = settings
428
- response_no_id.soft = true
429
- response_no_id.is_valid?
430
- assert_includes response_no_id.errors, "Missing ID attribute on SAML Response"
431
- end
432
-
433
- it "return false when no 2.0 Version present in the SAML Response" do
434
- settings.idp_cert_fingerprint = signature_fingerprint_1
435
- response_no_version.settings = settings
436
- response_no_version.soft = true
437
- error_msg = "Unsupported SAML version"
438
- response_no_version.is_valid?
439
- assert_includes response_no_version.errors, "Unsupported SAML version"
440
- end
441
-
442
- it "return true when a nil URI is given in the ds:Reference" do
443
- settings.idp_cert = ruby_saml_cert_text
444
- settings.assertion_consumer_service_url = "http://localhost:9001/v1/users/authorize/saml"
445
- response_without_reference_uri.settings = settings
446
- response_without_reference_uri.stubs(:conditions).returns(nil)
447
- response_without_reference_uri.is_valid?
448
- assert_empty response_without_reference_uri.errors
449
- assert 'saml@user.com', response_without_reference_uri.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']
450
- end
451
-
452
- it "collect errors when collect_errors=true" do
453
- settings.idp_cert = ruby_saml_cert_text
454
- settings.sp_entity_id = 'invalid'
455
- response_invalid_subjectconfirmation_recipient.settings = settings
456
- collect_errors = true
457
- response_invalid_subjectconfirmation_recipient.is_valid?(collect_errors)
458
- assert_includes response_invalid_subjectconfirmation_recipient.errors, generate_audience_error('invalid', ['http://stuff.com/endpoints/metadata.php'])
459
- assert_includes response_invalid_subjectconfirmation_recipient.errors, "Invalid Signature on SAML Response"
460
- end
461
- end
462
- end
463
-
464
- describe "#validate_audience" do
465
- it "return true when the audience is valid" do
466
- response.settings = settings
467
- response.settings.sp_entity_id = '{audience}'
468
- assert response.send(:validate_audience)
469
- assert_empty response.errors
470
- end
471
-
472
- it "return true when the audience is self closing" do
473
- response_audience_self_closed.settings = settings
474
- response_audience_self_closed.settings.sp_entity_id = '{audience}'
475
- assert response_audience_self_closed.send(:validate_audience)
476
- assert_empty response_audience_self_closed.errors
477
- end
478
-
479
- it "return false when the audience is valid" do
480
- response.settings = settings
481
- response.settings.sp_entity_id = 'invalid_audience'
482
- assert !response.send(:validate_audience)
483
- assert_includes response.errors, generate_audience_error(response.settings.sp_entity_id, ['{audience}'])
484
- end
485
- end
486
-
487
- describe "#validate_destination" do
488
- it "return true when the destination of the SAML Response matches the assertion consumer service url" do
489
- response.settings = settings
490
- assert response.send(:validate_destination)
491
- assert_empty response.errors
492
- end
493
-
494
- it "return false when the destination of the SAML Response does not match the assertion consumer service url" do
495
- response.settings = settings
496
- response.settings.assertion_consumer_service_url = 'invalid_acs'
497
- assert !response.send(:validate_destination)
498
- assert_includes response.errors, "The response was received at #{response.destination} instead of #{response.settings.assertion_consumer_service_url}"
499
- end
500
-
501
- it "return false when the destination of the SAML Response is empty" do
502
- response_empty_destination.settings = settings
503
- assert !response_empty_destination.send(:validate_destination)
504
- assert_includes response_empty_destination.errors, "The response has an empty Destination value"
505
- end
506
-
507
- it "return true when the destination of the SAML Response is empty but skip_destination option is used" do
508
- response_empty_destination_with_skip.settings = settings
509
- assert response_empty_destination_with_skip.send(:validate_destination)
510
- assert_empty response_empty_destination.errors
511
- end
512
-
513
- it "returns true on a case insensitive match on the domain" do
514
- response_valid_signed_without_x509certificate.settings = settings
515
- response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url = 'http://APP.muDa.no/sso/consume'
516
- assert response_valid_signed_without_x509certificate.send(:validate_destination)
517
- assert_empty response_valid_signed_without_x509certificate.errors
518
- end
519
-
520
- it "returns true on a case insensitive match on the scheme" do
521
- response_valid_signed_without_x509certificate.settings = settings
522
- response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url = 'HTTP://app.muda.no/sso/consume'
523
- assert response_valid_signed_without_x509certificate.send(:validate_destination)
524
- assert_empty response_valid_signed_without_x509certificate.errors
525
- end
526
-
527
- it "returns false on a case insenstive match on the path" do
528
- response_valid_signed_without_x509certificate.settings = settings
529
- response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url = 'http://app.muda.no/SSO/consume'
530
- assert !response_valid_signed_without_x509certificate.send(:validate_destination)
531
- assert_includes response_valid_signed_without_x509certificate.errors, "The response was received at #{response_valid_signed_without_x509certificate.destination} instead of #{response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url}"
532
- end
533
-
534
- it "returns true if it can't parse out a full URI." do
535
- response_valid_signed_without_x509certificate.settings = settings
536
- response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url = 'presenter'
537
- assert !response_valid_signed_without_x509certificate.send(:validate_destination)
538
- assert_includes response_valid_signed_without_x509certificate.errors, "The response was received at #{response_valid_signed_without_x509certificate.destination} instead of #{response_valid_signed_without_x509certificate.settings.assertion_consumer_service_url}"
539
- end
540
- end
541
-
542
- describe "#validate_issuer" do
543
- it "return true when the issuer of the Message/Assertion matches the IdP entityId" do
544
- response_valid_signed.settings = settings
545
- assert response_valid_signed.send(:validate_issuer)
546
-
547
- response_valid_signed.settings.idp_entity_id = 'https://app.onelogin.com/saml2'
548
- assert response_valid_signed.send(:validate_issuer)
549
- end
550
-
551
- it "return false when the issuer of the Message does not match the IdP entityId" do
552
- response_invalid_issuer_message.settings = settings
553
- response_invalid_issuer_message.settings.idp_entity_id = 'http://idp.example.com/'
554
- assert !response_invalid_issuer_message.send(:validate_issuer)
555
- assert_includes response_invalid_issuer_message.errors, "Doesn't match the issuer, expected: <#{response_invalid_issuer_message.settings.idp_entity_id}>, but was: <http://invalid.issuer.example.com/>"
556
- end
557
-
558
- it "return false when the issuer of the Assertion does not match the IdP entityId" do
559
- response_invalid_issuer_assertion.settings = settings
560
- response_invalid_issuer_assertion.settings.idp_entity_id = 'http://idp.example.com/'
561
- assert !response_invalid_issuer_assertion.send(:validate_issuer)
562
- assert_includes response_invalid_issuer_assertion.errors, "Doesn't match the issuer, expected: <#{response_invalid_issuer_assertion.settings.idp_entity_id}>, but was: <http://invalid.issuer.example.com/>"
563
- end
564
- end
565
-
566
- describe "#validate_num_assertion" do
567
- it "return true when SAML Response contains 1 assertion" do
568
- assert response.send(:validate_num_assertion)
569
- assert_empty response.errors
570
- end
571
-
572
- it "return false when no 2.0 Version present in the SAML Response" do
573
- assert !response_multi_assertion.send(:validate_num_assertion)
574
- assert_includes response_multi_assertion.errors, "SAML Response must contain 1 assertion"
575
- end
576
- end
577
-
578
- describe "validate_success_status" do
579
- it "return true when the status is 'Success'" do
580
- assert response.send(:validate_success_status)
581
- assert_empty response.errors
582
- end
583
-
584
- it "return false when no Status provided" do
585
- assert !response_no_status.send(:validate_success_status)
586
- assert_includes response_no_status.errors, "The status code of the Response was not Success"
587
- end
588
-
589
- it "return false when no StatusCode provided" do
590
- assert !response_no_statuscode.send(:validate_success_status)
591
- assert_includes response_no_statuscode.errors, "The status code of the Response was not Success"
592
- end
593
-
594
- it "return false when the status is not 'Success'" do
595
- assert !response_statuscode_responder.send(:validate_success_status)
596
- assert_includes response_statuscode_responder.errors, "The status code of the Response was not Success, was Responder"
597
- end
598
-
599
- it "return false when the status is not 'Success', and shows the StatusMessage" do
600
- assert !response_statuscode_responder_and_msg.send(:validate_success_status)
601
- assert_includes response_statuscode_responder_and_msg.errors, "The status code of the Response was not Success, was Responder -> something_is_wrong"
602
- end
603
-
604
- it "return false when the status is not 'Success'" do
605
- assert !response_double_statuscode.send(:validate_success_status)
606
- assert_includes response_double_statuscode.errors, "The status code of the Response was not Success, was Requester => UnsupportedBinding"
607
- end
608
- end
609
-
610
- describe "#validate_structure" do
611
- it "return true when encountering a wellformed SAML Response" do
612
- assert response.send(:validate_structure)
613
- assert_empty response.errors
614
- end
615
-
616
- it "return false when encountering a mailformed element that prevents the document from being valid" do
617
- response_without_attributes.soft = true
618
- response_without_attributes.send(:validate_structure)
619
- assert response_without_attributes.errors.include? "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd"
620
- end
621
-
622
- it "raise when encountering a mailformed element that prevents the document from being valid" do
623
- response_without_attributes.soft = false
624
- assert_raises(OneLogin::RubySaml::ValidationError) {
625
- response_without_attributes.send(:validate_structure)
626
- }
627
- end
628
- end
629
-
630
- describe "validate_formatted_x509_certificate" do
631
- let(:response_with_formatted_x509certificate) {
632
- OneLogin::RubySaml::Response.new(read_response("valid_response_with_formatted_x509certificate.xml.base64"), {
633
- :skip_conditions => true,
634
- :skip_subject_confirmation => true })
635
- }
636
-
637
- it "be able to parse the response wihout errors" do
638
- response_with_formatted_x509certificate.settings = settings
639
- response_with_formatted_x509certificate.settings.idp_cert = ruby_saml_cert_text
640
- assert response_with_formatted_x509certificate.is_valid?
641
- assert_empty response_with_formatted_x509certificate.errors
642
- end
643
- end
644
-
645
- describe "#validate_in_response_to" do
646
- it "return true when the inResponseTo value matches the Request ID" do
647
- response = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings, :matches_request_id => "_fc4a34b0-7efb-012e-caae-782bcb13bb38")
648
- assert response.send(:validate_in_response_to)
649
- assert_empty response.errors
650
- end
651
-
652
- it "return true when no Request ID is provided for checking" do
653
- response = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings)
654
- assert response.send(:validate_in_response_to)
655
- assert_empty response.errors
656
- end
657
-
658
- it "return false when the inResponseTo value does not match the Request ID" do
659
- response = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings, :matches_request_id => "invalid_request_id")
660
- assert !response.send(:validate_in_response_to)
661
- assert_includes response.errors, "The InResponseTo of the Response: _fc4a34b0-7efb-012e-caae-782bcb13bb38, does not match the ID of the AuthNRequest sent by the SP: invalid_request_id"
662
- end
663
- end
664
-
665
- describe "#validate_audience" do
666
- it "return true when the audience is valid" do
667
- response_valid_signed.settings = settings
668
- response_valid_signed.settings.sp_entity_id = "https://someone.example.com/audience"
669
- assert response_valid_signed.send(:validate_audience)
670
- assert_empty response_valid_signed.errors
671
- end
672
-
673
- it "return true when there is not sp_entity_id defined" do
674
- response_valid_signed.settings = settings
675
- response_valid_signed.settings.sp_entity_id = nil
676
- assert response_valid_signed.send(:validate_audience)
677
- assert_empty response_valid_signed.errors
678
- end
679
-
680
- it "return false when there is no valid audience" do
681
- response_invalid_audience.settings = settings
682
- response_invalid_audience.settings.sp_entity_id = "https://invalid.example.com/audience"
683
- assert !response_invalid_audience.send(:validate_audience)
684
- assert_includes response_invalid_audience.errors, generate_audience_error(response_invalid_audience.settings.sp_entity_id, ['http://invalid.audience.com'])
685
- end
686
- end
687
-
688
- describe "#validate_issuer" do
689
- it "return true when the issuer of the Message/Assertion matches the IdP entityId or it was empty" do
690
- response_valid_signed.settings = settings
691
- assert response_valid_signed.send(:validate_issuer)
692
- assert_empty response_valid_signed.errors
693
-
694
- response_valid_signed.settings.idp_entity_id = 'https://app.onelogin.com/saml2'
695
- assert response_valid_signed.send(:validate_issuer)
696
- assert_empty response_valid_signed.errors
697
- end
698
-
699
- it "return false when the issuer of the Message does not match the IdP entityId" do
700
- response_invalid_issuer_message.settings = settings
701
- response_invalid_issuer_message.settings.idp_entity_id = 'http://idp.example.com/'
702
- assert !response_invalid_issuer_message.send(:validate_issuer)
703
- assert_includes response_invalid_issuer_message.errors, "Doesn't match the issuer, expected: <#{response_invalid_issuer_message.settings.idp_entity_id}>, but was: <http://invalid.issuer.example.com/>"
704
- end
705
-
706
- it "return false when the issuer of the Assertion does not match the IdP entityId" do
707
- response_invalid_issuer_assertion.settings = settings
708
- response_invalid_issuer_assertion.settings.idp_entity_id = 'http://idp.example.com/'
709
- assert !response_invalid_issuer_assertion.send(:validate_issuer)
710
- assert_includes response_invalid_issuer_assertion.errors, "Doesn't match the issuer, expected: <#{response_invalid_issuer_assertion.settings.idp_entity_id}>, but was: <http://invalid.issuer.example.com/>"
711
- end
712
-
713
- it "return false when the no issuer at the Response" do
714
- response_no_issuer_response.settings = settings
715
- response_no_issuer_response.settings.idp_entity_id = 'http://idp.example.com/'
716
- assert !response_no_issuer_response.send(:validate_issuer)
717
- assert_includes response_no_issuer_response.errors, "Issuer of the Response not found or multiple."
718
- end
719
-
720
- it "return false when the no issuer at the Assertion" do
721
- response_no_issuer_assertion.settings = settings
722
- response_no_issuer_assertion.settings.idp_entity_id = 'http://idp.example.com/'
723
- assert !response_no_issuer_assertion.send(:validate_issuer)
724
- assert_includes response_no_issuer_assertion.errors, "Issuer of the Assertion not found or multiple."
725
- end
726
- end
727
-
728
- describe "#validate_subject_confirmation" do
729
- it "return true when valid subject confirmation" do
730
- response_valid_signed.settings = settings
731
- response_valid_signed.settings.assertion_consumer_service_url = 'recipient'
732
- assert response_valid_signed.send(:validate_subject_confirmation)
733
- assert_empty response_valid_signed.errors
734
- end
735
-
736
- it "return false when no subject confirmation data" do
737
- response_no_subjectconfirmation_data.settings = settings
738
- assert !response_no_subjectconfirmation_data.send(:validate_subject_confirmation)
739
- assert_includes response_no_subjectconfirmation_data.errors, "A valid SubjectConfirmation was not found on this Response"
740
- end
741
-
742
- it "return false when no valid subject confirmation method" do
743
- response_no_subjectconfirmation_method.settings = settings
744
- assert !response_no_subjectconfirmation_method.send(:validate_subject_confirmation)
745
- assert_includes response_no_subjectconfirmation_method.errors, "A valid SubjectConfirmation was not found on this Response"
746
- end
747
-
748
- it "return false when invalid inresponse" do
749
- response_invalid_subjectconfirmation_inresponse.settings = settings
750
- assert !response_invalid_subjectconfirmation_inresponse.send(:validate_subject_confirmation)
751
- assert_includes response_invalid_subjectconfirmation_inresponse.errors, "A valid SubjectConfirmation was not found on this Response"
752
- end
753
-
754
- it "return false when invalid NotBefore" do
755
- response_invalid_subjectconfirmation_nb.settings = settings
756
- assert !response_invalid_subjectconfirmation_nb.send(:validate_subject_confirmation)
757
- assert_includes response_invalid_subjectconfirmation_nb.errors, "A valid SubjectConfirmation was not found on this Response"
758
- end
759
-
760
- it "return false when invalid NotOnOrAfter" do
761
- response_invalid_subjectconfirmation_noa.settings = settings
762
- assert !response_invalid_subjectconfirmation_noa.send(:validate_subject_confirmation)
763
- assert_includes response_invalid_subjectconfirmation_noa.errors, "A valid SubjectConfirmation was not found on this Response"
764
- end
765
-
766
- it "return true when valid subject confirmation recipient" do
767
- response_valid_signed.settings = settings
768
- response_valid_signed.settings.assertion_consumer_service_url = 'recipient'
769
- assert response_valid_signed.send(:validate_subject_confirmation)
770
- assert_empty response_valid_signed.errors
771
- assert_empty response_valid_signed.errors
772
- end
773
-
774
- it "return false when invalid subject confirmation recipient" do
775
- response_valid_signed.settings = settings
776
- response_valid_signed.settings.assertion_consumer_service_url = 'not-the-recipient'
777
- assert !response_valid_signed.send(:validate_subject_confirmation)
778
- assert_includes response_valid_signed.errors, "A valid SubjectConfirmation was not found on this Response"
779
- end
780
-
781
- it "return false when invalid subject confirmation recipient, but skipping the check(default)" do
782
- response_valid_signed_without_recipient.settings = settings
783
- response_valid_signed_without_recipient.settings.assertion_consumer_service_url = 'not-the-recipient'
784
- assert response_valid_signed_without_recipient.send(:validate_subject_confirmation)
785
- assert_empty response_valid_signed_without_recipient.errors
786
- end
787
-
788
- it "return true when the skip_subject_confirmation option is passed and the subject confirmation is valid" do
789
- opts = {}
790
- opts[:skip_subject_confirmation] = true
791
- response_with_skip = OneLogin::RubySaml::Response.new(response_document_valid_signed, opts)
792
- response_with_skip.settings = settings
793
- response_with_skip.settings.assertion_consumer_service_url = 'recipient'
794
- Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
795
- assert response_with_skip.send(:validate_subject_confirmation)
796
- assert_empty response_with_skip.errors
797
- end
798
-
799
- it "return true when the skip_subject_confirmation option is passed and the response has an invalid subject confirmation" do
800
- opts = {}
801
- opts[:skip_subject_confirmation] = true
802
- response_with_skip = OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_noa.xml.base64"), opts)
803
- response_with_skip.settings = settings
804
- Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
805
- assert response_with_skip.send(:validate_subject_confirmation)
806
- assert_empty response_with_skip.errors
807
- end
808
- end
809
-
810
- describe "#validate_session_expiration" do
811
- it "return true when the session has not expired" do
812
- response_valid_signed.settings = settings
813
- assert response_valid_signed.send(:validate_session_expiration)
814
- assert_empty response_valid_signed.errors
815
- end
816
-
817
- it "return false when the session has expired" do
818
- response.settings = settings
819
- assert !response.send(:validate_session_expiration)
820
- assert_includes response.errors, "The attributes have expired, based on the SessionNotOnOrAfter of the AuthnStatement of this Response"
821
- end
822
-
823
- it "returns true when the session has expired, but is still within the allowed_clock_drift" do
824
- drift = (Time.now - Time.parse("2010-11-19T21:57:37Z")) * 60 # seconds ago that this assertion expired
825
- drift += 10 # add a buffer of 10 seconds to make sure the test passes
826
- opts = {}
827
- opts[:allowed_clock_drift] = drift
828
-
829
- response_with_drift = OneLogin::RubySaml::Response.new(response_document_without_recipient, opts)
830
- response_with_drift.settings = settings
831
- assert response_with_drift.send(:validate_session_expiration)
832
- assert_empty response_with_drift.errors
833
- end
834
- end
835
-
836
- describe "#validate_signature" do
837
- it "return true when the signature is valid" do
838
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
839
- response_valid_signed.settings = settings
840
- assert response_valid_signed.send(:validate_signature)
841
- assert_empty response_valid_signed.errors
842
- end
843
-
844
- it "return true when the signature is valid and ds namespace is at the root" do
845
- settings.idp_cert_fingerprint = '5614657ab692b960480389723a36446a5fe1f7ec'
846
- response_with_ds_namespace_at_the_root.settings = settings
847
- assert response_with_ds_namespace_at_the_root.send(:validate_signature)
848
- assert_empty response_with_ds_namespace_at_the_root.errors
849
- end
850
-
851
- it "return true when the signature is valid and fingerprint provided" do
852
- settings.idp_cert_fingerprint = '49:EC:3F:A4:71:8A:1E:C9:DB:70:A7:CC:33:36:96:F0:48:8C:4E:DA'
853
- xml = 'PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERlc3RpbmF0aW9uPSJodHRwczovL2NvZGVycGFkLmlvL3NhbWwvYWNzIiBJRD0iXzEwOGE1ZTg0MDllYzRjZjlhY2QxYzQ2OWU5ZDcxNGFkIiBJblJlc3BvbnNlVG89Il80ZmZmYWE2MC02OTZiLTAxMzMtMzg4Ni0wMjQxZjY1YzA2OTMiIElzc3VlSW5zdGFudD0iMjAxNS0xMS0wOVQyMzo1NTo0M1oiIFZlcnNpb249IjIuMCI+PHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vbG9naW4uaHVsdS5jb208L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOkNhbm9uaWNhbGl6YXRpb25NZXRob2Q+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSI+PC9kczpTaWduYXR1cmVNZXRob2Q+PGRzOlJlZmVyZW5jZSBVUkk9IiNfMTA4YTVlODQwOWVjNGNmOWFjZDFjNDY5ZTlkNzE0YWQiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSI+PC9kczpUcmFuc2Zvcm0+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PC9kczpUcmFuc2Zvcm0+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSI+PC9kczpEaWdlc3RNZXRob2Q+PGRzOkRpZ2VzdFZhbHVlPm9sQllXbTQyRi9oZm0xdHJYTHk2a3V6MXlMUT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+dXNRTmY5WGpKTDRlOXVucnVCdWViSnQ3R0tXM2hJUk9teWVqTm1NMHM4WFhlWHN3WHc4U3ZCZi8zeDNNWEpkWnpNV0pOM3ExN2tGWHN2bTVna1JzbkE9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJQ1FEQ0NBZXFnQXdJQkFnSUpBSVZOdzVLRzR1aTFNQTBHQ1NxR1NJYjNEUUVCQlFVQU1Fd3hDekFKQmdOVkJBWVRBa2RDTVJJd0VBWURWUVFJRXdsQ1pYSnJjMmhwY21VeEVEQU9CZ05WQkFjVEIwNWxkMkoxY25reEZ6QVZCZ05WQkFvVERrMTVJRU52YlhCaGJua2dUSFJrTUI0WERURXlNVEF5TlRBMk1qY3pORm9YRFRJeU1UQXlNekEyTWpjek5Gb3dUREVMTUFrR0ExVUVCaE1DUjBJeEVqQVFCZ05WQkFnVENVSmxjbXR6YUdseVpURVFNQTRHQTFVRUJ4TUhUbVYzWW5WeWVURVhNQlVHQTFVRUNoTU9UWGtnUTI5dGNHRnVlU0JNZEdRd1hEQU5CZ2txaGtpRzl3MEJBUUVGQUFOTEFEQklBa0VBd1NOL2dpMzNSbXBBUW9MUWo3UDZ6QW5OVDBSbjdiakMzMjNuM3ExT25mdm52UjBmUWp2TnQ3ckRrQTVBdjVRbk02VjRZVU5Vbk1mYk9RcTBXTGJMU3dJREFRQUJvNEd1TUlHck1CMEdBMVVkRGdRV0JCUWZJSDFvZkJWcHNSQWNJTUsyaGJsN25nTVRZREI4QmdOVkhTTUVkVEJ6Z0JRZklIMW9mQlZwc1JBY0lNSzJoYmw3bmdNVFlLRlFwRTR3VERFTE1Ba0dBMVVFQmhNQ1IwSXhFakFRQmdOVkJBZ1RDVUpsY210emFHbHlaVEVRTUE0R0ExVUVCeE1IVG1WM1luVnllVEVYTUJVR0ExVUVDaE1PVFhrZ1EyOXRjR0Z1ZVNCTWRHU0NDUUNGVGNPU2h1TG90VEFNQmdOVkhSTUVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJCUVVBQTBFQXFvZ1YzdVBjbEtYRG1EWk1UN3ZsUFl4TEFxQ0dIWnRsQ3h6NGhNNEtTdGxEMi9HTmMxWGlMYjFoL0swQ0pMRG9zckVJYm0zd2lPMk12VEVSclZZU01RPT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48c2FtbHA6U3RhdHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiPjwvc2FtbHA6U3RhdHVzQ29kZT48L3NhbWxwOlN0YXR1cz48c2FtbDpBc3NlcnRpb24geG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il8wMTg4MmRhOTM2OTQ0ZDFlYTZlZmY0NDA2NTc2MzFiNSIgSXNzdWVJbnN0YW50PSIyMDE1LTExLTA5VDIzOjU1OjQzWiIgVmVyc2lvbj0iMi4wIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9sb2dpbi5odWx1LmNvbTwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjwvZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZD48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIj48L2RzOlNpZ25hdHVyZU1ldGhvZD48ZHM6UmVmZXJlbmNlIFVSST0iI18wMTg4MmRhOTM2OTQ0ZDFlYTZlZmY0NDA2NTc2MzFiNSI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIj48L2RzOlRyYW5zZm9ybT48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIj48L2RzOkRpZ2VzdE1ldGhvZD48ZHM6RGlnZXN0VmFsdWU+cmo2YzhucC9BUmV0ZkJ1dWVOSzNPS0xDYnowPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5hR05FemZHM1dLcExKc2ZLRGJSNmpva2d6OEFnZ0FIRVVESEZyd0dsTHVQeWpyNEl3M09NcFNkV2gyL01YK1F3M1dPTk5mNHJNalh5TGVZSFJIVGpMQT09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDUURDQ0FlcWdBd0lCQWdJSkFJVk53NUtHNHVpMU1BMEdDU3FHU0liM0RRRUJCUVVBTUV3eEN6QUpCZ05WQkFZVEFrZENNUkl3RUFZRFZRUUlFd2xDWlhKcmMyaHBjbVV4RURBT0JnTlZCQWNUQjA1bGQySjFjbmt4RnpBVkJnTlZCQW9URGsxNUlFTnZiWEJoYm5rZ1RIUmtNQjRYRFRFeU1UQXlOVEEyTWpjek5Gb1hEVEl5TVRBeU16QTJNamN6TkZvd1RERUxNQWtHQTFVRUJoTUNSMEl4RWpBUUJnTlZCQWdUQ1VKbGNtdHphR2x5WlRFUU1BNEdBMVVFQnhNSFRtVjNZblZ5ZVRFWE1CVUdBMVVFQ2hNT1RYa2dRMjl0Y0dGdWVTQk1kR1F3WERBTkJna3Foa2lHOXcwQkFRRUZBQU5MQURCSUFrRUF3U04vZ2kzM1JtcEFRb0xRajdQNnpBbk5UMFJuN2JqQzMyM24zcTFPbmZ2bnZSMGZRanZOdDdyRGtBNUF2NVFuTTZWNFlVTlVuTWZiT1FxMFdMYkxTd0lEQVFBQm80R3VNSUdyTUIwR0ExVWREZ1FXQkJRZklIMW9mQlZwc1JBY0lNSzJoYmw3bmdNVFlEQjhCZ05WSFNNRWRUQnpnQlFmSUgxb2ZCVnBzUkFjSU1LMmhibDduZ01UWUtGUXBFNHdUREVMTUFrR0ExVUVCaE1DUjBJeEVqQVFCZ05WQkFnVENVSmxjbXR6YUdseVpURVFNQTRHQTFVRUJ4TUhUbVYzWW5WeWVURVhNQlVHQTFVRUNoTU9UWGtnUTI5dGNHRnVlU0JNZEdTQ0NRQ0ZUY09TaHVMb3RUQU1CZ05WSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkJRVUFBMEVBcW9nVjN1UGNsS1hEbURaTVQ3dmxQWXhMQXFDR0hadGxDeHo0aE00S1N0bEQyL0dOYzFYaUxiMWgvSzBDSkxEb3NyRUlibTN3aU8yTXZURVJyVllTTVE9PTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sOlN1YmplY3Q+PHNhbWw6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6ZW1haWxBZGRyZXNzIiBTUE5hbWVRdWFsaWZpZXI9Imh0dHBzOi8vY29kZXJwYWQuaW8iPm1hdHQuanVyaWtAaHVsdS5jb208L3NhbWw6TmFtZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBJblJlc3BvbnNlVG89Il80ZmZmYWE2MC02OTZiLTAxMzMtMzg4Ni0wMjQxZjY1YzA2OTMiIE5vdE9uT3JBZnRlcj0iMjAxNS0xMS0xMFQwMDoxMDo0M1oiIFJlY2lwaWVudD0iaHR0cHM6Ly9jb2RlcnBhZC5pby9zYW1sL2FjcyI+PC9zYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhPjwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE1LTExLTA5VDIyOjU1OjQzWiIgTm90T25PckFmdGVyPSIyMDE1LTExLTEwVDAwOjEwOjQzWiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDpBdWRpZW5jZT5odHRwczovL2NvZGVycGFkLmlvPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNS0xMS0wOVQyMzo1NTo0M1oiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlIE5hbWU9IkdpdmVuLW5hbWUiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlPk1hdHQ8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iU3VybmFtZSI+PHNhbWw6QXR0cmlidXRlVmFsdWU+SnVyaWs8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iRW1haWwiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlPm1hdHQuanVyaWtAaHVsdS5jb208L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48L3NhbWw6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDpBc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4='
854
- response_x = OneLogin::RubySaml::Response.new(xml)
855
- response_x.settings = settings
856
- assert response_x.send(:validate_signature)
857
- assert_empty response_x.errors
858
- end
859
-
860
- it "return false when no fingerprint" do
861
- settings.idp_cert_fingerprint = nil
862
- settings.idp_cert = nil
863
- response.settings = settings
864
- assert !response.send(:validate_signature)
865
- assert_includes response.errors, "Invalid Signature on SAML Response"
866
- end
867
-
868
- it "return false when the signature is invalid" do
869
- settings.idp_cert_fingerprint = signature_fingerprint_1
870
- response.settings = settings
871
- assert !response.send(:validate_signature)
872
- assert_includes response.errors, "Invalid Signature on SAML Response"
873
- end
874
-
875
- it "return false when no X509Certificate and not cert provided at settings" do
876
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
877
- settings.idp_cert = nil
878
- response_valid_signed_without_x509certificate.settings = settings
879
- assert !response_valid_signed_without_x509certificate.send(:validate_signature)
880
- assert_includes response_valid_signed_without_x509certificate.errors, "Invalid Signature on SAML Response"
881
- end
882
-
883
- it "return false when cert expired and check_idp_cert_expiration enabled" do
884
- settings.idp_cert_fingerprint = nil
885
- settings.idp_cert = ruby_saml_cert_text
886
- settings.security[:check_idp_cert_expiration] = true
887
- response_valid_signed.settings = settings
888
- assert !response_valid_signed.send(:validate_signature)
889
- assert_includes response_valid_signed.errors, "IdP x509 certificate expired"
890
- end
891
-
892
- it "return false when no X509Certificate and the cert provided at settings mismatches" do
893
- settings.idp_cert_fingerprint = nil
894
- settings.idp_cert = signature_1
895
- response_valid_signed_without_x509certificate.settings = settings
896
- assert !response_valid_signed_without_x509certificate.send(:validate_signature)
897
- assert_includes response_valid_signed_without_x509certificate.errors, "Invalid Signature on SAML Response"
898
- end
899
-
900
- it "return true when no X509Certificate and the cert provided at settings matches" do
901
- settings.idp_cert_fingerprint = nil
902
- settings.idp_cert = ruby_saml_cert_text
903
- response_valid_signed_without_x509certificate.settings = settings
904
- assert response_valid_signed_without_x509certificate.send(:validate_signature)
905
- assert_empty response_valid_signed_without_x509certificate.errors
906
- end
907
-
908
- it "return false when signature wrapping attack" do
909
- signature_wrapping_attack = read_invalid_response("signature_wrapping_attack.xml.base64")
910
- response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack)
911
- response_wrapped.stubs(:conditions).returns(nil)
912
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
913
- settings.idp_cert_fingerprint = "afe71c28ef740bc87425be13a2263d37971da1f9"
914
- response_wrapped.settings = settings
915
- assert !response_wrapped.send(:validate_signature)
916
- assert_includes response_wrapped.errors, "Invalid Signature on SAML Response"
917
- assert_includes response_wrapped.errors, "Signed element id #pfxc3d2b542-0f7e-8767-8e87-5b0dc6913375 is not found"
918
- end
919
- end
920
-
921
- describe "#validate_signature with multiple idp certs" do
922
- it "return true when at least a cert on idp_cert_multi is valid" do
923
- settings.idp_cert_multi = {
924
- :signing => [ruby_saml_cert_text2, ruby_saml_cert_text],
925
- :encryption => []
926
- }
927
- response_valid_signed.settings = settings
928
- assert response_valid_signed.send(:validate_signature)
929
- assert_empty response_valid_signed.errors
930
- end
931
-
932
- it "return false when none cert on idp_cert_multi is valid" do
933
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
934
- settings.idp_cert_multi = {
935
- :signing => [ruby_saml_cert_text2, ruby_saml_cert_text2],
936
- :encryption => []
937
- }
938
- response_valid_signed.settings = settings
939
- assert !response_valid_signed.send(:validate_signature)
940
- assert_includes response_valid_signed.errors, "Invalid Signature on SAML Response"
941
- end
942
- end
943
-
944
- describe "#validate nameid" do
945
- it "return false when no nameid element and required by settings" do
946
- settings.security[:want_name_id] = true
947
- response_no_nameid.settings = settings
948
- assert !response_no_nameid.send(:validate_name_id)
949
- assert_includes response_no_nameid.errors, "No NameID element found in the assertion of the Response"
950
- end
951
-
952
- it "return false when no nameid element and required by settings" do
953
- response_empty_nameid.settings = settings
954
- assert !response_empty_nameid.send(:validate_name_id)
955
- assert_includes response_empty_nameid.errors, "An empty NameID value found"
956
- end
957
-
958
- it "return false when no nameid value" do
959
- response_empty_nameid.settings = settings
960
- assert !response_empty_nameid.send(:validate_name_id)
961
- assert_includes response_empty_nameid.errors, "An empty NameID value found"
962
- end
963
-
964
- it "return false when wrong_spnamequalifier" do
965
- settings.sp_entity_id = 'sp_entity_id'
966
- response_wrong_spnamequalifier.settings = settings
967
- assert !response_wrong_spnamequalifier.send(:validate_name_id)
968
- assert_includes response_wrong_spnamequalifier.errors, "The SPNameQualifier value mistmatch the SP entityID value."
969
- end
970
-
971
- it "return true when no nameid element but not required by settings" do
972
- settings.security[:want_name_id] = false
973
- response_no_nameid.settings = settings
974
- assert response_no_nameid.send(:validate_name_id)
975
- end
976
-
977
- it "return true when nameid is valid and response_wrong_spnamequalifier matches the SP issuer" do
978
- settings.sp_entity_id = 'wrong-sp-entityid'
979
- response_wrong_spnamequalifier.settings = settings
980
- assert response_wrong_spnamequalifier.send(:validate_name_id)
981
- end
982
- end
983
-
984
- describe "#nameid" do
985
- it "extract the value of the name id element" do
986
- assert_equal "support@onelogin.com", response.nameid
987
- assert_equal "someone@example.com", response_with_signed_assertion.nameid
988
- end
989
-
990
- it "be extractable from an OpenSAML response" do
991
- response_open_saml = OneLogin::RubySaml::Response.new(fixture(:open_saml))
992
- assert_equal "someone@example.org", response_open_saml.nameid
993
- end
994
-
995
- it "be extractable from a Simple SAML PHP response" do
996
- response_ssp = OneLogin::RubySaml::Response.new(fixture(:simple_saml_php))
997
- assert_equal "someone@example.com", response_ssp.nameid
998
- end
999
- end
1000
-
1001
- describe "#name_id_format" do
1002
- it "extract the value of the name id element" do
1003
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", response.name_id_format
1004
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", response_with_signed_assertion.name_id_format
1005
- end
1006
- end
1007
-
1008
- describe "#sessionindex" do
1009
- it "extract the value of the sessionindex element" do
1010
- response = OneLogin::RubySaml::Response.new(fixture(:simple_saml_php))
1011
- assert_equal "_51be37965feb5579d803141076936dc2e9d1d98ebf", response.sessionindex
1012
- end
1013
- end
1014
-
1015
- describe "#check_one_conditions" do
1016
- it "return false when none or more than one conditions element" do
1017
- response_no_conditions.soft = true
1018
- assert !response_no_conditions.send(:validate_one_conditions)
1019
- assert_includes response_no_conditions.errors, "The Assertion must include one Conditions element"
1020
- end
1021
-
1022
- it "return true when one conditions element" do
1023
- response.soft = true
1024
- assert response.send(:validate_one_conditions)
1025
- end
1026
-
1027
- it "return true when no conditions are present and skip_conditions is true" do
1028
- response_no_conditions_with_skip.soft = true
1029
- assert response_no_conditions_with_skip.send(:validate_one_conditions)
1030
- end
1031
- end
1032
-
1033
- describe "#check_one_authnstatement" do
1034
- it "return false when none or more than one authnstatement element" do
1035
- response_no_authnstatement.soft = true
1036
- assert !response_no_authnstatement.send(:validate_one_authnstatement)
1037
- assert_includes response_no_authnstatement.errors, "The Assertion must include one AuthnStatement element"
1038
- end
1039
-
1040
- it "return true when one authnstatement element" do
1041
- response.soft = true
1042
- assert response.send(:validate_one_authnstatement)
1043
- end
1044
-
1045
- it "return true when SAML Response is empty but skip_authstatement option is used" do
1046
- response_no_authnstatement_with_skip.soft = true
1047
- assert response_no_authnstatement_with_skip.send(:validate_one_authnstatement)
1048
- assert_empty response_empty_destination_with_skip.errors
1049
- end
1050
- end
1051
-
1052
- describe "#check_conditions" do
1053
- it "check time conditions" do
1054
- response.soft = true
1055
- assert !response.send(:validate_conditions)
1056
- response_time_updated = OneLogin::RubySaml::Response.new(response_document_without_recipient_with_time_updated)
1057
- response_time_updated.soft = true
1058
- assert response_time_updated.send(:validate_conditions)
1059
- Timecop.freeze(Time.parse("2011-06-14T18:25:01.516Z")) do
1060
- response_with_saml2_namespace = OneLogin::RubySaml::Response.new(response_document_with_saml2_namespace)
1061
- response_with_saml2_namespace.soft = true
1062
- assert response_with_saml2_namespace.send(:validate_conditions)
1063
- end
1064
- end
1065
-
1066
- it "optionally allows for clock drift" do
1067
- # The NotBefore condition in the document is 2011-06-14T18:21:01.516Z
1068
- Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
1069
- settings.soft = true
1070
- special_response_with_saml2_namespace = OneLogin::RubySaml::Response.new(
1071
- response_document_with_saml2_namespace,
1072
- :allowed_clock_drift => 0.515,
1073
- :settings => settings
1074
- )
1075
- assert !special_response_with_saml2_namespace.send(:validate_conditions)
1076
- end
1077
-
1078
- Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
1079
- special_response_with_saml2_namespace = OneLogin::RubySaml::Response.new(
1080
- response_document_with_saml2_namespace,
1081
- :allowed_clock_drift => 0.516
1082
- )
1083
- assert special_response_with_saml2_namespace.send(:validate_conditions)
1084
- end
1085
-
1086
- Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
1087
- settings.soft = true
1088
- special_response_with_saml2_namespace = OneLogin::RubySaml::Response.new(
1089
- response_document_with_saml2_namespace,
1090
- :allowed_clock_drift => '0.515',
1091
- :settings => settings
1092
- )
1093
- assert !special_response_with_saml2_namespace.send(:validate_conditions)
1094
- end
1095
-
1096
- Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
1097
- special_response_with_saml2_namespace = OneLogin::RubySaml::Response.new(
1098
- response_document_with_saml2_namespace,
1099
- :allowed_clock_drift => '0.516'
1100
- )
1101
- assert special_response_with_saml2_namespace.send(:validate_conditions)
1102
- end
1103
- end
1104
- end
1105
-
1106
- describe "#attributes" do
1107
- it "extract the first attribute in a hash accessed via its symbol" do
1108
- assert_equal "demo", response.attributes[:uid]
1109
- end
1110
-
1111
- it "extract the first attribute in a hash accessed via its name" do
1112
- assert_equal "demo", response.attributes["uid"]
1113
- end
1114
-
1115
- it "extract all attributes" do
1116
- assert_equal "demo", response.attributes[:uid]
1117
- assert_equal "value", response.attributes[:another_value]
1118
- end
1119
-
1120
- it "work for implicit namespaces" do
1121
- assert_equal "someone@example.com", response_with_signed_assertion.attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
1122
- end
1123
-
1124
- it "extract attributes from all AttributeStatement tags" do
1125
- assert_equal "smith", response_with_multiple_attribute_statements.attributes[:surname]
1126
- assert_equal "bob", response_with_multiple_attribute_statements.attributes[:firstname]
1127
- end
1128
-
1129
- it "not raise on responses without attributes" do
1130
- assert_equal OneLogin::RubySaml::Attributes.new, response_unsigned.attributes
1131
- end
1132
-
1133
- describe "#encrypted attributes" do
1134
- it "raise error when the assertion contains encrypted attributes but no private key to decrypt" do
1135
- settings.private_key = nil
1136
- response_encrypted_attrs.settings = settings
1137
- assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedAttribute found and no SP private key found on the settings to decrypt it") do
1138
- attrs = response_encrypted_attrs.attributes
1139
- end
1140
- end
1141
-
1142
- it "extract attributes when the assertion contains encrypted attributes and the private key is provided" do
1143
- settings.certificate = ruby_saml_cert_text
1144
- settings.private_key = ruby_saml_key_text
1145
- response_encrypted_attrs.settings = settings
1146
- attributes = response_encrypted_attrs.attributes
1147
- assert_equal "test", attributes[:uid]
1148
- assert_equal "test@example.com", attributes[:mail]
1149
- end
1150
- end
1151
-
1152
- it "return false when validating a response with duplicate attributes" do
1153
- response_duplicated_attributes.settings = settings
1154
- response_duplicated_attributes.options[:check_duplicated_attributes] = true
1155
- assert !response_duplicated_attributes.send(:validate_no_duplicated_attributes)
1156
- assert_includes response_duplicated_attributes.errors, "Found an Attribute element with duplicated Name"
1157
- end
1158
-
1159
- it "return true when validating a response with duplicate attributes but skip check" do
1160
- response_duplicated_attributes.settings = settings
1161
- assert response_duplicated_attributes.send(:validate_no_duplicated_attributes)
1162
- end
1163
-
1164
- describe "#multiple values" do
1165
- it "extract single value as string" do
1166
- assert_equal "demo", response_multiple_attr_values.attributes[:uid]
1167
- end
1168
-
1169
- it "extract single value as string in compatibility mode off" do
1170
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1171
- assert_equal ["demo"], response_multiple_attr_values.attributes[:uid]
1172
- # classes are not reloaded between tests so restore default
1173
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1174
- end
1175
-
1176
- it "extract first of multiple values as string for b/w compatibility" do
1177
- assert_equal 'value1', response_multiple_attr_values.attributes[:another_value]
1178
- end
1179
-
1180
- it "extract first of multiple values as string for b/w compatibility in compatibility mode off" do
1181
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1182
- assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes[:another_value]
1183
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1184
- end
1185
-
1186
- it "return array with all attributes when asked in XML order" do
1187
- assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
1188
- end
1189
-
1190
- it "return array with all attributes when asked in XML order in compatibility mode off" do
1191
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1192
- assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
1193
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1194
- end
1195
-
1196
- it "return first of multiple values when multiple Attribute tags in XML" do
1197
- assert_equal 'role1', response_multiple_attr_values.attributes[:role]
1198
- end
1199
-
1200
- it "return first of multiple values when multiple Attribute tags in XML in compatibility mode off" do
1201
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1202
- assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes[:role]
1203
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1204
- end
1205
-
1206
- it "return all of multiple values in reverse order when multiple Attribute tags in XML" do
1207
- assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
1208
- end
1209
-
1210
- it "return all of multiple values in reverse order when multiple Attribute tags in XML in compatibility mode off" do
1211
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1212
- assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
1213
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1214
- end
1215
-
1216
- it "return all of multiple values when multiple Attribute tags in multiple AttributeStatement tags" do
1217
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1218
- assert_equal ['role1', 'role2', 'role3'], response_with_multiple_attribute_statements.attributes.multi(:role)
1219
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1220
- end
1221
-
1222
- it "return nil value correctly" do
1223
- assert_nil response_multiple_attr_values.attributes[:attribute_with_nil_value]
1224
- end
1225
-
1226
- it "return nil value correctly when not in compatibility mode off" do
1227
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1228
- assert_equal [nil], response_multiple_attr_values.attributes[:attribute_with_nil_value]
1229
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1230
- end
1231
-
1232
- it "return multiple values including nil and empty string" do
1233
- response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
1234
- assert_equal ["", "valuePresent", nil, nil], response.attributes.multi(:attribute_with_nils_and_empty_strings)
1235
- end
1236
-
1237
- it "return multiple values from [] when not in compatibility mode off" do
1238
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1239
- assert_equal ["", "valuePresent", nil, nil], response_multiple_attr_values.attributes[:attribute_with_nils_and_empty_strings]
1240
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1241
- end
1242
-
1243
- it "check what happens when trying retrieve attribute that does not exists" do
1244
- assert_nil response_multiple_attr_values.attributes[:attribute_not_exists]
1245
- assert_nil response_multiple_attr_values.attributes.single(:attribute_not_exists)
1246
- assert_nil response_multiple_attr_values.attributes.multi(:attribute_not_exists)
1247
-
1248
- OneLogin::RubySaml::Attributes.single_value_compatibility = false
1249
- assert_nil response_multiple_attr_values.attributes[:attribute_not_exists]
1250
- assert_nil response_multiple_attr_values.attributes.single(:attribute_not_exists)
1251
- assert_nil response_multiple_attr_values.attributes.multi(:attribute_not_exists)
1252
- OneLogin::RubySaml::Attributes.single_value_compatibility = true
1253
- end
1254
-
1255
- end
1256
- end
1257
-
1258
- describe "#session_expires_at" do
1259
- it "extract the value of the SessionNotOnOrAfter attribute" do
1260
- assert response.session_expires_at.is_a?(Time)
1261
- end
1262
-
1263
- it "return nil when the value of the SessionNotOnOrAfter is not set" do
1264
- assert_nil response_without_attributes.session_expires_at
1265
- end
1266
- end
1267
-
1268
- describe "#success" do
1269
- it "find a status code that says success" do
1270
- response.success?
1271
- end
1272
- end
1273
-
1274
- describe '#xpath_first_from_signed_assertion' do
1275
- it 'not allow arbitrary code execution' do
1276
- malicious_response_document = fixture('response_eval', false)
1277
- malicious_response = OneLogin::RubySaml::Response.new(malicious_response_document)
1278
- malicious_response.send(:xpath_first_from_signed_assertion)
1279
- assert_nil $evalled
1280
- end
1281
- end
1282
-
1283
- describe '#sign_document' do
1284
- it 'Sign an unsigned SAML Response XML and initiate the SAML object with it' do
1285
- xml = Base64.decode64(fixture("test_sign.xml"))
1286
-
1287
- document = XMLSecurity::Document.new(xml)
1288
-
1289
- formatted_cert = OneLogin::RubySaml::Utils.format_cert(ruby_saml_cert_text)
1290
- cert = OpenSSL::X509::Certificate.new(formatted_cert)
1291
-
1292
- formatted_private_key = OneLogin::RubySaml::Utils.format_private_key(ruby_saml_key_text)
1293
- private_key = OpenSSL::PKey::RSA.new(formatted_private_key)
1294
- document.sign_document(private_key, cert)
1295
-
1296
- signed_response = OneLogin::RubySaml::Response.new(document.to_s)
1297
- settings.assertion_consumer_service_url = "http://recipient"
1298
- settings.idp_cert = ruby_saml_cert_text
1299
- signed_response.settings = settings
1300
- Timecop.freeze(Time.parse("2015-03-18T04:50:24Z")) do
1301
- assert signed_response.is_valid?
1302
- end
1303
- assert_empty signed_response.errors
1304
- end
1305
- end
1306
-
1307
- describe '#want_assertion_signed' do
1308
- before do
1309
- settings.security[:want_assertions_signed] = true
1310
- @signed_assertion = OneLogin::RubySaml::Response.new(response_document_with_signed_assertion, :settings => settings)
1311
- @no_signed_assertion = OneLogin::RubySaml::Response.new(response_document_valid_signed, :settings => settings)
1312
- end
1313
-
1314
-
1315
- it 'returns false if :want_assertion_signed enabled and Assertion not signed' do
1316
- assert !@no_signed_assertion.send(:validate_signed_elements)
1317
- assert_includes @no_signed_assertion.errors, "The Assertion of the Response is not signed and the SP requires it"
1318
-
1319
- end
1320
-
1321
- it 'returns true if :want_assertion_signed enabled and Assertion is signed' do
1322
- assert @signed_assertion.send(:validate_signed_elements)
1323
- assert_empty @signed_assertion.errors
1324
- end
1325
- end
1326
-
1327
- describe "retrieve nameID" do
1328
- it 'is possible when nameID inside the assertion' do
1329
- response_valid_signed.settings = settings
1330
- assert_equal "test@onelogin.com", response_valid_signed.nameid
1331
- end
1332
-
1333
- it 'is not possible when encryptID inside the assertion but no private key' do
1334
- response_encrypted_nameid.settings = settings
1335
- assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedID found and no SP private key found on the settings to decrypt it") do
1336
- assert_equal "test@onelogin.com", response_encrypted_nameid.nameid
1337
- end
1338
-
1339
- assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedID found and no SP private key found on the settings to decrypt it") do
1340
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", response_encrypted_nameid.name_id_format
1341
- end
1342
- end
1343
-
1344
- it 'is possible when encryptID inside the assertion and settings has the private key' do
1345
- settings.private_key = ruby_saml_key_text
1346
- response_encrypted_nameid.settings = settings
1347
- assert_equal "test@onelogin.com", response_encrypted_nameid.nameid
1348
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", response_encrypted_nameid.name_id_format
1349
- end
1350
-
1351
- end
1352
-
1353
- describe 'try to initialize an encrypted response' do
1354
- it 'raise if an encrypted assertion is found and no sp private key to decrypt it' do
1355
- error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it. Be sure you provided the :settings parameter at the initialize method"
1356
-
1357
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
1358
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion)
1359
- end
1360
-
1361
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
1362
- response2 = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1363
- end
1364
-
1365
- settings.certificate = ruby_saml_cert_text
1366
- settings.private_key = ruby_saml_key_text
1367
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
1368
- response3 = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion)
1369
- response3.settings
1370
- end
1371
- end
1372
-
1373
- it 'raise if an encrypted assertion is found and the sp private key is wrong' do
1374
- settings.certificate = ruby_saml_cert_text
1375
- wrong_private_key = ruby_saml_key_text.sub!('A', 'B')
1376
- settings.private_key = wrong_private_key
1377
-
1378
- error_msg = "Neither PUB key nor PRIV key: nested asn1 error"
1379
- assert_raises(OpenSSL::PKey::RSAError, error_msg) do
1380
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1381
- end
1382
- end
1383
-
1384
- it 'return true if an encrypted assertion is found and settings initialized with private_key' do
1385
- settings.certificate = ruby_saml_cert_text
1386
- settings.private_key = ruby_saml_key_text
1387
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1388
- assert response.decrypted_document
1389
-
1390
- response2 = OneLogin::RubySaml::Response.new(signed_message_encrypted_signed_assertion, :settings => settings)
1391
- assert response2.decrypted_document
1392
-
1393
- response3 = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_signed_assertion, :settings => settings)
1394
- assert response3.decrypted_document
1395
-
1396
- response4 = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_unsigned_assertion, :settings => settings)
1397
- assert response4.decrypted_document
1398
-
1399
- assert OneLogin::RubySaml::Response.new(
1400
- Base64.encode64(File.read('test/responses/unsigned_encrypted_adfs.xml')),
1401
- :settings => settings
1402
- ).decrypted_document
1403
- end
1404
- end
1405
-
1406
- describe "retrieve nameID and attributes from encrypted assertion" do
1407
-
1408
- before do
1409
- settings.idp_cert_fingerprint = 'EE:17:4E:FB:A8:81:71:12:0D:2A:78:43:BC:E7:0C:07:58:79:F4:F4'
1410
- settings.sp_entity_id = 'http://rubysaml.com:3000/saml/metadata'
1411
- settings.assertion_consumer_service_url = 'http://rubysaml.com:3000/saml/acs'
1412
- settings.certificate = ruby_saml_cert_text
1413
- settings.private_key = ruby_saml_key_text
1414
- end
1415
-
1416
- it 'is possible when signed_message_encrypted_unsigned_assertion' do
1417
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1418
- Timecop.freeze(Time.parse("2015-03-19T14:30:31Z")) do
1419
- assert response.is_valid?
1420
- assert_empty response.errors
1421
- assert_equal "test", response.attributes[:uid]
1422
- assert_equal "98e2bb61075e951b37d6b3be6954a54b340d86c7", response.nameid
1423
- end
1424
- end
1425
-
1426
- it 'is possible when signed_message_encrypted_signed_assertion' do
1427
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_signed_assertion, :settings => settings)
1428
- Timecop.freeze(Time.parse("2015-03-19T14:30:31Z")) do
1429
- assert response.is_valid?
1430
- assert_empty response.errors
1431
- assert_equal "test", response.attributes[:uid]
1432
- assert_equal "98e2bb61075e951b37d6b3be6954a54b340d86c7", response.nameid
1433
- end
1434
- end
1435
-
1436
- it 'is possible when unsigned_message_encrypted_signed_assertion' do
1437
- response = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_signed_assertion, :settings => settings)
1438
- Timecop.freeze(Time.parse("2015-03-19T14:30:31Z")) do
1439
- assert response.is_valid?
1440
- assert_empty response.errors
1441
- assert_equal "test", response.attributes[:uid]
1442
- assert_equal "98e2bb61075e951b37d6b3be6954a54b340d86c7", response.nameid
1443
- end
1444
- end
1445
-
1446
- it 'is not possible when unsigned_message_encrypted_unsigned_assertion' do
1447
- response = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_unsigned_assertion, :settings => settings)
1448
- Timecop.freeze(Time.parse("2015-03-19T14:30:31Z")) do
1449
- assert !response.is_valid?
1450
- assert_includes response.errors, "Found an unexpected number of Signature Element. SAML Response rejected"
1451
- end
1452
- end
1453
- end
1454
-
1455
- describe "#decrypt_assertion" do
1456
- before do
1457
- settings.private_key = ruby_saml_key_text
1458
- end
1459
-
1460
- describe "check right settings" do
1461
-
1462
- it "is not possible to decrypt the assertion if no private key" do
1463
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1464
-
1465
- encrypted_assertion_node = REXML::XPath.first(
1466
- response.document,
1467
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1468
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1469
- )
1470
- response.settings.private_key = nil
1471
-
1472
- error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it"
1473
- assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
1474
- decrypted = response.send(:decrypt_assertion, encrypted_assertion_node)
1475
- end
1476
- end
1477
-
1478
- it "is possible to decrypt the assertion if private key" do
1479
- response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
1480
-
1481
- encrypted_assertion_node = REXML::XPath.first(
1482
- response.document,
1483
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1484
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1485
- )
1486
- decrypted = response.send(:decrypt_assertion, encrypted_assertion_node)
1487
-
1488
- encrypted_assertion_node2 = REXML::XPath.first(
1489
- decrypted,
1490
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1491
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1492
- )
1493
- assert_nil encrypted_assertion_node2
1494
- assert decrypted.name, "Assertion"
1495
- end
1496
-
1497
- it "is possible to decrypt the assertion if private key provided and EncryptedKey RetrievalMethod presents in response" do
1498
- settings.private_key = ruby_saml_key_text
1499
- resp = read_response('response_with_retrieval_method.xml')
1500
- response = OneLogin::RubySaml::Response.new(resp, :settings => settings)
1501
-
1502
- encrypted_assertion_node = REXML::XPath.first(
1503
- response.document,
1504
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1505
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1506
- )
1507
- decrypted = response.send(:decrypt_assertion, encrypted_assertion_node)
1508
-
1509
- encrypted_assertion_node2 = REXML::XPath.first(
1510
- decrypted,
1511
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1512
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1513
- )
1514
-
1515
- assert_nil encrypted_assertion_node2
1516
- assert decrypted.name, "Assertion"
1517
- end
1518
-
1519
- it "is possible to decrypt the assertion if private key but no saml namespace on the Assertion Element that is inside the EncryptedAssertion" do
1520
- unsigned_message_encrypted_assertion_without_saml_namespace = read_response('unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64')
1521
- response = OneLogin::RubySaml::Response.new(unsigned_message_encrypted_assertion_without_saml_namespace, :settings => settings)
1522
- encrypted_assertion_node = REXML::XPath.first(
1523
- response.document,
1524
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1525
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1526
- )
1527
- decrypted = response.send(:decrypt_assertion, encrypted_assertion_node)
1528
-
1529
- encrypted_assertion_node2 = REXML::XPath.first(
1530
- decrypted,
1531
- "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
1532
- { "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
1533
- )
1534
- assert_nil encrypted_assertion_node2
1535
- assert decrypted.name, "Assertion"
1536
- end
1537
- end
1538
-
1539
- describe "check different encrypt methods supported" do
1540
- it "EncryptionMethod DES-192 && Key Encryption Algorithm RSA-1_5" do
1541
- unsigned_message_des192_encrypted_signed_assertion = read_response('unsigned_message_des192_encrypted_signed_assertion.xml.base64')
1542
- response = OneLogin::RubySaml::Response.new(unsigned_message_des192_encrypted_signed_assertion, :settings => settings)
1543
- assert_equal "test", response.attributes[:uid]
1544
- assert_equal "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7", response.nameid
1545
- end
1546
-
1547
- it "EncryptionMethod AES-128 && Key Encryption Algorithm RSA-OAEP-MGF1P" do
1548
- unsigned_message_aes128_encrypted_signed_assertion = read_response('unsigned_message_aes128_encrypted_signed_assertion.xml.base64')
1549
- response = OneLogin::RubySaml::Response.new(unsigned_message_aes128_encrypted_signed_assertion, :settings => settings)
1550
- assert_equal "test", response.attributes[:uid]
1551
- assert_equal "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7", response.nameid
1552
- end
1553
-
1554
- it "EncryptionMethod AES-192 && Key Encryption Algorithm RSA-OAEP-MGF1P" do
1555
- unsigned_message_aes192_encrypted_signed_assertion = read_response('unsigned_message_aes192_encrypted_signed_assertion.xml.base64')
1556
- response = OneLogin::RubySaml::Response.new(unsigned_message_aes192_encrypted_signed_assertion, :settings => settings)
1557
- assert_equal "test", response.attributes[:uid]
1558
- assert_equal "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7", response.nameid
1559
- end
1560
-
1561
- it "EncryptionMethod AES-256 && Key Encryption Algorithm RSA-OAEP-MGF1P" do
1562
- unsigned_message_aes256_encrypted_signed_assertion = read_response('unsigned_message_aes256_encrypted_signed_assertion.xml.base64')
1563
- response = OneLogin::RubySaml::Response.new(unsigned_message_aes256_encrypted_signed_assertion, :settings => settings)
1564
- assert_equal "test", response.attributes[:uid]
1565
- assert_equal "_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7", response.nameid
1566
- end
1567
- end
1568
-
1569
- end
1570
- describe "test qualified name id in attributes" do
1571
-
1572
- it "parsed the nameid" do
1573
- response = OneLogin::RubySaml::Response.new(read_response("signed_nameid_in_atts.xml"), :settings => settings)
1574
- response.settings.idp_cert_fingerprint = 'c51985d947f1be57082025050846eb27f6cab783'
1575
- assert_empty response.errors
1576
- assert_equal "test", response.attributes[:uid]
1577
- assert_equal "http://idp.example.com/metadata.php/ZdrjpwEdw22vKoxWAbZB78/gQ7s=", response.attributes.single('urn:oid:1.3.6.1.4.1.5923.1.1.1.10')
1578
- end
1579
- end
1580
-
1581
- describe "test unqualified name id in attributes" do
1582
-
1583
- it "parsed the nameid" do
1584
- response = OneLogin::RubySaml::Response.new(read_response("signed_unqual_nameid_in_atts.xml"), :settings => settings)
1585
- response.settings.idp_cert_fingerprint = 'c51985d947f1be57082025050846eb27f6cab783'
1586
- assert_empty response.errors
1587
- assert_equal "test", response.attributes[:uid]
1588
- assert_equal "ZdrjpwEdw22vKoxWAbZB78/gQ7s=", response.attributes.single('urn:oid:1.3.6.1.4.1.5923.1.1.1.10')
1589
- end
1590
- end
1591
-
1592
- describe "signature wrapping attack with encrypted assertion" do
1593
- it "should not be valid" do
1594
- settings.private_key = ruby_saml_key_text
1595
- signature_wrapping_attack = read_invalid_response("encrypted_new_attack.xml.base64")
1596
- response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
1597
- response_wrapped.stubs(:conditions).returns(nil)
1598
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
1599
- settings.idp_cert_fingerprint = "385b1eec71143f00db6af936e2ea12a28771d72c"
1600
- assert !response_wrapped.is_valid?
1601
- assert_includes response_wrapped.errors, "Found an invalid Signed Element. SAML Response rejected"
1602
- end
1603
- end
1604
-
1605
- describe "signature wrapping attack - concealed SAML response body" do
1606
- it "should not be valid" do
1607
- signature_wrapping_attack = read_invalid_response("response_with_concealed_signed_assertion.xml")
1608
- response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
1609
- settings.idp_cert_fingerprint = '4b68c453c7d994aad9025c99d5efcf566287fe8d'
1610
- response_wrapped.stubs(:conditions).returns(nil)
1611
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
1612
- assert !response_wrapped.is_valid?
1613
- assert_includes response_wrapped.errors, "SAML Response must contain 1 assertion"
1614
- end
1615
- end
1616
-
1617
- describe "signature wrapping attack - doubled signed assertion SAML response" do
1618
- it "should not be valid" do
1619
- signature_wrapping_attack = read_invalid_response("response_with_doubled_signed_assertion.xml")
1620
- response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
1621
- settings.idp_cert_fingerprint = '4b68c453c7d994aad9025c99d5efcf566287fe8d'
1622
- response_wrapped.stubs(:conditions).returns(nil)
1623
- response_wrapped.stubs(:validate_subject_confirmation).returns(true)
1624
- assert !response_wrapped.is_valid?
1625
- assert_includes response_wrapped.errors, "SAML Response must contain 1 assertion"
1626
- end
1627
- end
1628
- end
1629
- end