ruby-saml 1.7.2 → 1.12.2

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