ruby-saml 1.11.0 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.travis.yml +14 -12
- data/README.md +76 -22
- data/changelog.md +27 -0
- data/lib/onelogin/ruby-saml/attributes.rb +24 -1
- data/lib/onelogin/ruby-saml/authrequest.rb +9 -4
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +62 -24
- data/lib/onelogin/ruby-saml/logoutrequest.rb +7 -1
- data/lib/onelogin/ruby-saml/logoutresponse.rb +4 -0
- data/lib/onelogin/ruby-saml/metadata.rb +9 -1
- data/lib/onelogin/ruby-saml/response.rb +38 -16
- data/lib/onelogin/ruby-saml/saml_message.rb +6 -0
- data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
- data/lib/onelogin/ruby-saml/settings.rb +34 -2
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +4 -0
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -14
- data/lib/onelogin/ruby-saml/utils.rb +56 -0
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +34 -6
- data/ruby-saml.gemspec +8 -4
- metadata +22 -282
- data/test/certificates/certificate.der +0 -0
- data/test/certificates/certificate1 +0 -12
- data/test/certificates/certificate_without_head_foot +0 -1
- data/test/certificates/formatted_certificate +0 -14
- data/test/certificates/formatted_chained_certificate +0 -42
- data/test/certificates/formatted_private_key +0 -12
- data/test/certificates/formatted_rsa_private_key +0 -12
- data/test/certificates/invalid_certificate1 +0 -1
- data/test/certificates/invalid_certificate2 +0 -1
- data/test/certificates/invalid_certificate3 +0 -12
- data/test/certificates/invalid_chained_certificate1 +0 -1
- data/test/certificates/invalid_private_key1 +0 -1
- data/test/certificates/invalid_private_key2 +0 -1
- data/test/certificates/invalid_private_key3 +0 -10
- data/test/certificates/invalid_rsa_private_key1 +0 -1
- data/test/certificates/invalid_rsa_private_key2 +0 -1
- data/test/certificates/invalid_rsa_private_key3 +0 -10
- data/test/certificates/ruby-saml-2.crt +0 -15
- data/test/certificates/ruby-saml.crt +0 -14
- data/test/certificates/ruby-saml.key +0 -15
- data/test/idp_metadata_parser_test.rb +0 -594
- data/test/logging_test.rb +0 -62
- data/test/logout_requests/invalid_slo_request.xml +0 -6
- data/test/logout_requests/slo_request.xml +0 -4
- data/test/logout_requests/slo_request.xml.base64 +0 -1
- data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
- data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
- data/test/logout_requests/slo_request_with_session_index.xml +0 -5
- data/test/logout_responses/logoutresponse_fixtures.rb +0 -86
- data/test/logoutrequest_test.rb +0 -260
- data/test/logoutresponse_test.rb +0 -427
- data/test/metadata/idp_descriptor.xml +0 -26
- data/test/metadata/idp_descriptor_2.xml +0 -56
- data/test/metadata/idp_descriptor_3.xml +0 -14
- data/test/metadata/idp_descriptor_4.xml +0 -72
- data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
- data/test/metadata/idp_metadata_multi_certs.xml +0 -75
- data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
- data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
- data/test/metadata/idp_multiple_descriptors.xml +0 -59
- data/test/metadata/idp_multiple_descriptors_2.xml +0 -59
- data/test/metadata/no_idp_descriptor.xml +0 -21
- data/test/metadata_test.rb +0 -331
- data/test/request_test.rb +0 -340
- data/test/response_test.rb +0 -1629
- data/test/responses/adfs_response_sha1.xml +0 -46
- data/test/responses/adfs_response_sha256.xml +0 -46
- data/test/responses/adfs_response_sha384.xml +0 -46
- data/test/responses/adfs_response_sha512.xml +0 -46
- data/test/responses/adfs_response_xmlns.xml +0 -45
- data/test/responses/attackxee.xml +0 -13
- data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
- data/test/responses/invalids/empty_destination.xml.base64 +0 -1
- data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
- data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
- data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
- data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
- data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
- data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
- data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
- data/test/responses/invalids/no_conditions.xml.base64 +0 -1
- data/test/responses/invalids/no_id.xml.base64 +0 -1
- data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
- data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
- data/test/responses/invalids/no_nameid.xml.base64 +0 -1
- data/test/responses/invalids/no_saml2.xml.base64 +0 -1
- data/test/responses/invalids/no_signature.xml.base64 +0 -1
- data/test/responses/invalids/no_status.xml.base64 +0 -1
- data/test/responses/invalids/no_status_code.xml.base64 +0 -1
- data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
- data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
- data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
- data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
- data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
- data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
- data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
- data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
- data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
- data/test/responses/no_signature_ns.xml +0 -48
- data/test/responses/open_saml_response.xml +0 -56
- data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
- data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
- data/test/responses/response_double_status_code.xml.base64 +0 -1
- data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
- data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
- data/test/responses/response_eval.xml +0 -7
- data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
- data/test/responses/response_node_text_attack.xml.base64 +0 -1
- data/test/responses/response_node_text_attack2.xml.base64 +0 -1
- data/test/responses/response_node_text_attack3.xml.base64 +0 -1
- data/test/responses/response_unsigned_xml_base64 +0 -1
- data/test/responses/response_with_ampersands.xml +0 -139
- data/test/responses/response_with_ampersands.xml.base64 +0 -93
- data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
- data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
- data/test/responses/response_with_multiple_attribute_values.xml +0 -67
- data/test/responses/response_with_retrieval_method.xml +0 -26
- data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
- data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
- data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
- data/test/responses/response_with_signed_assertion_3.xml +0 -30
- data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
- data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
- data/test/responses/response_without_attributes.xml.base64 +0 -79
- data/test/responses/response_without_reference_uri.xml.base64 +0 -1
- data/test/responses/response_wrapped.xml.base64 +0 -150
- data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
- data/test/responses/signed_nameid_in_atts.xml +0 -47
- data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
- data/test/responses/simple_saml_php.xml +0 -71
- data/test/responses/starfield_response.xml.base64 +0 -1
- data/test/responses/test_sign.xml +0 -43
- data/test/responses/unsigned_encrypted_adfs.xml +0 -23
- data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
- data/test/responses/valid_response.xml.base64 +0 -1
- data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
- data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
- data/test/saml_message_test.rb +0 -56
- data/test/settings_test.rb +0 -338
- data/test/slo_logoutrequest_test.rb +0 -467
- data/test/slo_logoutresponse_test.rb +0 -233
- data/test/test_helper.rb +0 -333
- data/test/utils_test.rb +0 -259
- data/test/xml_security_test.rb +0 -421
@@ -1,467 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
-
require 'logout_responses/logoutresponse_fixtures'
|
3
|
-
|
4
|
-
require 'onelogin/ruby-saml/slo_logoutrequest'
|
5
|
-
require 'timecop'
|
6
|
-
|
7
|
-
class RubySamlTest < Minitest::Test
|
8
|
-
|
9
|
-
describe "SloLogoutrequest" do
|
10
|
-
|
11
|
-
let(:settings) { OneLogin::RubySaml::Settings.new }
|
12
|
-
let(:logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document) }
|
13
|
-
let(:invalid_logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(invalid_logout_request_document) }
|
14
|
-
|
15
|
-
before do
|
16
|
-
settings.idp_entity_id = 'https://app.onelogin.com/saml/metadata/SOMEACCOUNT'
|
17
|
-
settings.soft = true
|
18
|
-
logout_request.settings = settings
|
19
|
-
invalid_logout_request.settings = settings
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "initiator" do
|
23
|
-
it "raise an exception when logout request is initialized with nil" do
|
24
|
-
assert_raises(ArgumentError) { OneLogin::RubySaml::SloLogoutrequest.new(nil) }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#is_valid?" do
|
29
|
-
it "return false when logout request is initialized with blank data" do
|
30
|
-
logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
|
31
|
-
assert !logout_request_blank.is_valid?
|
32
|
-
assert_includes logout_request_blank.errors, 'Blank logout request'
|
33
|
-
end
|
34
|
-
|
35
|
-
it "return true when the logout request is initialized with valid data" do
|
36
|
-
assert logout_request.is_valid?
|
37
|
-
assert_empty logout_request.errors
|
38
|
-
assert_equal 'someone@example.org', logout_request.nameid
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should be idempotent when the logout request is initialized with invalid data" do
|
42
|
-
assert !invalid_logout_request.is_valid?
|
43
|
-
assert_equal ['Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd'], invalid_logout_request.errors
|
44
|
-
assert !invalid_logout_request.is_valid?
|
45
|
-
assert_equal ['Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd'], invalid_logout_request.errors
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should be idempotent when the logout request is initialized with valid data" do
|
49
|
-
assert logout_request.is_valid?
|
50
|
-
assert_empty logout_request.errors
|
51
|
-
assert logout_request.is_valid?
|
52
|
-
assert_empty logout_request.errors
|
53
|
-
end
|
54
|
-
|
55
|
-
it "collect errors when collect_errors=true" do
|
56
|
-
settings.idp_entity_id = 'http://idp.example.com/invalid'
|
57
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
58
|
-
settings.security[:logout_requests_signed] = true
|
59
|
-
settings.security[:embed_sign] = false
|
60
|
-
settings.certificate = ruby_saml_cert_text
|
61
|
-
settings.private_key = ruby_saml_key_text
|
62
|
-
settings.idp_cert = ruby_saml_cert_text
|
63
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
64
|
-
params = {}
|
65
|
-
params['SAMLRequest'] = logout_request_deflated_base64
|
66
|
-
params['RelayState'] = 'http://invalid.example.com'
|
67
|
-
params['Signature'] = 'invalid_signature'
|
68
|
-
params['SigAlg'] = XMLSecurity::Document::RSA_SHA1
|
69
|
-
options = {}
|
70
|
-
options[:get_params] = params
|
71
|
-
|
72
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
73
|
-
logout_request_sign_test.settings = settings
|
74
|
-
|
75
|
-
collect_errors = true
|
76
|
-
assert !logout_request_sign_test.is_valid?(collect_errors)
|
77
|
-
assert_includes logout_request_sign_test.errors, "Invalid Signature on Logout Request"
|
78
|
-
assert_includes logout_request_sign_test.errors, "Doesn't match the issuer, expected: <http://idp.example.com/invalid>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>"
|
79
|
-
end
|
80
|
-
|
81
|
-
it "raise error for invalid xml" do
|
82
|
-
invalid_logout_request.soft = false
|
83
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { invalid_logout_request.is_valid? }
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "#nameid" do
|
89
|
-
it "extract the value of the name id element" do
|
90
|
-
assert_equal "someone@example.org", logout_request.nameid
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe "#nameid_format" do
|
95
|
-
let(:logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document_with_name_id_format) }
|
96
|
-
|
97
|
-
it "extract the format attribute of the name id element" do
|
98
|
-
assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", logout_request.nameid_format
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe "#issuer" do
|
103
|
-
it "return the issuer inside the logout request" do
|
104
|
-
assert_equal "https://app.onelogin.com/saml/metadata/SOMEACCOUNT", logout_request.issuer
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe "#id" do
|
109
|
-
it "extract the value of the ID attribute" do
|
110
|
-
assert_equal "_c0348950-935b-0131-1060-782bcb56fcaa", logout_request.id
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "#not_on_or_after" do
|
115
|
-
it "extract the value of the NotOnOrAfter attribute" do
|
116
|
-
time_value = '2014-07-17T01:01:48Z'
|
117
|
-
assert_nil logout_request.not_on_or_after
|
118
|
-
logout_request.document.root.attributes['NotOnOrAfter'] = time_value
|
119
|
-
assert_equal Time.parse(time_value), logout_request.not_on_or_after
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
describe '#session_indexes' do
|
124
|
-
it "return empty array when no SessionIndex" do
|
125
|
-
assert_equal [], logout_request.session_indexes
|
126
|
-
end
|
127
|
-
|
128
|
-
it "return an Array with one SessionIndex" do
|
129
|
-
logout_request_with_session_index = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_xml_with_session_index)
|
130
|
-
assert_equal ['_ea853497-c58a-408a-bc23-c849752d9741'], logout_request_with_session_index.session_indexes
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe "#validate_id" do
|
135
|
-
it "return true when there is a valid ID in the logout request" do
|
136
|
-
assert logout_request.send(:validate_id)
|
137
|
-
assert_empty logout_request.errors
|
138
|
-
end
|
139
|
-
|
140
|
-
it "return false when there is an invalid ID in the logout request" do
|
141
|
-
logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
|
142
|
-
assert !logout_request_blank.send(:validate_id)
|
143
|
-
assert_includes logout_request_blank.errors, "Missing ID attribute on Logout Request"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
describe "#validate_version" do
|
148
|
-
it "return true when the logout request is SAML 2.0 Version" do
|
149
|
-
assert logout_request.send(:validate_version)
|
150
|
-
end
|
151
|
-
|
152
|
-
it "return false when the logout request is not SAML 2.0 Version" do
|
153
|
-
logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
|
154
|
-
assert !logout_request_blank.send(:validate_version)
|
155
|
-
assert_includes logout_request_blank.errors, "Unsupported SAML version"
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "#validate_not_on_or_after" do
|
160
|
-
it "return true when the logout request has a valid NotOnOrAfter or does not contain any" do
|
161
|
-
assert logout_request.send(:validate_not_on_or_after)
|
162
|
-
assert_empty logout_request.errors
|
163
|
-
Timecop.freeze Time.parse('2011-06-14T18:25:01.516Z') do
|
164
|
-
time_value = '2014-07-17T01:01:48Z'
|
165
|
-
logout_request.document.root.attributes['NotOnOrAfter'] = time_value
|
166
|
-
assert logout_request.send(:validate_not_on_or_after)
|
167
|
-
assert_empty logout_request.errors
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
it "return false when the logout request has an invalid NotOnOrAfter" do
|
172
|
-
logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
|
173
|
-
assert !logout_request.send(:validate_not_on_or_after)
|
174
|
-
assert /Current time is on or after NotOnOrAfter/.match(logout_request.errors[0])
|
175
|
-
end
|
176
|
-
|
177
|
-
it "raise when the logout request has an invalid NotOnOrAfter" do
|
178
|
-
logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
|
179
|
-
logout_request.soft = false
|
180
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Current time is on or after NotOnOrAfter") do
|
181
|
-
logout_request.send(:validate_not_on_or_after)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe "#validate_request_state" do
|
187
|
-
it "return true when valid logout request xml" do
|
188
|
-
assert logout_request.send(:validate_request_state)
|
189
|
-
assert_empty logout_request.errors
|
190
|
-
assert logout_request.send(:validate_request_state)
|
191
|
-
assert_empty logout_request.errors
|
192
|
-
end
|
193
|
-
|
194
|
-
it "return false when invalid logout request xml" do
|
195
|
-
logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
|
196
|
-
logout_request_blank.soft = true
|
197
|
-
assert !logout_request_blank.send(:validate_request_state)
|
198
|
-
assert_includes logout_request_blank.errors, "Blank logout request"
|
199
|
-
end
|
200
|
-
|
201
|
-
it "raise error for invalid xml" do
|
202
|
-
logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
|
203
|
-
logout_request_blank.soft = false
|
204
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Blank logout request") do
|
205
|
-
logout_request_blank.send(:validate_request_state)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe "#validate_structure" do
|
211
|
-
it "return true when encountering a valid Logout Request xml" do
|
212
|
-
assert logout_request.send(:validate_structure)
|
213
|
-
assert_empty logout_request.errors
|
214
|
-
end
|
215
|
-
|
216
|
-
it "return false when encountering a Logout Request bad formatted" do
|
217
|
-
assert !invalid_logout_request.send(:validate_structure)
|
218
|
-
assert_includes invalid_logout_request.errors, "Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd"
|
219
|
-
end
|
220
|
-
|
221
|
-
it "raise when encountering a Logout Request bad formatted" do
|
222
|
-
invalid_logout_request.soft = false
|
223
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Element '{urn:oasis:names:tc:SAML:2.0:assertion}Issuer': This element is not expected") do
|
224
|
-
invalid_logout_request.send(:validate_structure)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
describe "#validate_issuer" do
|
230
|
-
it "return true when the issuer of the Logout Request matchs the IdP entityId" do
|
231
|
-
logout_request.settings.idp_entity_id = 'https://app.onelogin.com/saml/metadata/SOMEACCOUNT'
|
232
|
-
assert logout_request.send(:validate_issuer)
|
233
|
-
end
|
234
|
-
it "return false when the issuer of the Logout Request does not match the IdP entityId" do
|
235
|
-
logout_request.settings.idp_entity_id = 'http://idp.example.com/invalid'
|
236
|
-
assert !logout_request.send(:validate_issuer)
|
237
|
-
assert_includes logout_request.errors, "Doesn't match the issuer, expected: <#{logout_request.settings.idp_entity_id}>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>"
|
238
|
-
end
|
239
|
-
it "raise when the issuer of the Logout Request does not match the IdP entityId" do
|
240
|
-
logout_request.settings.idp_entity_id = 'http://idp.example.com/invalid'
|
241
|
-
logout_request.soft = false
|
242
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Doesn't match the issuer, expected: <#{logout_request.settings.idp_entity_id}>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>") do
|
243
|
-
logout_request.send(:validate_issuer)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
describe "#validate_signature" do
|
249
|
-
before do
|
250
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
251
|
-
settings.security[:logout_requests_signed] = true
|
252
|
-
settings.security[:embed_sign] = false
|
253
|
-
settings.certificate = ruby_saml_cert_text
|
254
|
-
settings.private_key = ruby_saml_key_text
|
255
|
-
settings.idp_cert = ruby_saml_cert_text
|
256
|
-
end
|
257
|
-
|
258
|
-
it "return true when no idp_cert is provided and option :relax_signature_validation is present" do
|
259
|
-
settings.idp_cert = nil
|
260
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
261
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
262
|
-
params['RelayState'] = params[:RelayState]
|
263
|
-
options = {}
|
264
|
-
options[:get_params] = params
|
265
|
-
options[:relax_signature_validation] = true
|
266
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
267
|
-
logout_request_sign_test.settings = settings
|
268
|
-
assert logout_request_sign_test.send(:validate_signature)
|
269
|
-
end
|
270
|
-
|
271
|
-
it "return false when no idp_cert is provided and no option :relax_signature_validation is present" do
|
272
|
-
settings.idp_cert = nil
|
273
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
274
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
275
|
-
params['RelayState'] = params[:RelayState]
|
276
|
-
options = {}
|
277
|
-
options[:get_params] = params
|
278
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
279
|
-
logout_request_sign_test.settings = settings
|
280
|
-
assert !logout_request_sign_test.send(:validate_signature)
|
281
|
-
end
|
282
|
-
|
283
|
-
it "return true when valid RSA_SHA1 Signature" do
|
284
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
285
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
286
|
-
params['RelayState'] = params[:RelayState]
|
287
|
-
options = {}
|
288
|
-
options[:get_params] = params
|
289
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
290
|
-
logout_request_sign_test.settings = settings
|
291
|
-
assert logout_request_sign_test.send(:validate_signature)
|
292
|
-
end
|
293
|
-
|
294
|
-
it "return true when valid RSA_SHA256 Signature" do
|
295
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
296
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
297
|
-
options = {}
|
298
|
-
options[:get_params] = params
|
299
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
300
|
-
params['RelayState'] = params[:RelayState]
|
301
|
-
logout_request_sign_test.settings = settings
|
302
|
-
assert logout_request_sign_test.send(:validate_signature)
|
303
|
-
end
|
304
|
-
|
305
|
-
it "return false when invalid RSA_SHA1 Signature" do
|
306
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
307
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
308
|
-
params['RelayState'] = 'http://invalid.example.com'
|
309
|
-
params[:RelayState] = params['RelayState']
|
310
|
-
options = {}
|
311
|
-
options[:get_params] = params
|
312
|
-
|
313
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
314
|
-
logout_request_sign_test.settings = settings
|
315
|
-
assert !logout_request_sign_test.send(:validate_signature)
|
316
|
-
end
|
317
|
-
|
318
|
-
it "raise when invalid RSA_SHA1 Signature" do
|
319
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
320
|
-
settings.soft = false
|
321
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
322
|
-
params['RelayState'] = 'http://invalid.example.com'
|
323
|
-
params[:RelayState] = params['RelayState']
|
324
|
-
options = {}
|
325
|
-
options[:get_params] = params
|
326
|
-
options[:settings] = settings
|
327
|
-
|
328
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
329
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
|
330
|
-
logout_request_sign_test.send(:validate_signature)
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
it "raise when get_params encoding differs from what this library generates" do
|
335
|
-
# Use Logoutrequest only to build the SAMLRequest parameter.
|
336
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
337
|
-
settings.soft = false
|
338
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
|
339
|
-
# Assemble query string.
|
340
|
-
query = OneLogin::RubySaml::Utils.build_query(
|
341
|
-
:type => 'SAMLRequest',
|
342
|
-
:data => params['SAMLRequest'],
|
343
|
-
:relay_state => params['RelayState'],
|
344
|
-
:sig_alg => params['SigAlg']
|
345
|
-
)
|
346
|
-
# Modify the query string so that it encodes the same values,
|
347
|
-
# but with different percent-encoding. Sanity-check that they
|
348
|
-
# really are equialent before moving on.
|
349
|
-
original_query = query.dup
|
350
|
-
query.gsub!("example", "ex%61mple")
|
351
|
-
refute_equal(query, original_query)
|
352
|
-
assert_equal(CGI.unescape(query), CGI.unescape(original_query))
|
353
|
-
# Make normalised signature based on our modified params.
|
354
|
-
sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
|
355
|
-
signature = settings.get_sp_key.sign(sign_algorithm.new, query)
|
356
|
-
params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
|
357
|
-
# Construct SloLogoutrequest and ask it to validate the signature.
|
358
|
-
# It will do it incorrectly, because it will compute it based on re-encoded
|
359
|
-
# query parameters, rather than their original encodings.
|
360
|
-
options = {}
|
361
|
-
options[:get_params] = params
|
362
|
-
options[:settings] = settings
|
363
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
364
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
|
365
|
-
logout_request_sign_test.send(:validate_signature)
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
it "return true even if raw_get_params encoding differs from what this library generates" do
|
370
|
-
# Use Logoutrequest only to build the SAMLRequest parameter.
|
371
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
372
|
-
settings.soft = false
|
373
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
|
374
|
-
# Assemble query string.
|
375
|
-
query = OneLogin::RubySaml::Utils.build_query(
|
376
|
-
:type => 'SAMLRequest',
|
377
|
-
:data => params['SAMLRequest'],
|
378
|
-
:relay_state => params['RelayState'],
|
379
|
-
:sig_alg => params['SigAlg']
|
380
|
-
)
|
381
|
-
# Modify the query string so that it encodes the same values,
|
382
|
-
# but with different percent-encoding. Sanity-check that they
|
383
|
-
# really are equialent before moving on.
|
384
|
-
original_query = query.dup
|
385
|
-
query.gsub!("example", "ex%61mple")
|
386
|
-
refute_equal(query, original_query)
|
387
|
-
assert_equal(CGI.unescape(query), CGI.unescape(original_query))
|
388
|
-
# Make normalised signature based on our modified params.
|
389
|
-
sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
|
390
|
-
signature = settings.get_sp_key.sign(sign_algorithm.new, query)
|
391
|
-
params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
|
392
|
-
# Construct SloLogoutrequest and ask it to validate the signature.
|
393
|
-
# Provide the altered parameter in its raw URI-encoded form,
|
394
|
-
# so that we don't have to guess the value that contributed to the signature.
|
395
|
-
options = {}
|
396
|
-
options[:get_params] = params
|
397
|
-
options[:get_params].delete("RelayState")
|
398
|
-
options[:raw_get_params] = {
|
399
|
-
"RelayState" => "http%3A%2F%2Fex%61mple.com",
|
400
|
-
}
|
401
|
-
options[:settings] = settings
|
402
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
403
|
-
assert logout_request_sign_test.send(:validate_signature)
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
describe "#validate_signature with multiple idp certs" do
|
408
|
-
before do
|
409
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
410
|
-
settings.certificate = ruby_saml_cert_text
|
411
|
-
settings.private_key = ruby_saml_key_text
|
412
|
-
settings.idp_cert = nil
|
413
|
-
settings.security[:logout_requests_signed] = true
|
414
|
-
settings.security[:embed_sign] = false
|
415
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
416
|
-
end
|
417
|
-
|
418
|
-
it "return true when at least a idp_cert is valid" do
|
419
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
420
|
-
params['RelayState'] = params[:RelayState]
|
421
|
-
options = {}
|
422
|
-
options[:get_params] = params
|
423
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
424
|
-
settings.idp_cert_multi = {
|
425
|
-
:signing => [ruby_saml_cert_text2, ruby_saml_cert_text],
|
426
|
-
:encryption => []
|
427
|
-
}
|
428
|
-
logout_request_sign_test.settings = settings
|
429
|
-
assert logout_request_sign_test.send(:validate_signature)
|
430
|
-
end
|
431
|
-
|
432
|
-
it "return false when cert expired and check_idp_cert_expiration expired" do
|
433
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
434
|
-
params['RelayState'] = params[:RelayState]
|
435
|
-
options = {}
|
436
|
-
options[:get_params] = params
|
437
|
-
settings.security[:check_idp_cert_expiration] = true
|
438
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
439
|
-
settings.idp_cert = nil
|
440
|
-
settings.idp_cert_multi = {
|
441
|
-
:signing => [ruby_saml_cert_text],
|
442
|
-
:encryption => []
|
443
|
-
}
|
444
|
-
logout_request_sign_test.settings = settings
|
445
|
-
assert !logout_request_sign_test.send(:validate_signature)
|
446
|
-
assert_includes logout_request_sign_test.errors, "IdP x509 certificate expired"
|
447
|
-
end
|
448
|
-
|
449
|
-
it "return false when none cert on idp_cert_multi is valid" do
|
450
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
451
|
-
params['RelayState'] = params[:RelayState]
|
452
|
-
options = {}
|
453
|
-
options[:get_params] = params
|
454
|
-
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
|
455
|
-
settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
|
456
|
-
settings.idp_cert_multi = {
|
457
|
-
:signing => [ruby_saml_cert_text2, ruby_saml_cert_text2],
|
458
|
-
:encryption => []
|
459
|
-
}
|
460
|
-
logout_request_sign_test.settings = settings
|
461
|
-
assert !logout_request_sign_test.send(:validate_signature)
|
462
|
-
assert_includes logout_request_sign_test.errors, "Invalid Signature on Logout Request"
|
463
|
-
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
end
|