ruby-saml 1.7.0 → 1.12.0

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