Skip to content

Commit bb2dcb2

Browse files
committed
Add possibility to parse all present IdPs in IdpMetadataParser
1 parent e36442f commit bb2dcb2

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

lib/onelogin/ruby-saml/idp_metadata_parser.rb

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,25 @@ def parse_remote(url, validate_cert = true, options = {})
6767
#
6868
# @raise [HttpError] Failure to fetch remote IdP metadata
6969
def parse_remote_to_hash(url, validate_cert = true, options = {})
70+
parse_remote_to_array(url, validate_cert, options)[0]
71+
end
72+
73+
# Parse all Identity Provider metadata and return the results as Array
74+
#
75+
# @param url [String] Url where the XML of the Identity Provider Metadata is published.
76+
# @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
77+
#
78+
# @param options [Hash] options used for parsing the metadata
79+
# @option options [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 [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, nil] :entity_id when this is given, the entity descriptor for this ID is used. When ommitted, all found IdPs are returned.
82+
#
83+
# @return [Array<Hash>]
84+
#
85+
# @raise [HttpError] Failure to fetch remote IdP metadata
86+
def parse_remote_to_array(url, validate_cert = true, options = {})
7087
idp_metadata = get_idp_metadata(url, validate_cert)
71-
parse_to_hash(idp_metadata, options)
88+
parse_to_array(idp_metadata, options)
7289
end
7390

7491
# Parse the Identity Provider metadata and update the settings with the IdP values
@@ -107,15 +124,29 @@ def parse(idp_metadata, options = {})
107124
#
108125
# @return [Hash]
109126
def parse_to_hash(idp_metadata, options = {})
127+
parse_to_array(idp_metadata, options)[0]
128+
end
129+
130+
# Parse all Identity Provider metadata and return the results as Array
131+
#
132+
# @param idp_metadata [String]
133+
#
134+
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
135+
# @option options [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.
136+
# @option options [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.
137+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When ommitted, all found IdPs are returned.
138+
#
139+
# @return [Array<Hash>]
140+
def parse_to_array(idp_metadata, options = {})
110141
@document = REXML::Document.new(idp_metadata)
111142
@options = options
112143

113-
idpsso_descriptor = IdpMetadata::get_idps(@document, options[:entity_id])[0]
114-
if idpsso_descriptor.nil?
144+
idpsso_descriptors = IdpMetadata::get_idps(@document, options[:entity_id])
145+
if !idpsso_descriptors.any?
115146
raise ArgumentError.new("idp_metadata must contain an IDPSSODescriptor element")
116147
end
117148

118-
return IdpMetadata.new(idpsso_descriptor, idpsso_descriptor.parent.attributes["entityID"]).to_hash(options)
149+
return idpsso_descriptors.map{|id| IdpMetadata.new(id, id.parent.attributes["entityID"]).to_hash(options)}
119150
end
120151

121152
private

test/idp_metadata_parser_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,14 @@ def initialize; end
342342
assert_equal "https://hello.example.com/access/saml/logout", @settings.idp_slo_target_url
343343
assert_equal ["AuthToken", "SSOStartPage"], @settings.idp_attribute_names
344344
end
345+
346+
it "should handle multiple descriptors at once" do
347+
settings = @idp_metadata_parser.parse_to_array(@idp_metadata)
348+
assert_equal "https://foo.example.com/access/saml/idp.xml", settings.first[:idp_entity_id]
349+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.first[:idp_cert_fingerprint]
350+
assert_equal "https://bar.example.com/access/saml/idp.xml", settings.last[:idp_entity_id]
351+
assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.last[:idp_cert_fingerprint]
352+
end
345353
end
346354

347355
describe "parsing metadata with no IDPSSODescriptor element" do

0 commit comments

Comments
 (0)