ruby-saml 1.8.0 → 1.13.0

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