Skip to content

Commit 0814853

Browse files
authored
Merge pull request #531 from dub357/extensible_idp_metadata_parser
make IdpMetadataParser more extensible for subclasses
2 parents 4efb76e + 61200c1 commit 0814853

1 file changed

Lines changed: 24 additions & 21 deletions

File tree

lib/onelogin/ruby-saml/idp_metadata_parser.rb

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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
402405
end

0 commit comments

Comments
 (0)