Skip to content

Commit 3911625

Browse files
committed
Merge branch 'idp_metadata_parse_binding' of https://github.com/flant/ruby-saml into flant-idp_metadata_parse_binding
2 parents b7061b7 + 2ff9d8e commit 3911625

1 file changed

Lines changed: 56 additions & 13 deletions

File tree

lib/onelogin/ruby-saml/idp_metadata_parser.rb

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,30 @@ class IdpMetadataParser
2828
# IdP values
2929
#
3030
# @param (see IdpMetadataParser#get_idp_metadata)
31+
# @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object
3132
# @return (see IdpMetadataParser#get_idp_metadata)
3233
# @raise (see IdpMetadataParser#get_idp_metadata)
33-
def parse_remote(url, validate_cert = true)
34+
def parse_remote(url, validate_cert = true, options = {})
3435
idp_metadata = get_idp_metadata(url, validate_cert)
35-
parse(idp_metadata)
36+
parse(idp_metadata, options)
3637
end
3738

3839
# Parse the Identity Provider metadata and update the settings with the IdP values
3940
# @param idp_metadata [String]
41+
# @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object
4042
#
41-
def parse(idp_metadata)
43+
def parse(idp_metadata, options = {})
4244
@document = REXML::Document.new(idp_metadata)
4345

44-
OneLogin::RubySaml::Settings.new.tap do |settings|
46+
(options[:settings] || OneLogin::RubySaml::Settings.new).tap do |settings|
4547
settings.idp_entity_id = idp_entity_id
4648
settings.name_identifier_format = idp_name_id_format
47-
settings.idp_sso_target_url = single_signon_service_url
48-
settings.idp_slo_target_url = single_logout_service_url
49+
settings.idp_sso_target_url = single_signon_service_url(options)
50+
settings.idp_slo_target_url = single_logout_service_url(options)
4951
settings.idp_cert = certificate_base64
50-
settings.idp_cert_fingerprint = fingerprint
52+
settings.idp_cert_fingerprint = fingerprint(settings.idp_cert_fingerprint_algorithm)
5153
settings.idp_attribute_names = attribute_names
54+
settings.idp_cert_fingerprint = fingerprint(settings.idp_cert_fingerprint_algorithm)
5255
end
5356
end
5457

@@ -115,23 +118,61 @@ def idp_name_id_format
115118
node.text if node
116119
end
117120

121+
# @param binding_priority [Array]
122+
# @return [String|nil] SingleSignOnService binding if exists
123+
#
124+
def single_signon_service_binding(binding_priority = nil)
125+
nodes = REXML::XPath.match(
126+
document,
127+
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleSignOnService/@Binding",
128+
{ "md" => METADATA }
129+
)
130+
if binding_priority
131+
values = nodes.map(&:value)
132+
binding_priority.detect{ |binding| values.include? binding }
133+
else
134+
nodes.first.value if nodes.any?
135+
end
136+
end
137+
138+
# @param options [Hash]
118139
# @return [String|nil] SingleSignOnService endpoint if exists
119140
#
120-
def single_signon_service_url
141+
def single_signon_service_url(options = {})
142+
binding = options[:sso_binding] || "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
121143
node = REXML::XPath.first(
122144
document,
123-
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleSignOnService/@Location",
145+
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleSignOnService[@Binding=\"#{binding}\"]/@Location",
124146
{ "md" => METADATA }
125147
)
126148
node.value if node
127149
end
128150

151+
# @param binding_priority [Array]
152+
# @return [String|nil] SingleLogoutService binding if exists
153+
#
154+
def single_logout_service_binding(binding_priority = nil)
155+
nodes = REXML::XPath.match(
156+
document,
157+
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleLogoutService/@Binding",
158+
{ "md" => METADATA }
159+
)
160+
if binding_priority
161+
values = nodes.map(&:value)
162+
binding_priority.detect{ |binding| values.include? binding }
163+
else
164+
nodes.first.value if nodes.any?
165+
end
166+
end
167+
168+
# @param options [Hash]
129169
# @return [String|nil] SingleLogoutService endpoint if exists
130170
#
131-
def single_logout_service_url
171+
def single_logout_service_url(options = {})
172+
binding = options[:slo_binding] || "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
132173
node = REXML::XPath.first(
133174
document,
134-
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleLogoutService/@Location",
175+
"/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleLogoutService[@Binding=\"#{binding}\"]/@Location",
135176
{ "md" => METADATA }
136177
)
137178
node.value if node
@@ -169,11 +210,13 @@ def certificate
169210

170211
# @return [String|nil] the SHA-1 fingerpint of the X509Certificate if it exists
171212
#
172-
def fingerprint
213+
def fingerprint(fingerprint_algorithm)
173214
@fingerprint ||= begin
174215
if certificate
175216
cert = OpenSSL::X509::Certificate.new(certificate)
176-
Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
217+
218+
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(fingerprint_algorithm).new
219+
fingerprint_alg.hexdigest(cert.to_der).upcase.scan(/../).join(":")
177220
end
178221
end
179222
end

0 commit comments

Comments
 (0)