ruby-saml 1.11.0 → 1.14.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.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +25 -0
- data/{changelog.md → CHANGELOG.md} +49 -1
- data/README.md +363 -218
- data/UPGRADING.md +149 -0
- data/lib/onelogin/ruby-saml/attributes.rb +24 -1
- data/lib/onelogin/ruby-saml/authrequest.rb +12 -8
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +154 -83
- data/lib/onelogin/ruby-saml/logoutrequest.rb +13 -7
- data/lib/onelogin/ruby-saml/logoutresponse.rb +6 -2
- data/lib/onelogin/ruby-saml/metadata.rb +62 -17
- data/lib/onelogin/ruby-saml/response.rb +57 -32
- data/lib/onelogin/ruby-saml/saml_message.rb +8 -3
- data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
- data/lib/onelogin/ruby-saml/settings.rb +92 -50
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +17 -30
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +32 -18
- data/lib/onelogin/ruby-saml/utils.rb +83 -8
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +39 -13
- data/ruby-saml.gemspec +14 -5
- metadata +29 -288
- data/.travis.yml +0 -46
- 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
|
@@ -11,14 +11,18 @@ module OneLogin
|
|
|
11
11
|
|
|
12
12
|
# Auxiliary class to retrieve and parse the Identity Provider Metadata
|
|
13
13
|
#
|
|
14
|
+
# This class does not validate in any way the URL that is introduced,
|
|
15
|
+
# make sure to validate it properly before use it in a parse_remote method.
|
|
16
|
+
# Read the `Security warning` section of the README.md file to get more info
|
|
17
|
+
#
|
|
14
18
|
class IdpMetadataParser
|
|
15
19
|
|
|
16
20
|
module SamlMetadata
|
|
17
21
|
module Vocabulary
|
|
18
|
-
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
|
|
19
|
-
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
|
20
|
-
NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:*"
|
|
21
|
-
SAML_ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
|
|
22
|
+
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata".freeze
|
|
23
|
+
DSIG = "http://www.w3.org/2000/09/xmldsig#".freeze
|
|
24
|
+
NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:*".freeze
|
|
25
|
+
SAML_ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion".freeze
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
NAMESPACE = {
|
|
@@ -26,7 +30,7 @@ module OneLogin
|
|
|
26
30
|
"NameFormat" => Vocabulary::NAME_FORMAT,
|
|
27
31
|
"saml" => Vocabulary::SAML_ASSERTION,
|
|
28
32
|
"ds" => Vocabulary::DSIG
|
|
29
|
-
}
|
|
33
|
+
}.freeze
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
include SamlMetadata::Vocabulary
|
|
@@ -34,6 +38,16 @@ module OneLogin
|
|
|
34
38
|
attr_reader :response
|
|
35
39
|
attr_reader :options
|
|
36
40
|
|
|
41
|
+
# fetch IdP descriptors from a metadata document
|
|
42
|
+
def self.get_idps(metadata_document, only_entity_id=nil)
|
|
43
|
+
path = "//md:EntityDescriptor#{only_entity_id && '[@entityID="' + only_entity_id + '"]'}/md:IDPSSODescriptor"
|
|
44
|
+
REXML::XPath.match(
|
|
45
|
+
metadata_document,
|
|
46
|
+
path,
|
|
47
|
+
SamlMetadata::NAMESPACE
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
37
51
|
# Parse the Identity Provider metadata and update the settings with the
|
|
38
52
|
# IdP values
|
|
39
53
|
#
|
|
@@ -42,9 +56,10 @@ module OneLogin
|
|
|
42
56
|
#
|
|
43
57
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
|
44
58
|
# @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings object which gets the parsed metadata merged into or an hash for Settings overrides.
|
|
45
|
-
# @option options [
|
|
46
|
-
# @option options [Array<String>, nil] :
|
|
47
|
-
# @option options [String, nil] :
|
|
59
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
|
60
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
61
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
62
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
48
63
|
#
|
|
49
64
|
# @return [OneLogin::RubySaml::Settings]
|
|
50
65
|
#
|
|
@@ -60,9 +75,10 @@ module OneLogin
|
|
|
60
75
|
# @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
|
|
61
76
|
#
|
|
62
77
|
# @param options [Hash] options used for parsing the metadata
|
|
63
|
-
# @option options [
|
|
64
|
-
# @option options [Array<String>, nil] :
|
|
65
|
-
# @option options [String, nil] :
|
|
78
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
|
79
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
80
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
81
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
66
82
|
#
|
|
67
83
|
# @return [Hash]
|
|
68
84
|
#
|
|
@@ -77,9 +93,10 @@ module OneLogin
|
|
|
77
93
|
# @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
|
|
78
94
|
#
|
|
79
95
|
# @param options [Hash] options used for parsing the metadata
|
|
80
|
-
# @option options [
|
|
81
|
-
# @option options [Array<String>, nil] :
|
|
82
|
-
# @option options [String, nil] :
|
|
96
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned.
|
|
97
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
98
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
99
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
83
100
|
#
|
|
84
101
|
# @return [Array<Hash>]
|
|
85
102
|
#
|
|
@@ -95,14 +112,27 @@ module OneLogin
|
|
|
95
112
|
#
|
|
96
113
|
# @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object or an hash for Settings overrides
|
|
97
114
|
# @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings object which gets the parsed metadata merged into or an hash for Settings overrides.
|
|
98
|
-
# @option options [
|
|
99
|
-
# @option options [Array<String>, nil] :
|
|
100
|
-
# @option options [String, nil] :
|
|
115
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
|
116
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
117
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
118
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
101
119
|
#
|
|
102
120
|
# @return [OneLogin::RubySaml::Settings]
|
|
103
121
|
def parse(idp_metadata, options = {})
|
|
104
122
|
parsed_metadata = parse_to_hash(idp_metadata, options)
|
|
105
123
|
|
|
124
|
+
unless parsed_metadata[:cache_duration].nil?
|
|
125
|
+
cache_valid_until_timestamp = OneLogin::RubySaml::Utils.parse_duration(parsed_metadata[:cache_duration])
|
|
126
|
+
unless cache_valid_until_timestamp.nil?
|
|
127
|
+
if parsed_metadata[:valid_until].nil? || cache_valid_until_timestamp < Time.parse(parsed_metadata[:valid_until], Time.now.utc).to_i
|
|
128
|
+
parsed_metadata[:valid_until] = Time.at(cache_valid_until_timestamp).utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
# Remove the cache_duration because on the settings
|
|
133
|
+
# we only gonna suppot valid_until
|
|
134
|
+
parsed_metadata.delete(:cache_duration)
|
|
135
|
+
|
|
106
136
|
settings = options[:settings]
|
|
107
137
|
|
|
108
138
|
if settings.nil?
|
|
@@ -119,9 +149,10 @@ module OneLogin
|
|
|
119
149
|
# @param idp_metadata [String]
|
|
120
150
|
#
|
|
121
151
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
|
122
|
-
# @option options [
|
|
123
|
-
# @option options [Array<String>, nil] :
|
|
124
|
-
# @option options [String, nil] :
|
|
152
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
|
153
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
154
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
155
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
125
156
|
#
|
|
126
157
|
# @return [Hash]
|
|
127
158
|
def parse_to_hash(idp_metadata, options = {})
|
|
@@ -133,21 +164,26 @@ module OneLogin
|
|
|
133
164
|
# @param idp_metadata [String]
|
|
134
165
|
#
|
|
135
166
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
|
136
|
-
# @option options [
|
|
137
|
-
# @option options [Array<String>, nil] :
|
|
138
|
-
# @option options [String, nil] :
|
|
167
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned.
|
|
168
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
|
169
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
|
170
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
|
139
171
|
#
|
|
140
172
|
# @return [Array<Hash>]
|
|
141
173
|
def parse_to_array(idp_metadata, options = {})
|
|
174
|
+
parse_to_idp_metadata_array(idp_metadata, options).map { |idp_md| idp_md.to_hash(options) }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def parse_to_idp_metadata_array(idp_metadata, options = {})
|
|
142
178
|
@document = REXML::Document.new(idp_metadata)
|
|
143
179
|
@options = options
|
|
144
180
|
|
|
145
|
-
idpsso_descriptors =
|
|
181
|
+
idpsso_descriptors = self.class.get_idps(@document, options[:entity_id])
|
|
146
182
|
if !idpsso_descriptors.any?
|
|
147
183
|
raise ArgumentError.new("idp_metadata must contain an IDPSSODescriptor element")
|
|
148
184
|
end
|
|
149
185
|
|
|
150
|
-
|
|
186
|
+
idpsso_descriptors.map {|id| IdpMetadata.new(id, id.parent.attributes["entityID"])}
|
|
151
187
|
end
|
|
152
188
|
|
|
153
189
|
private
|
|
@@ -175,6 +211,7 @@ module OneLogin
|
|
|
175
211
|
end
|
|
176
212
|
|
|
177
213
|
get = Net::HTTP::Get.new(uri.request_uri)
|
|
214
|
+
get.basic_auth uri.user, uri.password if uri.user
|
|
178
215
|
@response = http.request(get)
|
|
179
216
|
return response.body if response.is_a? Net::HTTPSuccess
|
|
180
217
|
|
|
@@ -184,14 +221,7 @@ module OneLogin
|
|
|
184
221
|
end
|
|
185
222
|
|
|
186
223
|
class IdpMetadata
|
|
187
|
-
|
|
188
|
-
path = "//md:EntityDescriptor#{only_entity_id && '[@entityID="' + only_entity_id + '"]'}/md:IDPSSODescriptor"
|
|
189
|
-
REXML::XPath.match(
|
|
190
|
-
metadata_document,
|
|
191
|
-
path,
|
|
192
|
-
SamlMetadata::NAMESPACE
|
|
193
|
-
)
|
|
194
|
-
end
|
|
224
|
+
attr_reader :idpsso_descriptor, :entity_id
|
|
195
225
|
|
|
196
226
|
def initialize(idpsso_descriptor, entity_id)
|
|
197
227
|
@idpsso_descriptor = idpsso_descriptor
|
|
@@ -199,32 +229,27 @@ module OneLogin
|
|
|
199
229
|
end
|
|
200
230
|
|
|
201
231
|
def to_hash(options = {})
|
|
232
|
+
sso_binding = options[:sso_binding]
|
|
233
|
+
slo_binding = options[:slo_binding]
|
|
202
234
|
{
|
|
203
235
|
:idp_entity_id => @entity_id,
|
|
204
|
-
:name_identifier_format => idp_name_id_format,
|
|
205
|
-
:
|
|
206
|
-
:
|
|
236
|
+
:name_identifier_format => idp_name_id_format(options[:name_id_format]),
|
|
237
|
+
:idp_sso_service_url => single_signon_service_url(sso_binding),
|
|
238
|
+
:idp_sso_service_binding => single_signon_service_binding(sso_binding),
|
|
239
|
+
:idp_slo_service_url => single_logout_service_url(slo_binding),
|
|
240
|
+
:idp_slo_service_binding => single_logout_service_binding(slo_binding),
|
|
241
|
+
:idp_slo_response_service_url => single_logout_response_service_url(slo_binding),
|
|
207
242
|
:idp_attribute_names => attribute_names,
|
|
208
243
|
:idp_cert => nil,
|
|
209
244
|
:idp_cert_fingerprint => nil,
|
|
210
245
|
:idp_cert_multi => nil,
|
|
211
|
-
:valid_until => valid_until
|
|
246
|
+
:valid_until => valid_until,
|
|
247
|
+
:cache_duration => cache_duration,
|
|
212
248
|
}.tap do |response_hash|
|
|
213
249
|
merge_certificates_into(response_hash) unless certificates.nil?
|
|
214
250
|
end
|
|
215
251
|
end
|
|
216
252
|
|
|
217
|
-
# @return [String|nil] IdP Name ID Format value if exists
|
|
218
|
-
#
|
|
219
|
-
def idp_name_id_format
|
|
220
|
-
node = REXML::XPath.first(
|
|
221
|
-
@idpsso_descriptor,
|
|
222
|
-
"md:NameIDFormat",
|
|
223
|
-
SamlMetadata::NAMESPACE
|
|
224
|
-
)
|
|
225
|
-
Utils.element_text(node)
|
|
226
|
-
end
|
|
227
|
-
|
|
228
253
|
# @return [String|nil] 'validUntil' attribute of metadata
|
|
229
254
|
#
|
|
230
255
|
def valid_until
|
|
@@ -232,7 +257,26 @@ module OneLogin
|
|
|
232
257
|
root.attributes['validUntil'] if root && root.attributes
|
|
233
258
|
end
|
|
234
259
|
|
|
235
|
-
# @
|
|
260
|
+
# @return [String|nil] 'cacheDuration' attribute of metadata
|
|
261
|
+
#
|
|
262
|
+
def cache_duration
|
|
263
|
+
root = @idpsso_descriptor.root
|
|
264
|
+
root.attributes['cacheDuration'] if root && root.attributes
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# @param name_id_priority [String|Array<String>] The prioritized list of NameIDFormat values to select. Will select first value if nil.
|
|
268
|
+
# @return [String|nil] IdP NameIDFormat value if exists
|
|
269
|
+
#
|
|
270
|
+
def idp_name_id_format(name_id_priority = nil)
|
|
271
|
+
nodes = REXML::XPath.match(
|
|
272
|
+
@idpsso_descriptor,
|
|
273
|
+
"md:NameIDFormat",
|
|
274
|
+
SamlMetadata::NAMESPACE
|
|
275
|
+
)
|
|
276
|
+
first_ranked_text(nodes, name_id_priority)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
|
236
280
|
# @return [String|nil] SingleSignOnService binding if exists
|
|
237
281
|
#
|
|
238
282
|
def single_signon_service_binding(binding_priority = nil)
|
|
@@ -241,19 +285,26 @@ module OneLogin
|
|
|
241
285
|
"md:SingleSignOnService/@Binding",
|
|
242
286
|
SamlMetadata::NAMESPACE
|
|
243
287
|
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
288
|
+
first_ranked_value(nodes, binding_priority)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
|
292
|
+
# @return [String|nil] SingleLogoutService binding if exists
|
|
293
|
+
#
|
|
294
|
+
def single_logout_service_binding(binding_priority = nil)
|
|
295
|
+
nodes = REXML::XPath.match(
|
|
296
|
+
@idpsso_descriptor,
|
|
297
|
+
"md:SingleLogoutService/@Binding",
|
|
298
|
+
SamlMetadata::NAMESPACE
|
|
299
|
+
)
|
|
300
|
+
first_ranked_value(nodes, binding_priority)
|
|
250
301
|
end
|
|
251
302
|
|
|
252
|
-
# @param
|
|
303
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
|
253
304
|
# @return [String|nil] SingleSignOnService endpoint if exists
|
|
254
305
|
#
|
|
255
|
-
def single_signon_service_url(
|
|
256
|
-
binding = single_signon_service_binding(
|
|
306
|
+
def single_signon_service_url(binding_priority = nil)
|
|
307
|
+
binding = single_signon_service_binding(binding_priority)
|
|
257
308
|
return if binding.nil?
|
|
258
309
|
|
|
259
310
|
node = REXML::XPath.first(
|
|
@@ -261,39 +312,37 @@ module OneLogin
|
|
|
261
312
|
"md:SingleSignOnService[@Binding=\"#{binding}\"]/@Location",
|
|
262
313
|
SamlMetadata::NAMESPACE
|
|
263
314
|
)
|
|
264
|
-
|
|
315
|
+
node.value if node
|
|
265
316
|
end
|
|
266
317
|
|
|
267
|
-
# @param binding_priority [Array]
|
|
268
|
-
# @return [String|nil] SingleLogoutService
|
|
318
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
|
319
|
+
# @return [String|nil] SingleLogoutService endpoint if exists
|
|
269
320
|
#
|
|
270
|
-
def
|
|
271
|
-
|
|
321
|
+
def single_logout_service_url(binding_priority = nil)
|
|
322
|
+
binding = single_logout_service_binding(binding_priority)
|
|
323
|
+
return if binding.nil?
|
|
324
|
+
|
|
325
|
+
node = REXML::XPath.first(
|
|
272
326
|
@idpsso_descriptor,
|
|
273
|
-
"md:SingleLogoutService
|
|
327
|
+
"md:SingleLogoutService[@Binding=\"#{binding}\"]/@Location",
|
|
274
328
|
SamlMetadata::NAMESPACE
|
|
275
329
|
)
|
|
276
|
-
if
|
|
277
|
-
values = nodes.map(&:value)
|
|
278
|
-
binding_priority.detect{ |binding| values.include? binding }
|
|
279
|
-
else
|
|
280
|
-
nodes.first.value if nodes.any?
|
|
281
|
-
end
|
|
330
|
+
node.value if node
|
|
282
331
|
end
|
|
283
332
|
|
|
284
|
-
# @param
|
|
285
|
-
# @return [String|nil] SingleLogoutService
|
|
333
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
|
334
|
+
# @return [String|nil] SingleLogoutService response url if exists
|
|
286
335
|
#
|
|
287
|
-
def
|
|
288
|
-
binding = single_logout_service_binding(
|
|
336
|
+
def single_logout_response_service_url(binding_priority = nil)
|
|
337
|
+
binding = single_logout_service_binding(binding_priority)
|
|
289
338
|
return if binding.nil?
|
|
290
339
|
|
|
291
340
|
node = REXML::XPath.first(
|
|
292
341
|
@idpsso_descriptor,
|
|
293
|
-
"md:SingleLogoutService[@Binding=\"#{binding}\"]/@
|
|
342
|
+
"md:SingleLogoutService[@Binding=\"#{binding}\"]/@ResponseLocation",
|
|
294
343
|
SamlMetadata::NAMESPACE
|
|
295
344
|
)
|
|
296
|
-
|
|
345
|
+
node.value if node
|
|
297
346
|
end
|
|
298
347
|
|
|
299
348
|
# @return [String|nil] Unformatted Certificate if exists
|
|
@@ -375,15 +424,41 @@ module OneLogin
|
|
|
375
424
|
parsed_metadata[:idp_cert_fingerprint_algorithm]
|
|
376
425
|
)
|
|
377
426
|
end
|
|
378
|
-
else
|
|
379
|
-
# symbolize keys of certificates and pass it on
|
|
380
|
-
parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }]
|
|
381
427
|
end
|
|
428
|
+
|
|
429
|
+
# symbolize keys of certificates and pass it on
|
|
430
|
+
parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }]
|
|
382
431
|
end
|
|
383
432
|
|
|
384
433
|
def certificates_has_one(key)
|
|
385
434
|
certificates.key?(key) && certificates[key].size == 1
|
|
386
435
|
end
|
|
436
|
+
|
|
437
|
+
private
|
|
438
|
+
|
|
439
|
+
def first_ranked_text(nodes, priority = nil)
|
|
440
|
+
return unless nodes.any?
|
|
441
|
+
|
|
442
|
+
priority = Array(priority)
|
|
443
|
+
if priority.any?
|
|
444
|
+
values = nodes.map(&:text)
|
|
445
|
+
priority.detect { |candidate| values.include?(candidate) }
|
|
446
|
+
else
|
|
447
|
+
nodes.first.text
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def first_ranked_value(nodes, priority = nil)
|
|
452
|
+
return unless nodes.any?
|
|
453
|
+
|
|
454
|
+
priority = Array(priority)
|
|
455
|
+
if priority.any?
|
|
456
|
+
values = nodes.map(&:value)
|
|
457
|
+
priority.detect { |candidate| values.include?(candidate) }
|
|
458
|
+
else
|
|
459
|
+
nodes.first.value
|
|
460
|
+
end
|
|
461
|
+
end
|
|
387
462
|
end
|
|
388
463
|
|
|
389
464
|
def merge_parsed_metadata_into(settings, parsed_metadata)
|
|
@@ -393,10 +468,6 @@ module OneLogin
|
|
|
393
468
|
|
|
394
469
|
settings
|
|
395
470
|
end
|
|
396
|
-
|
|
397
|
-
if self.respond_to?(:private_constant)
|
|
398
|
-
private_constant :SamlMetadata, :IdpMetadata
|
|
399
|
-
end
|
|
400
471
|
end
|
|
401
472
|
end
|
|
402
473
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "onelogin/ruby-saml/logging"
|
|
2
2
|
require "onelogin/ruby-saml/saml_message"
|
|
3
3
|
require "onelogin/ruby-saml/utils"
|
|
4
|
+
require "onelogin/ruby-saml/setting_error"
|
|
4
5
|
|
|
5
6
|
# Only supports SAML 2.0
|
|
6
7
|
module OneLogin
|
|
@@ -11,7 +12,7 @@ module OneLogin
|
|
|
11
12
|
class Logoutrequest < SamlMessage
|
|
12
13
|
|
|
13
14
|
# Logout Request ID
|
|
14
|
-
|
|
15
|
+
attr_accessor :uuid
|
|
15
16
|
|
|
16
17
|
# Initializes the Logout Request. A Logoutrequest Object that is an extension of the SamlMessage class.
|
|
17
18
|
# Asigns an ID, a random uuid.
|
|
@@ -20,6 +21,10 @@ module OneLogin
|
|
|
20
21
|
@uuid = OneLogin::RubySaml::Utils.uuid
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
def request_id
|
|
25
|
+
@uuid
|
|
26
|
+
end
|
|
27
|
+
|
|
23
28
|
# Creates the Logout Request string.
|
|
24
29
|
# @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
|
|
25
30
|
# @param params [Hash] Some extra parameters to be added in the GET for example the RelayState
|
|
@@ -27,13 +32,14 @@ module OneLogin
|
|
|
27
32
|
#
|
|
28
33
|
def create(settings, params={})
|
|
29
34
|
params = create_params(settings, params)
|
|
30
|
-
params_prefix = (settings.
|
|
35
|
+
params_prefix = (settings.idp_slo_service_url =~ /\?/) ? '&' : '?'
|
|
31
36
|
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
|
32
37
|
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
|
33
38
|
params.each_pair do |key, value|
|
|
34
39
|
request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
|
35
40
|
end
|
|
36
|
-
|
|
41
|
+
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if settings.idp_slo_service_url.nil? or settings.idp_slo_service_url.empty?
|
|
42
|
+
@logout_url = settings.idp_slo_service_url + request_params
|
|
37
43
|
end
|
|
38
44
|
|
|
39
45
|
# Creates the Get parameters for the logout request.
|
|
@@ -64,8 +70,8 @@ module OneLogin
|
|
|
64
70
|
base64_request = encode(request)
|
|
65
71
|
request_params = {"SAMLRequest" => base64_request}
|
|
66
72
|
|
|
67
|
-
if settings.
|
|
68
|
-
params['SigAlg']
|
|
73
|
+
if settings.idp_slo_service_binding == Utils::BINDINGS[:redirect] && settings.security[:logout_requests_signed] && settings.private_key
|
|
74
|
+
params['SigAlg'] = settings.security[:signature_method]
|
|
69
75
|
url_string = OneLogin::RubySaml::Utils.build_query(
|
|
70
76
|
:type => 'SAMLRequest',
|
|
71
77
|
:data => base64_request,
|
|
@@ -103,7 +109,7 @@ module OneLogin
|
|
|
103
109
|
root.attributes['ID'] = uuid
|
|
104
110
|
root.attributes['IssueInstant'] = time
|
|
105
111
|
root.attributes['Version'] = "2.0"
|
|
106
|
-
root.attributes['Destination'] = settings.
|
|
112
|
+
root.attributes['Destination'] = settings.idp_slo_service_url unless settings.idp_slo_service_url.nil? or settings.idp_slo_service_url.empty?
|
|
107
113
|
|
|
108
114
|
if settings.sp_entity_id
|
|
109
115
|
issuer = root.add_element "saml:Issuer"
|
|
@@ -132,7 +138,7 @@ module OneLogin
|
|
|
132
138
|
|
|
133
139
|
def sign_document(document, settings)
|
|
134
140
|
# embed signature
|
|
135
|
-
if settings.
|
|
141
|
+
if settings.idp_slo_service_binding == Utils::BINDINGS[:post] && settings.security[:logout_requests_signed] && settings.private_key && settings.certificate
|
|
136
142
|
private_key = settings.get_sp_key
|
|
137
143
|
cert = settings.get_sp_cert
|
|
138
144
|
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
|
|
@@ -43,10 +43,14 @@ module OneLogin
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
@options = options
|
|
46
|
-
@response = decode_raw_saml(response)
|
|
46
|
+
@response = decode_raw_saml(response, settings)
|
|
47
47
|
@document = XMLSecurity::SignedDocument.new(@response)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
def response_id
|
|
51
|
+
id(document)
|
|
52
|
+
end
|
|
53
|
+
|
|
50
54
|
# Checks if the Status has the "Success" code
|
|
51
55
|
# @return [Boolean] True if the StatusCode is Sucess
|
|
52
56
|
# @raise [ValidationError] if soft == false and validation fails
|
|
@@ -208,7 +212,7 @@ module OneLogin
|
|
|
208
212
|
return true unless options.has_key? :get_params
|
|
209
213
|
return true unless options[:get_params].has_key? 'Signature'
|
|
210
214
|
|
|
211
|
-
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params])
|
|
215
|
+
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params], settings.security[:lowercase_url_encoding])
|
|
212
216
|
|
|
213
217
|
if options[:get_params]['SigAlg'].nil? && !options[:raw_get_params]['SigAlg'].nil?
|
|
214
218
|
options[:get_params]['SigAlg'] = CGI.unescape(options[:raw_get_params]['SigAlg'])
|
|
@@ -15,25 +15,56 @@ module OneLogin
|
|
|
15
15
|
# @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
|
|
16
16
|
# @param pretty_print [Boolean] Pretty print or not the response
|
|
17
17
|
# (No pretty print if you gonna validate the signature)
|
|
18
|
+
# @param valid_until [DateTime] Metadata's valid time
|
|
19
|
+
# @param cache_duration [Integer] Duration of the cache in seconds
|
|
18
20
|
# @return [String] XML Metadata of the Service Provider
|
|
19
21
|
#
|
|
20
|
-
def generate(settings, pretty_print=false)
|
|
22
|
+
def generate(settings, pretty_print=false, valid_until=nil, cache_duration=nil)
|
|
21
23
|
meta_doc = XMLSecurity::Document.new
|
|
24
|
+
add_xml_declaration(meta_doc)
|
|
25
|
+
root = add_root_element(meta_doc, settings, valid_until, cache_duration)
|
|
26
|
+
sp_sso = add_sp_sso_element(root, settings)
|
|
27
|
+
add_sp_certificates(sp_sso, settings)
|
|
28
|
+
add_sp_service_elements(sp_sso, settings)
|
|
29
|
+
add_extras(root, settings)
|
|
30
|
+
embed_signature(meta_doc, settings)
|
|
31
|
+
output_xml(meta_doc, pretty_print)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def add_xml_declaration(meta_doc)
|
|
37
|
+
meta_doc << REXML::XMLDecl.new('1.0', 'UTF-8')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_root_element(meta_doc, settings, valid_until, cache_duration)
|
|
22
41
|
namespaces = {
|
|
23
42
|
"xmlns:md" => "urn:oasis:names:tc:SAML:2.0:metadata"
|
|
24
43
|
}
|
|
44
|
+
|
|
25
45
|
if settings.attribute_consuming_service.configured?
|
|
26
46
|
namespaces["xmlns:saml"] = "urn:oasis:names:tc:SAML:2.0:assertion"
|
|
27
47
|
end
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
|
|
49
|
+
root = meta_doc.add_element("md:EntityDescriptor", namespaces)
|
|
50
|
+
root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
|
|
51
|
+
root.attributes["entityID"] = settings.sp_entity_id if settings.sp_entity_id
|
|
52
|
+
root.attributes["validUntil"] = valid_until.strftime('%Y-%m-%dT%H:%M:%S%z') if valid_until
|
|
53
|
+
root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S" if cache_duration
|
|
54
|
+
root
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def add_sp_sso_element(root, settings)
|
|
58
|
+
root.add_element "md:SPSSODescriptor", {
|
|
30
59
|
"protocolSupportEnumeration" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
31
60
|
"AuthnRequestsSigned" => settings.security[:authn_requests_signed],
|
|
32
61
|
"WantAssertionsSigned" => settings.security[:want_assertions_signed],
|
|
33
62
|
}
|
|
63
|
+
end
|
|
34
64
|
|
|
35
|
-
|
|
36
|
-
|
|
65
|
+
# Add KeyDescriptor if messages will be signed / encrypted
|
|
66
|
+
# with SP certificate, and new SP certificate if any
|
|
67
|
+
def add_sp_certificates(sp_sso, settings)
|
|
37
68
|
cert = settings.get_sp_cert
|
|
38
69
|
cert_new = settings.get_sp_cert_new
|
|
39
70
|
|
|
@@ -56,10 +87,10 @@ module OneLogin
|
|
|
56
87
|
end
|
|
57
88
|
end
|
|
58
89
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
sp_sso
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def add_sp_service_elements(sp_sso, settings)
|
|
63
94
|
if settings.single_logout_service_url
|
|
64
95
|
sp_sso.add_element "md:SingleLogoutService", {
|
|
65
96
|
"Binding" => settings.single_logout_service_binding,
|
|
@@ -67,10 +98,12 @@ module OneLogin
|
|
|
67
98
|
"ResponseLocation" => settings.single_logout_service_url
|
|
68
99
|
}
|
|
69
100
|
end
|
|
101
|
+
|
|
70
102
|
if settings.name_identifier_format
|
|
71
103
|
nameid = sp_sso.add_element "md:NameIDFormat"
|
|
72
104
|
nameid.text = settings.name_identifier_format
|
|
73
105
|
end
|
|
106
|
+
|
|
74
107
|
if settings.assertion_consumer_service_url
|
|
75
108
|
sp_sso.add_element "md:AssertionConsumerService", {
|
|
76
109
|
"Binding" => settings.assertion_consumer_service_binding,
|
|
@@ -109,15 +142,27 @@ module OneLogin
|
|
|
109
142
|
# <md:RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:query="urn:oasis:names:tc:SAML:metadata:ext:query" xsi:type="query:AttributeQueryDescriptorType" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
|
|
110
143
|
# <md:XACMLAuthzDecisionQueryDescriptor WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
|
|
111
144
|
|
|
112
|
-
|
|
145
|
+
sp_sso
|
|
146
|
+
end
|
|
113
147
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
148
|
+
# can be overridden in subclass
|
|
149
|
+
def add_extras(root, _settings)
|
|
150
|
+
root
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def embed_signature(meta_doc, settings)
|
|
154
|
+
return unless settings.security[:metadata_signed]
|
|
155
|
+
|
|
156
|
+
private_key = settings.get_sp_key
|
|
157
|
+
cert = settings.get_sp_cert
|
|
158
|
+
return unless private_key && cert
|
|
159
|
+
|
|
160
|
+
meta_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def output_xml(meta_doc, pretty_print)
|
|
164
|
+
ret = ''
|
|
119
165
|
|
|
120
|
-
ret = ""
|
|
121
166
|
# pretty print the XML so IdP administrators can easily see what the SP supports
|
|
122
167
|
if pretty_print
|
|
123
168
|
meta_doc.write(ret, 1)
|
|
@@ -125,7 +170,7 @@ module OneLogin
|
|
|
125
170
|
ret = meta_doc.to_s
|
|
126
171
|
end
|
|
127
172
|
|
|
128
|
-
|
|
173
|
+
ret
|
|
129
174
|
end
|
|
130
175
|
end
|
|
131
176
|
end
|