Class: Saml::Kit::Metadata

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations, Buildable, Translatable, XsdValidatable
Defined in:
lib/saml/kit/metadata.rb

Overview

The Metadata object can be used to parse an XML string of metadata.

 = Saml::Kit::Metadata.from(raw_xml)

It can also be used to generate a new metadata string.

 = Saml::Kit::Metadata.build do |builder|
  builder.entity_id = "my-issuer"
  builder.build_service_provider do |x|
    x.add_assertion_consumer_service(assertions_url, binding: :http_post)
    x.add_single_logout_service(logout_url, binding: :http_post)
  end
  builder.build_identity_provider do |x|
    x.add_single_sign_on_service(, binding: :http_redirect)
    x.add_single_logout_service(logout_url, binding: :http_post)
  end
end
puts .to_xml(pretty: true)

See Builders::ServiceProviderMetadata and Builders::IdentityProviderMetadata for a list of options that can be specified.

Constant Summary collapse

METADATA_XSD =
File.expand_path('./xsd/saml-schema-metadata-2.0.xsd', File.dirname(__FILE__)).freeze
NAMESPACES =
{
  "NameFormat": Namespaces::ATTR_SPLAT,
  "ds": ::Xml::Kit::Namespaces::XMLDSIG,
  "md": Namespaces::METADATA,
  "saml": Namespaces::ASSERTION,
  "samlp": Namespaces::PROTOCOL,
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, xml) ⇒ Metadata

Returns a new instance of Metadata.



46
47
48
49
# File 'lib/saml/kit/metadata.rb', line 46

def initialize(name, xml)
  @name = name
  @xml = xml
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



44
45
46
# File 'lib/saml/kit/metadata.rb', line 44

def name
  @name
end

Class Method Details

.from(content) ⇒ Saml::Kit::Metadata

Creates a ‘Saml::Kit::Metadata` object from a raw XML [String].

Parameters:

  • content (String)

    the raw metadata XML.

Returns:



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/saml/kit/metadata.rb', line 191

def from(content)
  hash = Hash.from_xml(content)
  entity_descriptor = hash['EntityDescriptor']
  if entity_descriptor.key?('SPSSODescriptor') && entity_descriptor.key?('IDPSSODescriptor')
    Saml::Kit::CompositeMetadata.new(content)
  elsif entity_descriptor.keys.include?('SPSSODescriptor')
    Saml::Kit::ServiceProviderMetadata.new(content)
  elsif entity_descriptor.keys.include?('IDPSSODescriptor')
    Saml::Kit::IdentityProviderMetadata.new(content)
  end
end

Instance Method Details

#certificatesObject

Returns each of the X509 certificates.



77
78
79
80
81
82
83
84
# File 'lib/saml/kit/metadata.rb', line 77

def certificates
  @certificates ||= document.find_all("/md:EntityDescriptor/md:#{name}/md:KeyDescriptor").map do |item|
    cert = item.at_xpath('./ds:KeyInfo/ds:X509Data/ds:X509Certificate', NAMESPACES).text
    attribute = item.attribute('use')
    use = attribute.nil? ? nil : item.attribute('use').value
    ::Xml::Kit::Certificate.new(cert, use: use)
  end
end

#contact_person_companyObject

Returns the Company



72
73
74
# File 'lib/saml/kit/metadata.rb', line 72

def contact_person_company
  document.find_by('/md:EntityDescriptor/md:ContactPerson/md:Company').try(:text)
end

#encryption_certificatesObject

Returns the encryption certificates



87
88
89
# File 'lib/saml/kit/metadata.rb', line 87

def encryption_certificates
  certificates.find_all(&:encryption?)
end

#entity_idObject

Returns the /EntityDescriptor/@entityID



52
53
54
# File 'lib/saml/kit/metadata.rb', line 52

def entity_id
  document.find_by('/md:EntityDescriptor/@entityID').value
end

#logout_request_for(user, binding: :http_post, relay_state: nil) ⇒ Array

Creates a serialized LogoutRequest.

Parameters:

  • user (Object)

    a user object that responds to name_id_for and assertion_attributes_for.

  • binding (Symbol) (defaults to: :http_post)

    can be :http_post or :http_redirect.

  • relay_state (String) (defaults to: nil)

    the relay state to have echo’d back.

Returns:

  • (Array)

    Returns an array with a url and Hash of parameters to send to the other party.



134
135
136
137
138
139
140
# File 'lib/saml/kit/metadata.rb', line 134

def logout_request_for(user, binding: :http_post, relay_state: nil)
  builder = Saml::Kit::LogoutRequest.builder(user) do |x|
    yield x if block_given?
  end
  request_binding = single_logout_service_for(binding: binding)
  request_binding.serialize(builder, relay_state: relay_state)
end

#matches?(fingerprint, use: :signing) ⇒ Xml::Kit::Certificate

Returns the certificate that matches the fingerprint

Parameters:

  • fingerprint (Saml::Kit::Fingerprint)

    the fingerprint to search for.

  • use (Symbol) (defaults to: :signing)

    the type of certificates to look at. Can be :signing or :encryption.

Returns:

  • (Xml::Kit::Certificate)

    returns the matching ‘Xml::Kit::Certificate`



