@@ -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