ruby-saml 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +67 -19
- data/changelog.md +23 -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 +37 -15
- 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
data/test/logging_test.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
-
|
3
|
-
require 'onelogin/ruby-saml/logging'
|
4
|
-
|
5
|
-
class LoggingTest < Minitest::Test
|
6
|
-
|
7
|
-
describe "Logging" do
|
8
|
-
before do
|
9
|
-
OneLogin::RubySaml::Logging.logger = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
after do
|
13
|
-
OneLogin::RubySaml::Logging.logger = ::TEST_LOGGER
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "given no specific logging setup" do
|
17
|
-
it "prints to stdout" do
|
18
|
-
OneLogin::RubySaml::Logging::DEFAULT_LOGGER.expects(:debug).with('hi mom')
|
19
|
-
OneLogin::RubySaml::Logging.debug('hi mom')
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "given a Rails app" do
|
24
|
-
let(:logger) { mock('Logger') }
|
25
|
-
|
26
|
-
before do
|
27
|
-
::Rails = mock('Rails module')
|
28
|
-
::Rails.stubs(:logger).returns(logger)
|
29
|
-
end
|
30
|
-
|
31
|
-
after do
|
32
|
-
Object.instance_eval { remove_const(:Rails) }
|
33
|
-
end
|
34
|
-
|
35
|
-
it "delegates to Rails" do
|
36
|
-
logger.expects(:debug).with('hi mom')
|
37
|
-
logger.expects(:info).with('sup?')
|
38
|
-
|
39
|
-
OneLogin::RubySaml::Logging.debug('hi mom')
|
40
|
-
OneLogin::RubySaml::Logging.info('sup?')
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "given a specific Logger" do
|
45
|
-
let(:logger) { mock('Logger') }
|
46
|
-
|
47
|
-
before { OneLogin::RubySaml::Logging.logger = logger }
|
48
|
-
|
49
|
-
after do
|
50
|
-
OneLogin::RubySaml::Logging.logger = ::TEST_LOGGER
|
51
|
-
end
|
52
|
-
|
53
|
-
it "delegates to the object" do
|
54
|
-
logger.expects(:debug).with('hi mom')
|
55
|
-
logger.expects(:info).with('sup?')
|
56
|
-
|
57
|
-
OneLogin::RubySaml::Logging.debug('hi mom')
|
58
|
-
OneLogin::RubySaml::Logging.info('sup?')
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,6 +0,0 @@
|
|
1
|
-
<samlp:LogoutRequest Version='2.0' ID='_c0348950-935b-0131-1060-782bcb56fcaa' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' IssueInstant='2014-03-21T19:20:13'>
|
2
|
-
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
3
|
-
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
4
|
-
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>someone@example.org</saml:NameID>
|
5
|
-
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>someone2@example.org</saml:NameID>
|
6
|
-
</samlp:LogoutRequest>
|
@@ -1,4 +0,0 @@
|
|
1
|
-
<samlp:LogoutRequest Version='2.0' ID='_c0348950-935b-0131-1060-782bcb56fcaa' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' IssueInstant='2014-03-21T19:20:13'>
|
2
|
-
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
3
|
-
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>someone@example.org</saml:NameID>
|
4
|
-
</samlp:LogoutRequest>
|
@@ -1 +0,0 @@
|
|
1
|
-
PHNhbWxwOkxvZ291dFJlcXVlc3QgVmVyc2lvbj0nMi4wJyBJRD0nX2MwMzQ4OTUwLTkzNWItMDEzMS0xMDYwLTc4MmJjYjU2ZmNhYScgeG1sbnM6c2FtbHA9J3VybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCcgSXNzdWVJbnN0YW50PScyMDE0LTAzLTIxVDE5OjIwOjEzJz4NCiAgPHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9J3VybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24nPmh0dHBzOi8vYXBwLm9uZWxvZ2luLmNvbS9zYW1sL21ldGFkYXRhL1NPTUVBQ0NPVU5UPC9zYW1sOklzc3Vlcj4NCiAgPHNhbWw6TmFtZUlEIHhtbG5zOnNhbWw9J3VybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24nPnNvbWVvbmVAZXhhbXBsZS5vcmc8L3NhbWw6TmFtZUlEPg0KPC9zYW1scDpMb2dvdXRSZXF1ZXN0Pg==
|
@@ -1 +0,0 @@
|
|
1
|
-
ndG7asMwFIDhvdB38KZJlmTHaSxs05B0COQCTdq1yKrqGqxLdWTI41dJOpgOHToKDv93DqpA6MHxre3sGJ7V16ggJK/KQ29NjbKUomSzrtGbpPlsURYUl3nRYspyhhmdU/ywyFrZFvMPKQRKznowwK/JGo3ecCugB26EVsCD5MflbstjlDtvg5V2iHWAUW0MBGFCBCmbYZrjjJ1YyTPKWY6a+7skqS5Rfh32E+ZvRQAoH+IlqPkMwQEnRDiXWqMG2/UmlVaTS4VoFcS7CIIcD7un5Wp1eNmfKjIhJzvsI7NZ/2cHsFpF+1GdhXaDSq3vfpBbMyK396//aL4B
|
@@ -1,4 +0,0 @@
|
|
1
|
-
<samlp:LogoutRequest Version='2.0' ID='_c0348950-935b-0131-1060-782bcb56fcaa' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' IssueInstant='2014-03-21T19:20:13'>
|
2
|
-
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
3
|
-
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'>someone@example.org</saml:NameID>
|
4
|
-
</samlp:LogoutRequest>
|
@@ -1,5 +0,0 @@
|
|
1
|
-
<samlp:LogoutRequest Version='2.0' ID='_c0348950-935b-0131-1060-782bcb56fcaa' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' IssueInstant='2014-03-21T19:20:13'>
|
2
|
-
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
3
|
-
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>someone@example.org</saml:NameID>
|
4
|
-
<samlp:SessionIndex>_ea853497-c58a-408a-bc23-c849752d9741</samlp:SessionIndex>
|
5
|
-
</samlp:LogoutRequest>
|
@@ -1,86 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
|
-
def default_logout_response_opts
|
4
|
-
{
|
5
|
-
:uuid => "_28024690-000e-0130-b6d2-38f6b112be8b",
|
6
|
-
:issue_instant => Time.now.strftime('%Y-%m-%dT%H:%M:%SZ'),
|
7
|
-
:settings => settings
|
8
|
-
}
|
9
|
-
end
|
10
|
-
|
11
|
-
def valid_logout_response_document(opts = {})
|
12
|
-
opts = default_logout_response_opts.merge(opts)
|
13
|
-
|
14
|
-
"<samlp:LogoutResponse
|
15
|
-
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
16
|
-
ID=\"#{random_id}\" Version=\"2.0\"
|
17
|
-
IssueInstant=\"#{opts[:issue_instant]}\"
|
18
|
-
Destination=\"#{opts[:settings].single_logout_service_url}\"
|
19
|
-
InResponseTo=\"#{opts[:uuid]}\">
|
20
|
-
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
|
21
|
-
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
22
|
-
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
23
|
-
Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\">
|
24
|
-
</samlp:StatusCode>
|
25
|
-
</samlp:Status>
|
26
|
-
</samlp:LogoutResponse>"
|
27
|
-
end
|
28
|
-
|
29
|
-
def unsuccessful_logout_response_document(opts = {})
|
30
|
-
opts = default_logout_response_opts.merge(opts)
|
31
|
-
|
32
|
-
"<samlp:LogoutResponse
|
33
|
-
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
34
|
-
ID=\"#{random_id}\" Version=\"2.0\"
|
35
|
-
IssueInstant=\"#{opts[:issue_instant]}\"
|
36
|
-
Destination=\"#{opts[:settings].single_logout_service_url}\"
|
37
|
-
InResponseTo=\"#{opts[:uuid]}\">
|
38
|
-
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
|
39
|
-
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
40
|
-
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
41
|
-
Value=\"urn:oasis:names:tc:SAML:2.0:status:Requester\">
|
42
|
-
</samlp:StatusCode>
|
43
|
-
</samlp:Status>
|
44
|
-
</samlp:LogoutResponse>"
|
45
|
-
end
|
46
|
-
|
47
|
-
def unsuccessful_logout_response_with_message_document(opts = {})
|
48
|
-
opts = default_logout_response_opts.merge(opts)
|
49
|
-
|
50
|
-
"<samlp:LogoutResponse
|
51
|
-
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
52
|
-
ID=\"#{random_id}\" Version=\"2.0\"
|
53
|
-
IssueInstant=\"#{opts[:issue_instant]}\"
|
54
|
-
Destination=\"#{opts[:settings].single_logout_service_url}\"
|
55
|
-
InResponseTo=\"#{opts[:uuid]}\">
|
56
|
-
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
|
57
|
-
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
58
|
-
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
59
|
-
Value=\"urn:oasis:names:tc:SAML:2.0:status:Requester\">
|
60
|
-
</samlp:StatusCode>
|
61
|
-
<samlp:StatusMessage>Logoutrequest expired</samlp:StatusMessage>
|
62
|
-
</samlp:Status>
|
63
|
-
</samlp:LogoutResponse>"
|
64
|
-
end
|
65
|
-
|
66
|
-
def invalid_xml_logout_response_document
|
67
|
-
"<samlp:SomethingAwful
|
68
|
-
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
69
|
-
ID=\"#{random_id}\" Version=\"2.0\">
|
70
|
-
</samlp:SomethingAwful>"
|
71
|
-
end
|
72
|
-
|
73
|
-
def settings
|
74
|
-
@settings ||= OneLogin::RubySaml::Settings.new(
|
75
|
-
{
|
76
|
-
:assertion_consumer_service_url => "http://app.muda.no/sso/consume",
|
77
|
-
:single_logout_service_url => "http://app.muda.no/sso/consume_logout",
|
78
|
-
:issuer => "http://app.muda.no",
|
79
|
-
:sp_name_qualifier => "http://sso.muda.no",
|
80
|
-
:idp_sso_target_url => "http://sso.muda.no/sso",
|
81
|
-
:idp_slo_target_url => "http://sso.muda.no/slo",
|
82
|
-
:idp_cert_fingerprint => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
|
83
|
-
:name_identifier_format => "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
84
|
-
}
|
85
|
-
)
|
86
|
-
end
|
data/test/logoutrequest_test.rb
DELETED
@@ -1,260 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
-
|
3
|
-
require 'onelogin/ruby-saml/logoutrequest'
|
4
|
-
|
5
|
-
class RequestTest < Minitest::Test
|
6
|
-
|
7
|
-
describe "Logoutrequest" do
|
8
|
-
let(:settings) { OneLogin::RubySaml::Settings.new }
|
9
|
-
|
10
|
-
before do
|
11
|
-
settings.idp_slo_target_url = "http://unauth.com/logout"
|
12
|
-
settings.name_identifier_value = "f00f00"
|
13
|
-
end
|
14
|
-
|
15
|
-
it "create the deflated SAMLRequest URL parameter" do
|
16
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
17
|
-
assert_match /^http:\/\/unauth\.com\/logout\?SAMLRequest=/, unauth_url
|
18
|
-
|
19
|
-
inflated = decode_saml_request_payload(unauth_url)
|
20
|
-
assert_match /^<samlp:LogoutRequest/, inflated
|
21
|
-
end
|
22
|
-
|
23
|
-
it "support additional params" do
|
24
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
|
25
|
-
assert_match /&hello=$/, unauth_url
|
26
|
-
|
27
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :foo => "bar" })
|
28
|
-
assert_match /&foo=bar$/, unauth_url
|
29
|
-
end
|
30
|
-
|
31
|
-
it "RelayState cases" do
|
32
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => nil })
|
33
|
-
assert !unauth_url.include?('RelayState')
|
34
|
-
|
35
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => "http://example.com" })
|
36
|
-
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
|
37
|
-
|
38
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => nil })
|
39
|
-
assert !unauth_url.include?('RelayState')
|
40
|
-
|
41
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => "http://example.com" })
|
42
|
-
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
|
43
|
-
end
|
44
|
-
|
45
|
-
it "set sessionindex" do
|
46
|
-
settings.idp_slo_target_url = "http://example.com"
|
47
|
-
sessionidx = OneLogin::RubySaml::Utils.uuid
|
48
|
-
settings.sessionindex = sessionidx
|
49
|
-
|
50
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
51
|
-
inflated = decode_saml_request_payload(unauth_url)
|
52
|
-
|
53
|
-
assert_match /<samlp:SessionIndex/, inflated
|
54
|
-
assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
|
55
|
-
end
|
56
|
-
|
57
|
-
it "set name_identifier_value" do
|
58
|
-
settings.name_identifier_format = "transient"
|
59
|
-
name_identifier_value = "abc123"
|
60
|
-
settings.name_identifier_value = name_identifier_value
|
61
|
-
|
62
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
63
|
-
inflated = decode_saml_request_payload(unauth_url)
|
64
|
-
|
65
|
-
assert_match /<saml:NameID/, inflated
|
66
|
-
assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "when the target url doesn't contain a query string" do
|
70
|
-
it "create the SAMLRequest parameter correctly" do
|
71
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
72
|
-
assert_match /^http:\/\/unauth.com\/logout\?SAMLRequest/, unauth_url
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "when the target url contains a query string" do
|
77
|
-
it "create the SAMLRequest parameter correctly" do
|
78
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
79
|
-
|
80
|
-
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
81
|
-
assert_match /^http:\/\/example.com\?field=value&SAMLRequest/, unauth_url
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe "consumation of logout may need to track the transaction" do
|
86
|
-
it "have access to the request uuid" do
|
87
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
88
|
-
|
89
|
-
unauth_req = OneLogin::RubySaml::Logoutrequest.new
|
90
|
-
unauth_url = unauth_req.create(settings)
|
91
|
-
|
92
|
-
inflated = decode_saml_request_payload(unauth_url)
|
93
|
-
assert_match %r[ID='#{unauth_req.uuid}'], inflated
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe "when the settings indicate to sign (embedded) logout request" do
|
98
|
-
|
99
|
-
before do
|
100
|
-
# sign the logout request
|
101
|
-
settings.security[:logout_requests_signed] = true
|
102
|
-
settings.security[:embed_sign] = true
|
103
|
-
settings.certificate = ruby_saml_cert_text
|
104
|
-
settings.private_key = ruby_saml_key_text
|
105
|
-
end
|
106
|
-
|
107
|
-
it "doesn't sign through create_xml_document" do
|
108
|
-
unauth_req = OneLogin::RubySaml::Logoutrequest.new
|
109
|
-
inflated = unauth_req.create_xml_document(settings).to_s
|
110
|
-
|
111
|
-
refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
112
|
-
refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
113
|
-
refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
114
|
-
end
|
115
|
-
|
116
|
-
it "sign unsigned request" do
|
117
|
-
unauth_req = OneLogin::RubySaml::Logoutrequest.new
|
118
|
-
unauth_req_doc = unauth_req.create_xml_document(settings)
|
119
|
-
inflated = unauth_req_doc.to_s
|
120
|
-
|
121
|
-
refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
122
|
-
refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
123
|
-
refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
124
|
-
|
125
|
-
inflated = unauth_req.sign_document(unauth_req_doc, settings).to_s
|
126
|
-
|
127
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
128
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
129
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
130
|
-
end
|
131
|
-
|
132
|
-
it "signs through create_logout_request_xml_doc" do
|
133
|
-
unauth_req = OneLogin::RubySaml::Logoutrequest.new
|
134
|
-
inflated = unauth_req.create_logout_request_xml_doc(settings).to_s
|
135
|
-
|
136
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
137
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
138
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
139
|
-
end
|
140
|
-
|
141
|
-
it "created a signed logout request" do
|
142
|
-
settings.compress_request = true
|
143
|
-
|
144
|
-
unauth_req = OneLogin::RubySaml::Logoutrequest.new
|
145
|
-
unauth_url = unauth_req.create(settings)
|
146
|
-
|
147
|
-
inflated = decode_saml_request_payload(unauth_url)
|
148
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
149
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
150
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
151
|
-
end
|
152
|
-
|
153
|
-
it "create a signed logout request with 256 digest and signature method" do
|
154
|
-
settings.compress_request = false
|
155
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
156
|
-
settings.security[:digest_method] = XMLSecurity::Document::SHA256
|
157
|
-
|
158
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
|
159
|
-
request_xml = Base64.decode64(params["SAMLRequest"])
|
160
|
-
|
161
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
|
162
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
|
163
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/>], request_xml
|
164
|
-
end
|
165
|
-
|
166
|
-
it "create a signed logout request with 512 digest and signature method RSA_SHA384" do
|
167
|
-
settings.compress_request = false
|
168
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
|
169
|
-
settings.security[:digest_method] = XMLSecurity::Document::SHA512
|
170
|
-
|
171
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
|
172
|
-
request_xml = Base64.decode64(params["SAMLRequest"])
|
173
|
-
|
174
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
|
175
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'/>], request_xml
|
176
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha512'/>], request_xml
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
describe "#create_params when the settings indicate to sign the logout request" do
|
181
|
-
|
182
|
-
let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
|
183
|
-
|
184
|
-
before do
|
185
|
-
# sign the logout request
|
186
|
-
settings.security[:logout_requests_signed] = true
|
187
|
-
settings.security[:embed_sign] = false
|
188
|
-
settings.certificate = ruby_saml_cert_text
|
189
|
-
settings.private_key = ruby_saml_key_text
|
190
|
-
end
|
191
|
-
|
192
|
-
it "create a signature parameter with RSA_SHA1 / SHA1 and validate it" do
|
193
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
194
|
-
|
195
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
196
|
-
assert params['SAMLRequest']
|
197
|
-
assert params[:RelayState]
|
198
|
-
assert params['Signature']
|
199
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
|
200
|
-
|
201
|
-
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
202
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
203
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
204
|
-
|
205
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
206
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
|
207
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
208
|
-
end
|
209
|
-
|
210
|
-
it "create a signature parameter with RSA_SHA256 / SHA256 and validate it" do
|
211
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
212
|
-
|
213
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
214
|
-
assert params['Signature']
|
215
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
|
216
|
-
|
217
|
-
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
218
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
219
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
220
|
-
|
221
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
222
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
|
223
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
224
|
-
end
|
225
|
-
|
226
|
-
it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
|
227
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
|
228
|
-
|
229
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
230
|
-
assert params['Signature']
|
231
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
|
232
|
-
|
233
|
-
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
234
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
235
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
236
|
-
|
237
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
238
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA384
|
239
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
240
|
-
end
|
241
|
-
|
242
|
-
it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
|
243
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
|
244
|
-
|
245
|
-
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
|
246
|
-
assert params['Signature']
|
247
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
|
248
|
-
|
249
|
-
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
250
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
251
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
252
|
-
|
253
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
254
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA512
|
255
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
256
|
-
end
|
257
|
-
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
data/test/logoutresponse_test.rb
DELETED
@@ -1,427 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
-
|
3
|
-
require 'onelogin/ruby-saml/logoutresponse'
|
4
|
-
require 'logout_responses/logoutresponse_fixtures'
|
5
|
-
|
6
|
-
class RubySamlTest < Minitest::Test
|
7
|
-
|
8
|
-
describe "Logoutresponse" do
|
9
|
-
|
10
|
-
let(:valid_logout_response_without_settings) { OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document) }
|
11
|
-
let(:valid_logout_response) { OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings) }
|
12
|
-
|
13
|
-
describe "#new" do
|
14
|
-
it "raise an exception when response is initialized with nil" do
|
15
|
-
assert_raises(ArgumentError) { OneLogin::RubySaml::Logoutresponse.new(nil) }
|
16
|
-
end
|
17
|
-
it "default to empty settings" do
|
18
|
-
assert_nil valid_logout_response_without_settings.settings
|
19
|
-
end
|
20
|
-
it "accept constructor-injected settings" do
|
21
|
-
refute_nil valid_logout_response.settings
|
22
|
-
end
|
23
|
-
it "accept constructor-injected options" do
|
24
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, nil, { :foo => :bar} )
|
25
|
-
assert !logoutresponse.options.empty?
|
26
|
-
end
|
27
|
-
it "support base64 encoded responses" do
|
28
|
-
generated_logout_response = valid_logout_response_document
|
29
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(Base64.encode64(generated_logout_response), settings)
|
30
|
-
assert_equal generated_logout_response, logoutresponse.response
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "#validate_structure" do
|
35
|
-
it "invalidates when the logout response has an invalid xml" do
|
36
|
-
settings.soft = true
|
37
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_logout_response_document, settings)
|
38
|
-
assert !logoutresponse.send(:validate_structure)
|
39
|
-
assert_includes logoutresponse.errors, "Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd"
|
40
|
-
end
|
41
|
-
|
42
|
-
it "raise when the logout response has an invalid xml" do
|
43
|
-
settings.soft = false
|
44
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_logout_response_document, settings)
|
45
|
-
assert_raises OneLogin::RubySaml::ValidationError do
|
46
|
-
logoutresponse.send(:validate_structure)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe "#validate" do
|
52
|
-
describe "when soft=true" do
|
53
|
-
before do
|
54
|
-
settings.soft = true
|
55
|
-
end
|
56
|
-
|
57
|
-
it "validate the logout response" do
|
58
|
-
in_relation_to_request_id = random_id
|
59
|
-
opts = { :matches_request_id => in_relation_to_request_id}
|
60
|
-
|
61
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document({:uuid => in_relation_to_request_id}), settings, opts)
|
62
|
-
|
63
|
-
assert logoutresponse.validate
|
64
|
-
|
65
|
-
assert_equal settings.sp_entity_id, logoutresponse.issuer
|
66
|
-
assert_equal in_relation_to_request_id, logoutresponse.in_response_to
|
67
|
-
|
68
|
-
assert logoutresponse.success?
|
69
|
-
assert_empty logoutresponse.errors
|
70
|
-
end
|
71
|
-
|
72
|
-
it "validate the logout response extended" do
|
73
|
-
in_relation_to_request_id = random_id
|
74
|
-
settings.idp_entity_id = 'http://app.muda.no'
|
75
|
-
opts = { :matches_request_id => in_relation_to_request_id}
|
76
|
-
|
77
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document({:uuid => in_relation_to_request_id}), settings, opts)
|
78
|
-
assert logoutresponse.validate
|
79
|
-
assert_equal in_relation_to_request_id, logoutresponse.in_response_to
|
80
|
-
assert logoutresponse.success?
|
81
|
-
assert_empty logoutresponse.errors
|
82
|
-
end
|
83
|
-
|
84
|
-
it "invalidate logout response when initiated with blank" do
|
85
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new("", settings)
|
86
|
-
assert !logoutresponse.validate
|
87
|
-
assert_includes logoutresponse.errors, "Blank logout response"
|
88
|
-
end
|
89
|
-
|
90
|
-
it "invalidate logout response when initiated with no idp cert or fingerprint" do
|
91
|
-
settings.idp_cert_fingerprint = nil
|
92
|
-
settings.idp_cert = nil
|
93
|
-
settings.idp_cert_multi = nil
|
94
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings)
|
95
|
-
assert !logoutresponse.validate
|
96
|
-
assert_includes logoutresponse.errors, "No fingerprint or certificate on settings of the logout response"
|
97
|
-
end
|
98
|
-
|
99
|
-
it "invalidate logout response with wrong id when given option :matches_request_id" do
|
100
|
-
expected_request_id = "_some_other_expected_uuid"
|
101
|
-
opts = { :matches_request_id => expected_request_id}
|
102
|
-
|
103
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings, opts)
|
104
|
-
|
105
|
-
assert !logoutresponse.validate
|
106
|
-
refute_equal expected_request_id, logoutresponse.in_response_to
|
107
|
-
assert_includes logoutresponse.errors, "The InResponseTo of the Logout Response: #{logoutresponse.in_response_to}, does not match the ID of the Logout Request sent by the SP: #{expected_request_id}"
|
108
|
-
end
|
109
|
-
|
110
|
-
it "invalidate logout response with unexpected request status" do
|
111
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
|
112
|
-
|
113
|
-
assert !logoutresponse.success?
|
114
|
-
assert !logoutresponse.validate
|
115
|
-
assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester"
|
116
|
-
end
|
117
|
-
|
118
|
-
it "invalidate logout response with unexpected request status and status message" do
|
119
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_with_message_document, settings)
|
120
|
-
|
121
|
-
assert !logoutresponse.success?
|
122
|
-
assert !logoutresponse.validate
|
123
|
-
assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester -> Logoutrequest expired"
|
124
|
-
end
|
125
|
-
|
126
|
-
it "invalidate logout response when in lack of sp_entity_id setting" do
|
127
|
-
bad_settings = settings
|
128
|
-
bad_settings.issuer = nil
|
129
|
-
bad_settings.sp_entity_id = nil
|
130
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, bad_settings)
|
131
|
-
assert !logoutresponse.validate
|
132
|
-
assert_includes logoutresponse.errors, "No sp_entity_id in settings of the logout response"
|
133
|
-
end
|
134
|
-
|
135
|
-
it "invalidate logout response with wrong issuer" do
|
136
|
-
in_relation_to_request_id = random_id
|
137
|
-
settings.idp_entity_id = 'http://invalid.issuer.example.com/'
|
138
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document({:uuid => in_relation_to_request_id}), settings)
|
139
|
-
assert !logoutresponse.validate
|
140
|
-
assert_includes logoutresponse.errors, "Doesn't match the issuer, expected: <#{logoutresponse.settings.idp_entity_id}>, but was: <http://app.muda.no>"
|
141
|
-
end
|
142
|
-
|
143
|
-
it "collect errors when collect_errors=true" do
|
144
|
-
settings.idp_entity_id = 'http://invalid.issuer.example.com/'
|
145
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
|
146
|
-
collect_errors = true
|
147
|
-
assert !logoutresponse.validate(collect_errors)
|
148
|
-
assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester"
|
149
|
-
assert_includes logoutresponse.errors, "Doesn't match the issuer, expected: <#{logoutresponse.settings.idp_entity_id}>, but was: <http://app.muda.no>"
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
describe "when soft=false" do
|
155
|
-
before do
|
156
|
-
settings.soft = false
|
157
|
-
end
|
158
|
-
|
159
|
-
it "validates good logout response" do
|
160
|
-
in_relation_to_request_id = random_id
|
161
|
-
|
162
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document({:uuid => in_relation_to_request_id}), settings)
|
163
|
-
assert logoutresponse.validate
|
164
|
-
assert_empty logoutresponse.errors
|
165
|
-
end
|
166
|
-
|
167
|
-
it "raises validation error when response initiated with blank" do
|
168
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new("", settings)
|
169
|
-
|
170
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
171
|
-
assert_includes logoutresponse.errors, "Blank logout response"
|
172
|
-
end
|
173
|
-
|
174
|
-
it "raises validation error when initiated with no idp cert or fingerprint" do
|
175
|
-
settings.idp_cert_fingerprint = nil
|
176
|
-
settings.idp_cert = nil
|
177
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings)
|
178
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
179
|
-
assert_includes logoutresponse.errors, "No fingerprint or certificate on settings of the logout response"
|
180
|
-
end
|
181
|
-
|
182
|
-
it "raises validation error when matching for wrong request id" do
|
183
|
-
|
184
|
-
expected_request_id = "_some_other_expected_id"
|
185
|
-
opts = { :matches_request_id => expected_request_id}
|
186
|
-
|
187
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document, settings, opts)
|
188
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
189
|
-
assert_includes logoutresponse.errors, "The InResponseTo of the Logout Response: #{logoutresponse.in_response_to}, does not match the ID of the Logout Request sent by the SP: #{expected_request_id}"
|
190
|
-
end
|
191
|
-
|
192
|
-
it "raise validation error for wrong request status" do
|
193
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
|
194
|
-
|
195
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
196
|
-
assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester"
|
197
|
-
end
|
198
|
-
|
199
|
-
it "raise validation error when in bad state" do
|
200
|
-
# no settings
|
201
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
|
202
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
203
|
-
assert_includes logoutresponse.errors, "The status code of the Logout Response was not Success, was Requester"
|
204
|
-
end
|
205
|
-
|
206
|
-
it "raise validation error when in lack of sp_entity_id setting" do
|
207
|
-
settings.issuer = nil
|
208
|
-
settings.sp_entity_id = nil
|
209
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_logout_response_document, settings)
|
210
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
211
|
-
assert_includes logoutresponse.errors, "No sp_entity_id in settings of the logout response"
|
212
|
-
end
|
213
|
-
|
214
|
-
it "raise validation error when logout response with wrong issuer" do
|
215
|
-
in_relation_to_request_id = random_id
|
216
|
-
settings.idp_entity_id = 'http://invalid.issuer.example.com/'
|
217
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_logout_response_document({:uuid => in_relation_to_request_id}), settings)
|
218
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate }
|
219
|
-
assert_includes logoutresponse.errors, "Doesn't match the issuer, expected: <#{logoutresponse.settings.idp_entity_id}>, but was: <http://app.muda.no>"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
describe "#validate_signature" do
|
224
|
-
let (:params) { OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, random_id, "Custom Logout Message", :RelayState => 'http://example.com') }
|
225
|
-
|
226
|
-
before do
|
227
|
-
settings.soft = true
|
228
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
229
|
-
settings.security[:logout_responses_signed] = true
|
230
|
-
settings.security[:embed_sign] = false
|
231
|
-
settings.certificate = ruby_saml_cert_text
|
232
|
-
settings.private_key = ruby_saml_key_text
|
233
|
-
settings.idp_cert = ruby_saml_cert_text
|
234
|
-
end
|
235
|
-
|
236
|
-
it "return true when no idp_cert is provided and option :relax_signature_validation is present" do
|
237
|
-
settings.idp_cert = nil
|
238
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
239
|
-
params['RelayState'] = params[:RelayState]
|
240
|
-
options = {}
|
241
|
-
options[:get_params] = params
|
242
|
-
options[:relax_signature_validation] = true
|
243
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
244
|
-
assert logoutresponse_sign_test.send(:validate_signature)
|
245
|
-
end
|
246
|
-
|
247
|
-
it "return false when no idp_cert is provided and no option :relax_signature_validation is present" do
|
248
|
-
settings.idp_cert = nil
|
249
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
250
|
-
params['RelayState'] = params[:RelayState]
|
251
|
-
options = {}
|
252
|
-
options[:get_params] = params
|
253
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
254
|
-
assert !logoutresponse_sign_test.send(:validate_signature)
|
255
|
-
end
|
256
|
-
|
257
|
-
it "return true when valid RSA_SHA1 Signature" do
|
258
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
259
|
-
params['RelayState'] = params[:RelayState]
|
260
|
-
options = {}
|
261
|
-
options[:get_params] = params
|
262
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
263
|
-
assert logoutresponse_sign_test.send(:validate_signature)
|
264
|
-
end
|
265
|
-
|
266
|
-
it "return true when valid RSA_SHA256 Signature" do
|
267
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
268
|
-
params['RelayState'] = params[:RelayState]
|
269
|
-
options = {}
|
270
|
-
options[:get_params] = params
|
271
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
272
|
-
assert logoutresponse.send(:validate_signature)
|
273
|
-
end
|
274
|
-
|
275
|
-
it "return false when invalid RSA_SHA1 Signature" do
|
276
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
277
|
-
params['RelayState'] = 'http://invalid.example.com'
|
278
|
-
options = {}
|
279
|
-
options[:get_params] = params
|
280
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
281
|
-
assert !logoutresponse.send(:validate_signature)
|
282
|
-
end
|
283
|
-
|
284
|
-
it "raise when invalid RSA_SHA1 Signature" do
|
285
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
286
|
-
settings.soft = false
|
287
|
-
params['RelayState'] = 'http://invalid.example.com'
|
288
|
-
options = {}
|
289
|
-
options[:get_params] = params
|
290
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
291
|
-
|
292
|
-
assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.send(:validate_signature) }
|
293
|
-
assert logoutresponse.errors.include? "Invalid Signature on Logout Response"
|
294
|
-
end
|
295
|
-
|
296
|
-
it "raise when get_params encoding differs from what this library generates" do
|
297
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
298
|
-
settings.soft = false
|
299
|
-
options = {}
|
300
|
-
options[:get_params] = params
|
301
|
-
options[:get_params]['RelayState'] = 'http://example.com'
|
302
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
303
|
-
# Assemble query string.
|
304
|
-
query = OneLogin::RubySaml::Utils.build_query(
|
305
|
-
:type => 'SAMLResponse',
|
306
|
-
:data => params['SAMLResponse'],
|
307
|
-
:relay_state => params['RelayState'],
|
308
|
-
:sig_alg => params['SigAlg']
|
309
|
-
)
|
310
|
-
# Modify the query string so that it encodes the same values,
|
311
|
-
# but with different percent-encoding. Sanity-check that they
|
312
|
-
# really are equialent before moving on.
|
313
|
-
original_query = query.dup
|
314
|
-
query.gsub!("example", "ex%61mple")
|
315
|
-
refute_equal(query, original_query)
|
316
|
-
assert_equal(CGI.unescape(query), CGI.unescape(original_query))
|
317
|
-
# Make normalised signature based on our modified params.
|
318
|
-
sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
|
319
|
-
signature = settings.get_sp_key.sign(sign_algorithm.new, query)
|
320
|
-
params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
|
321
|
-
# Re-create the Logoutresponse based on these modified parameters,
|
322
|
-
# and ask it to validate the signature. It will do it incorrectly,
|
323
|
-
# because it will compute it based on re-encoded query parameters,
|
324
|
-
# rather than their original encodings.
|
325
|
-
options[:get_params] = params
|
326
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
327
|
-
assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
|
328
|
-
logoutresponse.send(:validate_signature)
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
it "return true even if raw_get_params encoding differs from what this library generates" do
|
333
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
334
|
-
settings.soft = false
|
335
|
-
options = {}
|
336
|
-
options[:get_params] = params
|
337
|
-
options[:get_params]['RelayState'] = 'http://example.com'
|
338
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
339
|
-
# Assemble query string.
|
340
|
-
query = OneLogin::RubySaml::Utils.build_query(
|
341
|
-
:type => 'SAMLResponse',
|
342
|
-
:data => params['SAMLResponse'],
|
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
|
-
# Re-create the Logoutresponse based on these modified parameters,
|
358
|
-
# and ask it to validate the signature. Provide the altered parameter
|
359
|
-
# in its raw URI-encoded form, so that we don't have to guess the value
|
360
|
-
# that contributed to the signature.
|
361
|
-
options[:get_params] = params
|
362
|
-
options[:get_params].delete("RelayState")
|
363
|
-
options[:raw_get_params] = {
|
364
|
-
"RelayState" => "http%3A%2F%2Fex%61mple.com",
|
365
|
-
}
|
366
|
-
logoutresponse = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
367
|
-
assert logoutresponse.send(:validate_signature)
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
describe "#validate_signature" do
|
372
|
-
let (:params) { OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, random_id, "Custom Logout Message", :RelayState => 'http://example.com') }
|
373
|
-
|
374
|
-
before do
|
375
|
-
settings.soft = true
|
376
|
-
settings.idp_slo_target_url = "http://example.com?field=value"
|
377
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
378
|
-
settings.security[:logout_responses_signed] = true
|
379
|
-
settings.security[:embed_sign] = false
|
380
|
-
settings.certificate = ruby_saml_cert_text
|
381
|
-
settings.private_key = ruby_saml_key_text
|
382
|
-
settings.idp_cert = nil
|
383
|
-
end
|
384
|
-
|
385
|
-
it "return true when at least a idp_cert is valid" do
|
386
|
-
params['RelayState'] = params[:RelayState]
|
387
|
-
options = {}
|
388
|
-
options[:get_params] = params
|
389
|
-
settings.idp_cert_multi = {
|
390
|
-
:signing => [ruby_saml_cert_text2, ruby_saml_cert_text],
|
391
|
-
:encryption => []
|
392
|
-
}
|
393
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
394
|
-
assert logoutresponse_sign_test.send(:validate_signature)
|
395
|
-
end
|
396
|
-
|
397
|
-
it "return false when cert expired and check_idp_cert_expiration expired" do
|
398
|
-
params['RelayState'] = params[:RelayState]
|
399
|
-
options = {}
|
400
|
-
options[:get_params] = params
|
401
|
-
settings.security[:check_idp_cert_expiration] = true
|
402
|
-
settings.idp_cert = nil
|
403
|
-
settings.idp_cert_multi = {
|
404
|
-
:signing => [ruby_saml_cert_text],
|
405
|
-
:encryption => []
|
406
|
-
}
|
407
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
408
|
-
assert !logoutresponse_sign_test.send(:validate_signature)
|
409
|
-
assert_includes logoutresponse_sign_test.errors, "IdP x509 certificate expired"
|
410
|
-
end
|
411
|
-
|
412
|
-
it "return false when none cert on idp_cert_multi is valid" do
|
413
|
-
params['RelayState'] = params[:RelayState]
|
414
|
-
options = {}
|
415
|
-
options[:get_params] = params
|
416
|
-
settings.idp_cert_multi = {
|
417
|
-
:signing => [ruby_saml_cert_text2, ruby_saml_cert_text2],
|
418
|
-
:encryption => []
|
419
|
-
}
|
420
|
-
logoutresponse_sign_test = OneLogin::RubySaml::Logoutresponse.new(params['SAMLResponse'], settings, options)
|
421
|
-
assert !logoutresponse_sign_test.send(:validate_signature)
|
422
|
-
assert_includes logoutresponse_sign_test.errors, "Invalid Signature on Logout Response"
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
end
|
427
|
-
end
|