class OneLogin::RubySaml::IdpMetadataParser::IdpMetadata
Attributes
Public Class Methods
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 226 def initialize(idpsso_descriptor, entity_id) @idpsso_descriptor = idpsso_descriptor @entity_id = entity_id end
Public Instance Methods
@return [Array] the names of all SAML attributes if any exist
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 399 def attribute_names nodes = REXML::XPath.match( @idpsso_descriptor , "saml:Attribute/@Name", SamlMetadata::NAMESPACE ) nodes.map(&:value) end
@return [String|nil] ‘cacheDuration’ attribute of metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 262 def cache_duration root = @idpsso_descriptor.root root.attributes['cacheDuration'] if root && root.attributes end
@return [String|nil] Unformatted Certificate if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 350 def certificates @certificates ||= begin signing_nodes = REXML::XPath.match( @idpsso_descriptor, "md:KeyDescriptor[not(contains(@use, 'encryption'))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate", SamlMetadata::NAMESPACE ) encryption_nodes = REXML::XPath.match( @idpsso_descriptor, "md:KeyDescriptor[not(contains(@use, 'signing'))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate", SamlMetadata::NAMESPACE ) return nil if signing_nodes.empty? && encryption_nodes.empty? certs = {} unless signing_nodes.empty? certs['signing'] = [] signing_nodes.each do |cert_node| certs['signing'] << Utils.element_text(cert_node) end end unless encryption_nodes.empty? certs['encryption'] = [] encryption_nodes.each do |cert_node| certs['encryption'] << Utils.element_text(cert_node) end end certs end end
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 433 def certificates_has_one(key) certificates.key?(key) && certificates[key].size == 1 end
@return [String|nil] the fingerpint of the X509Certificate if it exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 386 def fingerprint(certificate, fingerprint_algorithm = XMLSecurity::Document::SHA1) @fingerprint ||= begin return unless certificate cert = OpenSSL::X509::Certificate.new(Base64.decode64(certificate)) fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(fingerprint_algorithm).new fingerprint_alg.hexdigest(cert.to_der).upcase.scan(/../).join(":") end end
@param name_id_priority [String|Array<String>] The prioritized list of NameIDFormat values to select. Will select first value if nil. @return [String|nil] IdP NameIDFormat value if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 270 def idp_name_id_format(name_id_priority = nil) nodes = REXML::XPath.match( @idpsso_descriptor, "md:NameIDFormat", SamlMetadata::NAMESPACE ) first_ranked_text(nodes, name_id_priority) end
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 408 def merge_certificates_into(parsed_metadata) if (certificates.size == 1 && (certificates_has_one('signing') || certificates_has_one('encryption'))) || (certificates_has_one('signing') && certificates_has_one('encryption') && certificates["signing"][0] == certificates["encryption"][0]) if certificates.key?("signing") parsed_metadata[:idp_cert] = certificates["signing"][0] parsed_metadata[:idp_cert_fingerprint] = fingerprint( parsed_metadata[:idp_cert], parsed_metadata[:idp_cert_fingerprint_algorithm] ) else parsed_metadata[:idp_cert] = certificates["encryption"][0] parsed_metadata[:idp_cert_fingerprint] = fingerprint( parsed_metadata[:idp_cert], parsed_metadata[:idp_cert_fingerprint_algorithm] ) end end # symbolize keys of certificates and pass it on parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }] end
@param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil. @return [String|nil] SingleLogoutService response url if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 336 def single_logout_response_service_url(binding_priority = nil) binding = single_logout_service_binding(binding_priority) return if binding.nil? node = REXML::XPath.first( @idpsso_descriptor, "md:SingleLogoutService[@Binding=\"#{binding}\"]/@ResponseLocation", SamlMetadata::NAMESPACE ) node.value if node end
@param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil. @return [String|nil] SingleLogoutService binding if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 294 def single_logout_service_binding(binding_priority = nil) nodes = REXML::XPath.match( @idpsso_descriptor, "md:SingleLogoutService/@Binding", SamlMetadata::NAMESPACE ) first_ranked_value(nodes, binding_priority) end
@param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil. @return [String|nil] SingleLogoutService endpoint if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 321 def single_logout_service_url(binding_priority = nil) binding = single_logout_service_binding(binding_priority) return if binding.nil? node = REXML::XPath.first( @idpsso_descriptor, "md:SingleLogoutService[@Binding=\"#{binding}\"]/@Location", SamlMetadata::NAMESPACE ) node.value if node end
@param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil. @return [String|nil] SingleSignOnService binding if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 282 def single_signon_service_binding(binding_priority = nil) nodes = REXML::XPath.match( @idpsso_descriptor, "md:SingleSignOnService/@Binding", SamlMetadata::NAMESPACE ) first_ranked_value(nodes, binding_priority) end
@param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil. @return [String|nil] SingleSignOnService endpoint if exists
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 306 def single_signon_service_url(binding_priority = nil) binding = single_signon_service_binding(binding_priority) return if binding.nil? node = REXML::XPath.first( @idpsso_descriptor, "md:SingleSignOnService[@Binding=\"#{binding}\"]/@Location", SamlMetadata::NAMESPACE ) node.value if node end
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 231 def to_hash(options = {}) sso_binding = options[:sso_binding] slo_binding = options[:slo_binding] { :idp_entity_id => @entity_id, :name_identifier_format => idp_name_id_format(options[:name_id_format]), :idp_sso_service_url => single_signon_service_url(sso_binding), :idp_sso_service_binding => single_signon_service_binding(sso_binding), :idp_slo_service_url => single_logout_service_url(slo_binding), :idp_slo_service_binding => single_logout_service_binding(slo_binding), :idp_slo_response_service_url => single_logout_response_service_url(slo_binding), :idp_attribute_names => attribute_names, :idp_cert => nil, :idp_cert_fingerprint => nil, :idp_cert_multi => nil, :valid_until => valid_until, :cache_duration => cache_duration, }.tap do |response_hash| merge_certificates_into(response_hash) unless certificates.nil? end end
@return [String|nil] ‘validUntil’ attribute of metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 255 def valid_until root = @idpsso_descriptor.root root.attributes['validUntil'] if root && root.attributes end
Private Instance Methods
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 439 def first_ranked_text(nodes, priority = nil) return unless nodes.any? priority = Array(priority) if priority.any? values = nodes.map(&:text) priority.detect { |candidate| values.include?(candidate) } else nodes.first.text end end
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 451 def first_ranked_value(nodes, priority = nil) return unless nodes.any? priority = Array(priority) if priority.any? values = nodes.map(&:value) priority.detect { |candidate| values.include?(candidate) } else nodes.first.value end end