147
148
149
150
151
# File 'lib/saml/kit/metadata.rb', line 147

def matches?(fingerprint, use: :signing)
  certificates.find do |certificate|
    certificate.for?(use) && certificate.fingerprint == fingerprint
  end
end

#name_id_formatsObject

Returns the supported NameIDFormats.



57
58
59
# File 'lib/saml/kit/metadata.rb', line 57

def name_id_formats
  document.find_all("/md:EntityDescriptor/md:#{name}/md:NameIDFormat").map(&:text)
end

#organization_nameObject

Returns the Organization Name



62
63
64
# File 'lib/saml/kit/metadata.rb', line 62

def organization_name
  document.find_by('/md:EntityDescriptor/md:Organization/md:OrganizationName').try(:text)
end

#organization_urlObject

Returns the Organization URL



67
68
69
# File 'lib/saml/kit/metadata.rb', line 67

def organization_url
  document.find_by('/md:EntityDescriptor/md:Organization/md:OrganizationURL').try(:text)
end

#service_for(binding:, type:) ⇒ Object

Returns a specifing service binding.

Parameters:

  • binding (Symbol)

    can be :http_post or :http_redirect.

  • type (Symbol)

    can be on the service element like AssertionConsumerServiceURL, SingleSignOnService or SingleLogoutService.



111
112
113
114
# File 'lib/saml/kit/metadata.rb', line 111

def service_for(binding:, type:)
  binding = Saml::Kit::Bindings.binding_for(binding)
  services(type).find { |x| x.binding?(binding) }
end

#services(type) ⇒ Object

Returns each of the service endpoints supported by this metadata.

Parameters:

  • type (String)

    the type of service. .E.g. AssertionConsumerServiceURL



99
100
101
102
103
104
105
# File 'lib/saml/kit/metadata.rb', line 99

def services(type)
  document.find_all("/md:EntityDescriptor/md:#{name}/md:#{type}").map do |item|
    binding = item.attribute('Binding').value
    location = item.attribute('Location').value
    Saml::Kit::Bindings.create_for(binding, location)
  end
end

#signatureObject



182
183
184
# File 'lib/saml/kit/metadata.rb', line 182

def signature
  @signature ||= Signature.new(at_xpath('/md:EntityDescriptor/ds:Signature'))
end

#signing_certificatesObject

Returns the signing certificates.



92
93
94
# File 'lib/saml/kit/metadata.rb', line 92

def signing_certificates
  certificates.find_all(&:signing?)
end

#single_logout_service_for(binding:) ⇒ Object

Returns the SingleLogoutService that matches the specified binding.

Parameters:

  • binding (Symbol)

    can be :http_post or :http_redirect.



124
125
126
# File 'lib/saml/kit/metadata.rb', line 124

def single_logout_service_for(binding:)
  service_for(binding: binding, type: 'SingleLogoutService')
end

#single_logout_servicesObject

Returns each of the SingleLogoutService bindings



117
118
119
# File 'lib/saml/kit/metadata.rb', line 117

def single_logout_services
  services('SingleLogoutService')
end

#to_hObject

Returns the XML document converted to a Hash.



154
155
156
# File 'lib/saml/kit/metadata.rb', line 154

def to_h
  @xml_hash ||= Hash.from_xml(to_xml)
end

#to_sObject

Returns the XML document as a [String].



166
167
168
# File 'lib/saml/kit/metadata.rb', line 166

def to_s
  to_xml
end

#to_xml(pretty: false) ⇒ Object

Returns the XML document as a String.

Parameters:

  • pretty (Symbol) (defaults to: false)

    true to return a human friendly version of the XML.



161
162
163
# File 'lib/saml/kit/metadata.rb', line 161

def to_xml(pretty: false)
  document.to_xml(pretty: pretty)
end

#verify(algorithm, signature, data) ⇒ Xml::Kit::Certificate

Verifies the signature and data using the signing certificates.

Parameters:

  • algorithm (OpenSSL::Digest)

    the digest algorithm to use. E.g. OpenSSL::Digest::SHA256

  • signature (String)

    the signature to verify

  • data (String)

    the data that is used to produce the signature.

Returns:

  • (Xml::Kit::Certificate)

    the certificate that was used to produce the signature.



176
177
178
179
180
# File 'lib/saml/kit/metadata.rb', line 176

def verify(algorithm, signature, data)
  signing_certificates.find do |certificate|
    certificate.public_key.verify(algorithm, signature, data)
  end
end