ruby-saml 1.7.2 → 1.12.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

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