class OneLogin::RubySaml::IdpMetadataParser
Auxiliary class to retrieve and parse the Identity Provider Metadata
This class does not validate in any way the URL that is introduced, make sure to validate it properly before use it in a parse_remote
method. Read the ‘Security warning` section of the README.md file to get more info
Attributes
Public Class Methods
fetch IdP descriptors from a metadata document
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 42 def self.get_idps(metadata_document, only_entity_id=nil) path = "//md:EntityDescriptor#{only_entity_id && '[@entityID="' + only_entity_id + '"]'}/md:IDPSSODescriptor" REXML::XPath.match( metadata_document, path, SamlMetadata::NAMESPACE ) end
Public Instance Methods
Retrieve the remote IdP metadata from the URL or a cached copy. @param url [String] Url where the XML of the Identity Provider Metadata
is published. @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked. @return [REXML::document] Parsed XML IdP metadata @raise [HttpError] Failure to fetch remote IdP metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 194 def get_idp_metadata(url, validate_cert) uri = URI.parse(url) raise ArgumentError.new("url must begin with http or https") unless /^https?/ =~ uri.scheme http = Net::HTTP.new(uri.host, uri.port) if uri.scheme == "https" http.use_ssl = true # Most IdPs will probably use self signed certs http.verify_mode = validate_cert ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE # Net::HTTP in Ruby 1.8 did not set the default certificate store # automatically when VERIFY_PEER was specified. if RUBY_VERSION < '1.9' && !http.ca_file && !http.ca_path && !http.cert_store http.cert_store = OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE end end get = Net::HTTP::Get.new(uri.request_uri) get.basic_auth uri.user, uri.password if uri.user @response = http.request(get) return response.body if response.is_a? Net::HTTPSuccess raise OneLogin::RubySaml::HttpError.new( "Failed to fetch idp metadata: #{response.code}: #{response.message}" ) end
Parse the Identity Provider metadata and update the settings with the IdP values
@param idp_metadata [String]
@param options [Hash] :settings to provide the OneLogin::RubySaml::Settings
object or an hash for Settings
overrides @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings
object which gets the parsed metadata merged into or an hash for Settings
overrides. @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [OneLogin::RubySaml::Settings]
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 121 def parse(idp_metadata, options = {}) parsed_metadata = parse_to_hash(idp_metadata, options) unless parsed_metadata[:cache_duration].nil? cache_valid_until_timestamp = OneLogin::RubySaml::Utils.parse_duration(parsed_metadata[:cache_duration]) unless cache_valid_until_timestamp.nil? if parsed_metadata[:valid_until].nil? || cache_valid_until_timestamp < Time.parse(parsed_metadata[:valid_until], Time.now.utc).to_i parsed_metadata[:valid_until] = Time.at(cache_valid_until_timestamp).utc.strftime("%Y-%m-%dT%H:%M:%SZ") end end end # Remove the cache_duration because on the settings # we only gonna suppot valid_until parsed_metadata.delete(:cache_duration) settings = options[:settings] if settings.nil? OneLogin::RubySaml::Settings.new(parsed_metadata) elsif settings.is_a?(Hash) OneLogin::RubySaml::Settings.new(settings.merge(parsed_metadata)) else merge_parsed_metadata_into(settings, parsed_metadata) end end
Parse the Identity Provider metadata and update the settings with the IdP values
@param url [String] Url where the XML of the Identity Provider Metadata
is published. @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
@param options [Hash] options used for parsing the metadata and the returned Settings
instance @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings
object which gets the parsed metadata merged into or an hash for Settings
overrides. @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [OneLogin::RubySaml::Settings]
@raise [HttpError] Failure to fetch remote IdP metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 67 def parse_remote(url, validate_cert = true, options = {}) idp_metadata = get_idp_metadata(url, validate_cert) parse(idp_metadata, options) end
Parse all Identity Provider metadata and return the results as Array
@param url [String] Url where the XML of the Identity Provider Metadata
is published. @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
@param options [Hash] options used for parsing the metadata @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [Array<Hash>]
@raise [HttpError] Failure to fetch remote IdP metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 104 def parse_remote_to_array(url, validate_cert = true, options = {}) idp_metadata = get_idp_metadata(url, validate_cert) parse_to_array(idp_metadata, options) end
Parse the Identity Provider metadata and return the results as Hash
@param url [String] Url where the XML of the Identity Provider Metadata
is published. @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
@param options [Hash] options used for parsing the metadata @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [Hash]
@raise [HttpError] Failure to fetch remote IdP metadata
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 86 def parse_remote_to_hash(url, validate_cert = true, options = {}) parse_remote_to_array(url, validate_cert, options)[0] end
Parse all Identity Provider metadata and return the results as Array
@param idp_metadata [String]
@param options [Hash] options used for parsing the metadata and the returned Settings
instance @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [Array<Hash>]
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 173 def parse_to_array(idp_metadata, options = {}) parse_to_idp_metadata_array(idp_metadata, options).map { |idp_md| idp_md.to_hash(options) } end
Parse the Identity Provider metadata and return the results as Hash
@param idp_metadata [String]
@param options [Hash] options used for parsing the metadata and the returned Settings
instance @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used. @option options [String, 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. @option options [String, 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. @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
@return [Hash]
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 158 def parse_to_hash(idp_metadata, options = {}) parse_to_array(idp_metadata, options)[0] end
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 177 def parse_to_idp_metadata_array(idp_metadata, options = {}) @document = REXML::Document.new(idp_metadata) @options = options idpsso_descriptors = self.class.get_idps(@document, options[:entity_id]) if !idpsso_descriptors.any? raise ArgumentError.new("idp_metadata must contain an IDPSSODescriptor element") end idpsso_descriptors.map {|id| IdpMetadata.new(id, id.parent.attributes["entityID"])} end
Private Instance Methods
# File lib/onelogin/ruby-saml/idp_metadata_parser.rb, line 464 def merge_parsed_metadata_into(settings, parsed_metadata) parsed_metadata.each do |key, value| settings.send("#{key}=".to_sym, value) end settings end