@@ -15,25 +15,35 @@ class IdpMetadataParser
1515
1616 module SamlMetadata
1717 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"
18+ METADATA = "urn:oasis:names:tc:SAML:2.0:metadata" . freeze
19+ DSIG = "http://www.w3.org/2000/09/xmldsig#" . freeze
20+ NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:*" . freeze
21+ SAML_ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion" . freeze
2222 end
2323
2424 NAMESPACE = {
2525 "md" => Vocabulary ::METADATA ,
2626 "NameFormat" => Vocabulary ::NAME_FORMAT ,
2727 "saml" => Vocabulary ::SAML_ASSERTION ,
2828 "ds" => Vocabulary ::DSIG
29- }
29+ } . freeze
3030 end
3131
3232 include SamlMetadata ::Vocabulary
3333 attr_reader :document
3434 attr_reader :response
3535 attr_reader :options
3636
37+ # fetch IdP descriptors from a metadata document
38+ def self . get_idps ( metadata_document , only_entity_id = nil )
39+ path = "//md:EntityDescriptor#{ only_entity_id && '[@entityID="' + only_entity_id + '"]' } /md:IDPSSODescriptor"
40+ REXML ::XPath . match (
41+ metadata_document ,
42+ path ,
43+ SamlMetadata ::NAMESPACE
44+ )
45+ end
46+
3747 # Parse the Identity Provider metadata and update the settings with the
3848 # IdP values
3949 #
@@ -139,17 +149,21 @@ def parse_to_hash(idp_metadata, options = {})
139149 #
140150 # @return [Array<Hash>]
141151 def parse_to_array ( idp_metadata , options = { } )
152+ parse_to_idp_metadata_array ( idp_metadata , options ) . map { |idp_md | idp_md . to_hash ( options ) }
153+ end
154+
155+ def parse_to_idp_metadata_array ( idp_metadata , options = { } )
142156 @document = REXML ::Document . new ( idp_metadata )
143157 @options = options
144158
145- idpsso_descriptors = IdpMetadata :: get_idps ( @document , options [ :entity_id ] )
159+ idpsso_descriptors = self . class . get_idps ( @document , options [ :entity_id ] )
146160 if !idpsso_descriptors . any?
147161 raise ArgumentError . new ( "idp_metadata must contain an IDPSSODescriptor element" )
148162 end
149163
150- return idpsso_descriptors . map { |id | IdpMetadata . new ( id , id . parent . attributes [ "entityID" ] ) . to_hash ( options ) }
164+ return idpsso_descriptors . map { |id | IdpMetadata . new ( id , id . parent . attributes [ "entityID" ] ) }
151165 end
152-
166+
153167 private
154168
155169 # Retrieve the remote IdP metadata from the URL or a cached copy.
@@ -184,15 +198,8 @@ def get_idp_metadata(url, validate_cert)
184198 end
185199
186200 class IdpMetadata
187- def self . get_idps ( metadata_document , only_entity_id = nil )
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
195-
201+ attr_reader :idpsso_descriptor , :entity_id
202+
196203 def initialize ( idpsso_descriptor , entity_id )
197204 @idpsso_descriptor = idpsso_descriptor
198205 @entity_id = entity_id
@@ -393,10 +400,6 @@ def merge_parsed_metadata_into(settings, parsed_metadata)
393400
394401 settings
395402 end
396-
397- if self . respond_to? ( :private_constant )
398- private_constant :SamlMetadata , :IdpMetadata
399- end
400403 end
401404 end
402405end
0 commit comments