Comparing changes

v0.2.14 v0.2.15
8 commits 24 files changed

Commits

803ab1d bump version. mo 2017-12-21 23:52:45
727a70d document Certificate mo 2017-12-21 23:46:58
dc9b9e9 add more documentation. mo 2017-12-21 23:37:46
4e4dcea add documentation. mo 2017-12-21 22:58:01
ade1976 params -> param. mo 2017-12-21 19:22:56
6b5e200 add documentation. mo 2017-12-21 19:19:27
ca36f2d add api doc. mo 2017-12-21 18:59:45
exe/saml-kit-create-self-signed-certificate
@@ -1,9 +1,9 @@
 #!/usr/bin/env ruby
 require 'saml/kit'
 
-puts "Enter Password:"
-password = STDIN.read.strip
-certificate, private_key = Saml::Kit::SelfSignedCertificate.new(password).create
+puts "Enter Passphrase:"
+passphrase = STDIN.read.strip
+certificate, private_key = Saml::Kit::SelfSignedCertificate.new(passphrase).create
 
 puts "** BEGIN File Format **"
 print certificate
@@ -18,5 +18,5 @@ puts private_key.inspect
 puts "***********************"
 
 puts
-puts "Private Key Password:"
-puts password.inspect
+puts "Private Key Passphrase:"
+puts passphrase.inspect
lib/saml/kit/builders/response.rb
@@ -18,18 +18,10 @@ module Saml
           @version = "2.0"
           @status_code = Namespaces::SUCCESS
           @issuer = configuration.issuer
-          @embed_signature = want_assertions_signed
           @encrypt = encryption_certificate.present?
           @configuration = configuration
         end
 
-        def want_assertions_signed
-          request.provider.want_assertions_signed
-        rescue => error
-          Saml::Kit.logger.error(error)
-          nil
-        end
-
         def build
           Saml::Kit::Response.new(to_xml, request_id: request.id, configuration: configuration)
         end
lib/saml/kit/certificate.rb
@@ -3,33 +3,51 @@ module Saml
     class Certificate
       BEGIN_CERT=/-----BEGIN CERTIFICATE-----/
       END_CERT=/-----END CERTIFICATE-----/
-      attr_reader :value, :use
+      # The use can be `:signing` or `:encryption`
+      attr_reader :use
 
       def initialize(value, use:)
         @value = value
         @use = use.downcase.to_sym
       end
 
+      # @return [Saml::Kit::Fingerprint] the certificate fingerprint.
       def fingerprint
         Fingerprint.new(value)
       end
 
+      # Returns true if this certificate is for the specified use.
+      #
+      # @param use [Symbol] `:signing` or `:encryption`.
+      # @return [Boolean] true or false.
       def for?(use)
         self.use == use.to_sym
       end
 
+      # Returns true if this certificate is used for encryption.
+      #
+      # return [Boolean] true or false.
       def encryption?
         for?(:encryption)
       end
 
+      # Returns true if this certificate is used for signing.
+      #
+      # return [Boolean] true or false.
       def signing?
         for?(:signing)
       end
 
+      # Returns the x509 form.
+      #
+      # return [OpenSSL::X509::Certificate] the OpenSSL equivalent.
       def x509
         self.class.to_x509(value)
       end
 
+      # Returns the public key.
+      #
+      # @return [OpenSSL::PKey::RSA] the RSA public key.
       def public_key
         x509.public_key
       end
@@ -68,6 +86,10 @@ module Saml
         Saml::Kit.logger.warn(error)
         OpenSSL::X509::Certificate.new(value)
       end
+
+      private
+
+      attr_reader :value
     end
   end
 end
lib/saml/kit/configuration.rb
@@ -11,20 +11,20 @@ module Saml
     #     config.logger = Rails.logger
     #   end
     #
-    #   To specify global configuration it is best to do this in an initialize 
+    #   To specify global configuration it is best to do this in an initializer
     #   that runs at the start of the program.
     #
     #   Saml::Kit.configure do |configuration|
     #     configuration.issuer = "https://www.example.com/saml/metadata"
     #     configuration.generate_key_pair_for(use: :signing)
-    #     configuration.add_key_pair(ENV["X509_CERTIFICATE"], ENV["PRIVATE_KEY"], password: ENV['PRIVATE_KEY_PASSWORD'], use: :encryption)
+    #     configuration.add_key_pair(ENV["X509_CERTIFICATE"], ENV["PRIVATE_KEY"], passphrase: ENV['PRIVATE_KEY_PASSPHRASE'], use: :encryption)
     #   end
     class Configuration
       # The issuer or entity_id to use.
       attr_accessor :issuer
-      # The signature method to use when generating signatures (See {SAML::Kit::Builders::XmlSignature::SIGNATURE_METHODS})
+      # The signature method to use when generating signatures (See {Saml::Kit::Builders::XmlSignature::SIGNATURE_METHODS})
       attr_accessor :signature_method
-      # The digest method to use when generating signatures (See {SAML::Kit::Builders::XmlSignature::DIGEST_METHODS})
+      # The digest method to use when generating signatures (See {Saml::Kit::Builders::XmlSignature::DIGEST_METHODS})
       attr_accessor :digest_method
       # The metadata registry to use for searching for metadata associated with an issuer.
       attr_accessor :registry
@@ -47,19 +47,19 @@ module Saml
       #
       # @param certificate [String] the x509 certificate with public key.
       # @param private_key [String] the plain text private key.
-      # @param password [String] the password to decrypt the private key.
+      # @param passphrase [String] the password to decrypt the private key.
       # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
-      def add_key_pair(certificate, private_key, password: '', use: :signing)
-        @key_pairs.push(KeyPair.new(certificate, private_key, password, use.to_sym))
+      def add_key_pair(certificate, private_key, passphrase: '', use: :signing)
+        @key_pairs.push(KeyPair.new(certificate, private_key, passphrase, use.to_sym))
       end
 
       # Generates a unique key pair that can be used for signing or encryption.
       #
       # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
-      # @param password [String] the private key password to use.
-      def generate_key_pair_for(use:, password: SecureRandom.uuid)
-        certificate, private_key = SelfSignedCertificate.new(password).create
-        add_key_pair(certificate, private_key, password: password, use: use)
+      # @param passphrase [String] the private key passphrase to use.
+      def generate_key_pair_for(use:, passphrase: SecureRandom.uuid)
+        certificate, private_key = SelfSignedCertificate.new(passphrase).create
+        add_key_pair(certificate, private_key, passphrase: passphrase, use: use)
       end
 
       # Return each key pair for a specific use.
lib/saml/kit/crypto.rb
@@ -8,6 +8,7 @@ module Saml
     module Crypto
       DECRYPTORS = [ SimpleCipher, RsaCipher, OaepCipher, UnknownCipher ]
 
+      # @!visibility private
       def self.decryptor_for(algorithm, key)
         DECRYPTORS.find { |x| x.matches?(algorithm) }.new(algorithm, key)
       end
lib/saml/kit/default_registry.rb
@@ -2,6 +2,31 @@ module Saml
   module Kit
     # The default metadata registry is used to fetch the metadata associated with an issuer or entity id.
     # The metadata associated with an issuer is used to verify trust for any SAML documents that are received.
+    #
+    # You can replace the default registry with your own at startup.
+    #
+    # Example:
+    #
+    #   class OnDemandRegistry
+    #    def initialize(original)
+    #      @original = original
+    #    end
+    #
+    #    def metadata_for(entity_id)
+    #      found = @original.metadata_for(entity_id)
+    #      return found if found
+    #
+    #      @original.register_url(entity_id, verify_ssl: Rails.env.production?)
+    #      @original.metadata_for(entity_id)
+    #    end
+    #   end
+    #
+    #   Saml::Kit.configure do |configuration|
+    #     configuration.issuer = ENV['ISSUER']
+    #     configuration.registry = OnDemandRegistry.new(configuration.registry)
+    #     configuration.logger = Rails.logger
+    #   end
+
     class DefaultRegistry
       def initialize(items = {})
         @items = items
lib/saml/kit/fingerprint.rb
@@ -1,6 +1,11 @@
 module Saml
   module Kit
     # This generates a fingerprint for an X509 Certificate.
+    #
+    #   certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
+    #
+    #   puts Saml::Kit::Fingerprint.new(certificate).to_s
+    #   # B7:AB:DC:BD:4D:23:58:65:FD:1A:99:0C:5F:89:EA:87:AD:F1:D7:83:34:7A:E9:E4:88:12:DD:46:1F:38:05:93
     class Fingerprint
       # The OpenSSL::X509::Certificate
       attr_reader :x509
lib/saml/kit/id.rb
@@ -1,6 +1,11 @@
 module Saml
   module Kit
+    # This class is used primary for generating ID.
+    #https://www.w3.org/2001/XMLSchema.xsd
     class Id
+
+     # Generate an ID that conforms to the XML Schema.
+      # https://www.w3.org/2001/XMLSchema.xsd
       def self.generate
         "_#{SecureRandom.uuid}"
       end
lib/saml/kit/identity_provider_metadata.rb
@@ -2,6 +2,7 @@ module Saml
   module Kit
     # This class is used to parse the IDPSSODescriptor from a SAML metadata document.
     #
+    #  raw_xml = <<-XML
     #  <?xml version="1.0" encoding="UTF-8"?>
     #  <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_cfa24e2f-0ec0-4ee3-abb8-b2fcfe394c1c" entityID="">
     #    <IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
@@ -12,6 +13,19 @@ module Saml
     #      <saml:Attribute Name="id"/>
     #    </IDPSSODescriptor>
     #  </EntityDescriptor>
+    #  XML
+    #
+    #  metadata = Saml::Kit::IdentityProviderMetadata.new(raw_xml)
+    #  puts metadata.entity_id
+    #
+    # It can also be used to generate IDP metadata.
+    #
+    #   metadata = Saml::Kit::IdentityProviderMetadata.build do |builder|
+    #     builder.entity_id = "my-entity-id"
+    #   end
+    #   puts metadata.to_xml
+    #
+    # For more details on generating metadata see {Saml::Kit::Metadata}.
     class IdentityProviderMetadata < Metadata
       def initialize(xml)
         super("IDPSSODescriptor", xml)
lib/saml/kit/key_pair.rb
@@ -9,10 +9,17 @@ module Saml
         @private_key = OpenSSL::PKey::RSA.new(private_key, passphrase)
       end
 
+      # Returns true if the key pair is the designated use.
+      #
+      # @param use [Symbol] Can be either `:signing` or `:encryption`.
       def for?(use)
         @use == use
       end
 
+      # Returns a generated self signed certificate with private key.
+      #
+      # @param use [Symbol] Can be either `:signing` or `:encryption`.
+      # @param passphrase [String] the passphrase to use to encrypt the private key.
       def self.generate(use:, passphrase: SecureRandom.uuid)
         certificate, private_key = SelfSignedCertificate.new(passphrase).create
         new(certificate, private_key, passphrase, use)
lib/saml/kit/logout_request.rb
@@ -1,10 +1,33 @@
 module Saml
   module Kit
-    # This class parses a LogoutRequest SAML document.
+    # This class can be used to parse a LogoutRequest SAML document.
+    #
+    #   document = Saml::Kit::LogoutRequest.new(raw_xml)
+    #
+    # It can also be used to generate a new LogoutRequest.
+    #
+    #   document = Saml::Kit::LogoutRequest.build do |builder|
+    #     builder.issuer = "issuer"
+    #   end
+    #
+    #   puts document.to_xml(pretty: true)
+    #
+    # See {Saml::Kit::Builders::LogoutRequest} for a list of available settings.
+    #
+    # This class can also be used to generate the correspondong LogoutResponse for a LogoutRequest.
+    #
+    #   document = Saml::Kit::LogoutRequest.new(raw_xml)
+    #   url, saml_params = document.response_for(binding: :http_post)
+    #
+    # See {#response_for} for more information.
     class LogoutRequest < Document
       include Requestable
       validates_presence_of :single_logout_service, if: :expected_type?
 
+      # A new instance of LogoutRequest
+      #
+      # @param xml [String] The raw xml string.
+      # @param configuration [Saml::Kit::Configuration] the configuration to use.
       def initialize(xml, configuration: Saml::Kit.configuration)
         super(xml, name: "LogoutRequest", configuration: configuration)
       end
lib/saml/kit/logout_response.rb
@@ -1,6 +1,8 @@
 module Saml
   module Kit
     # This class is used to parse a LogoutResponse SAML document.
+    #
+    #   document = Saml::Kit::LogoutResponse.new(raw_xml)
     class LogoutResponse < Document
       include Respondable
 
lib/saml/kit/metadata.rb
@@ -1,5 +1,26 @@
 module Saml
   module Kit
+    # The Metadata object can be used to parse an XML string of metadata.
+    #
+    #   metadata = Saml::Kit::Metadata.from(raw_xml)
+    #
+    # It can also be used to generate a new metadata string.
+    #
+    #   metadata = 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(login_url, binding: :http_redirect)
+    #       x.add_single_logout_service(logout_url, binding: :http_post)
+    #     end
+    #   end
+    #   puts metadata.to_xml(pretty: true)
+    #
+    # See {Saml::Kit::Builders::ServiceProviderMetadata} and {Saml::Kit::Builders::IdentityProviderMetadata}
+    # for a list of options that can be specified.
     class Metadata
       METADATA_XSD = File.expand_path("./xsd/saml-schema-metadata-2.0.xsd", File.dirname(__FILE__)).freeze
       include ActiveModel::Validations
@@ -12,35 +33,39 @@ module Saml
       validate :must_match_xsd
       validate :must_have_valid_signature
 
-      attr_reader :xml, :name
-      attr_accessor :hash_algorithm
+      attr_reader :name
 
       def initialize(name, xml)
         @name = name
         @xml = xml
-        @hash_algorithm = OpenSSL::Digest::SHA256
       end
 
+      # Returns the /EntityDescriptor/@entityID
       def entity_id
         document.find_by("/md:EntityDescriptor/@entityID").value
       end
 
+      # Returns the supported NameIDFormats.
       def name_id_formats
         document.find_all("/md:EntityDescriptor/md:#{name}/md:NameIDFormat").map(&:text)
       end
 
+      # Returns the Organization Name
       def organization_name
         document.find_by("/md:EntityDescriptor/md:Organization/md:OrganizationName").try(:text)
       end
 
+      # Returns the Organization URL
       def organization_url
         document.find_by("/md:EntityDescriptor/md:Organization/md:OrganizationURL").try(:text)
       end
 
+      # Returns the Company
       def contact_person_company
         document.find_by("/md:EntityDescriptor/md:ContactPerson/md:Company").try(:text)
       end
 
+      # Returns each of the X509 certificates.
       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", Xml::NAMESPACES).text
@@ -48,14 +73,19 @@ module Saml
         end
       end
 
+      # Returns the encryption certificates
       def encryption_certificates
         certificates.find_all(&:encryption?)
       end
 
+      # Returns the signing certificates.
       def signing_certificates
         certificates.find_all(&:signing?)
       end
 
+      # Returns each of the service endpoints supported by this metadata.
+      #
+      # @param type [String] the type of service. .E.g. `AssertionConsumerServiceURL`
       def services(type)
         document.find_all("/md:EntityDescriptor/md:#{name}/md:#{type}").map do |item|
           binding = item.attribute("Binding").value
@@ -64,19 +94,33 @@ module Saml
         end
       end
 
+      # Returns a specifing service binding.
+      #
+      # @param binding [Symbol] can be `:http_post` or `:http_redirect`.
+      # @param type [Symbol] can be on the service element like `AssertionConsumerServiceURL`, `SingleSignOnService` or `SingleLogoutService`.
       def service_for(binding:, type:)
         binding = Saml::Kit::Bindings.binding_for(binding)
         services(type).find { |x| x.binding?(binding) }
       end
 
+      # Returns each of the SingleLogoutService bindings
       def single_logout_services
         services('SingleLogoutService')
       end
 
+      # Returns the SingleLogoutService that matches the specified binding.
+      #
+      # @param binding [Symbol] can be `:http_post` or `:http_redirect`.
       def single_logout_service_for(binding:)
         service_for(binding: binding, type: 'SingleLogoutService')
       end
 
+      # Creates a serialized LogoutRequest.
+      #
+      # @param user [Object] a user object that responds to `name_id_for` and `assertion_attributes_for`.
+      # @param binding [Symbol] can be `:http_post` or `:http_redirect`.
+      # @param relay_state [String] the relay state to have echo'd back.
+      # @return [Array] Returns an array with a url and Hash of parameters to send to the other party.
       def logout_request_for(user, binding: :http_post, relay_state: nil)
         builder = Saml::Kit::LogoutRequest.builder(user) do |x|
           yield x if block_given?
@@ -85,30 +129,50 @@ module Saml
         request_binding.serialize(builder, relay_state: relay_state)
       end
 
+      # Returns the certificate that matches the fingerprint
+      #
+      # @param fingerprint [Saml::Kit::Fingerprint] the fingerprint to search for.
+      # @param use [Symbol] the type of certificates to look at. Can be `:signing` or `:encryption`.
+      # @return [Saml::Kit::Certificate] returns the matching `{Saml::Kit::Certificate}`
       def matches?(fingerprint, use: :signing)
         certificates.find do |certificate|
           certificate.for?(use) && certificate.fingerprint == fingerprint
         end
       end
 
+      # Returns the XML document converted to a Hash.
       def to_h
         @xml_hash ||= Hash.from_xml(to_xml)
       end
 
+      # Returns the XML document as a String.
+      #
+      # @param pretty [Symbol] true to return a human friendly version of the XML.
       def to_xml(pretty: false)
         document.to_xml(pretty: pretty)
       end
 
+      # Returns the XML document as a [String].
       def to_s
         to_xml
       end
 
+      # Verifies the signature and data using the signing certificates.
+      #
+      # @param algorithm [OpenSSL::Digest] the digest algorithm to use. E.g. `OpenSSL::Digest::SHA256`
+      # @param signature [String] the signature to verify
+      # @param data [String] the data that is used to produce the signature.
+      # @return [Saml::Kit::Certificate] the certificate that was used to produce the signature.
       def verify(algorithm, signature, data)
         signing_certificates.find do |certificate|
           certificate.public_key.verify(algorithm, signature, data)
         end
       end
 
+      # Creates a `{Saml::Kit::Metadata}` object from a raw XML [String].
+      #
+      # @param content [String] the raw metadata XML.
+      # @return [Saml::Kit::Metadata] the metadata document or subclass.
       def self.from(content)
         hash = Hash.from_xml(content)
         entity_descriptor = hash["EntityDescriptor"]
@@ -121,12 +185,15 @@ module Saml
         end
       end
 
+      # @!visibility private
       def self.builder_class
         Saml::Kit::Builders::Metadata
       end
 
       private
 
+      attr_reader :xml
+
       def document
         @document ||= Xml.new(xml)
       end
lib/saml/kit/serializable.rb
@@ -1,28 +1,47 @@
 module Saml
   module Kit
     module Serializable
+      # Base 64 decodes the value.
+      #
+      # @param value [String] the string to base 64 decode.
       def decode(value)
         Base64.decode64(value)
       end
 
+      # Base 64 encodes the value.
+      #
+      # @param value [String] the string to base 64 encode.
       def encode(value)
         Base64.strict_encode64(value)
       end
 
+      # Inflates the value using zlib decompression.
+      #
+      # @param value [String] the value to inflate.
       def inflate(value)
         inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
         inflater.inflate(value)
       end
 
-      # drop header and checksum as per spec.
+      # Deflate the value and drop the header and checksum as per the SAML spec.
+      # https://en.wikipedia.org/wiki/SAML_2.0#HTTP_Redirect_Binding
+      #
+      # @param value [String] the value to deflate.
+      # @param level [Integer] the level of compression.
       def deflate(value, level: Zlib::BEST_COMPRESSION)
         Zlib::Deflate.deflate(value, level)[2..-5]
       end
 
+      # URL unescape a value
+      #
+      # @param value [String] the value to unescape.
       def unescape(value)
         CGI.unescape(value)
       end
 
+      # URL escape a value
+      #
+      # @param value [String] the value to escape.
       def escape(value)
         CGI.escape(value)
       end
lib/saml/kit/service_provider_metadata.rb
@@ -5,24 +5,31 @@ module Saml
         super("SPSSODescriptor", xml)
       end
 
+      # Returns each of the AssertionConsumerService bindings.
       def assertion_consumer_services
         services('AssertionConsumerService')
       end
 
+      # Returns the AssertionConsumerService for the specified binding.
+      #
+      # @param binding [Symbol] can be either `:http_post` or `:http_redirect`
       def assertion_consumer_service_for(binding:)
         service_for(binding: binding, type: 'AssertionConsumerService')
       end
 
+      # Returns true when the metadata demands that Assertions must be signed.
       def want_assertions_signed
         attribute = document.find_by("/md:EntityDescriptor/md:#{name}").attribute("WantAssertionsSigned")
         return true if attribute.nil?
         attribute.text.downcase == "true"
       end
 
+      # @!visibility private
       def self.builder_class
         Saml::Kit::Builders::ServiceProviderMetadata
       end
 
+      # @deprecated Use 'Saml::Kit::Builders::ServiceProviderMetadata'.
       Builder = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Saml::Kit::ServiceProviderMetadata::Builder', 'Saml::Kit::Builders::ServiceProviderMetadata')
     end
   end
lib/saml/kit/signature.rb
@@ -5,17 +5,20 @@ module Saml
         @xml_hash = xml_hash
       end
 
+      # Returns the embedded X509 Certificate
       def certificate
         value = to_h.fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
         return if value.nil?
         Saml::Kit::Certificate.new(value, use: :signing)
       end
 
+      # Returns true when the fingerprint of the certificate matches one of the certificates registered in the metadata.
       def trusted?(metadata)
         return false if metadata.nil?
         metadata.matches?(certificate.fingerprint, use: :signing)
       end
 
+      # Returns the XML Hash.
       def to_h
         @xml_hash
       end
lib/saml/kit/signatures.rb
@@ -1,5 +1,6 @@
 module Saml
   module Kit
+    # @!visibility private
     class Signatures # :nodoc:
       # @!visibility private
       attr_reader :configuration
@@ -10,6 +11,7 @@ module Saml
         @key_pair = configuration.key_pairs(use: :signing).last
       end
 
+      # @!visibility private
       def sign_with(key_pair)
         @key_pair = key_pair
       end
lib/saml/kit/templatable.rb
@@ -1,34 +1,46 @@
 module Saml
   module Kit
     module Templatable
+      # Can be used to disable embeding a signature.
+      # By default a signature will be embedded if a signing
+      # certificate is available via the configuration.
       attr_accessor :embed_signature
 
+      # @deprecated Use {#embed_signature=} instead of this method.
       def sign=(value)
         Saml::Kit.deprecate("sign= is deprecated. Use embed_signature= instead")
         self.embed_signature = value
       end
 
+      # Returns the generated XML document with an XML Digital Signature and XML Encryption.
       def to_xml(xml: ::Builder::XmlMarkup.new)
         signatures.complete(render(self, xml: xml))
       end
 
+      # @!visibility private
       def signature_for(reference_id:, xml:)
         return unless sign?
         render(signatures.build(reference_id), xml: xml)
       end
 
+      # Allows you to specify which key pair to use for generating an XML digital signature.
+      #
+      # @param key_pair [Saml::Kit::KeyPair] the key pair to use for signing.
       def sign_with(key_pair)
         signatures.sign_with(key_pair)
       end
 
+      # Returns true if an embedded signature is requested and at least one signing certificate is available via the configuration.
       def sign?
         embed_signature.nil? ? configuration.sign? : embed_signature && configuration.sign?
       end
 
+      # @!visibility private
       def signatures
         @signatures ||= Saml::Kit::Signatures.new(configuration: configuration)
       end
 
+      # @!visibility private
       def encryption_for(xml:)
         if encrypt?
           temp = ::Builder::XmlMarkup.new
@@ -41,10 +53,12 @@ module Saml
         end
       end
 
+      # @!visibility private
       def encrypt?
         encrypt && encryption_certificate
       end
 
+      # @!visibility private
       def render(model, options)
         Saml::Kit::Template.new(model).to_xml(options)
       end
lib/saml/kit/template.rb
@@ -7,6 +7,9 @@ module Saml
         @target = target
       end
 
+      # Returns the compiled template as a [String].
+      #
+      # @param options [Hash] The options hash to pass to the template engine.
       def to_xml(options)
         template.render(target, options)
       end
lib/saml/kit/trustable.rb
@@ -9,6 +9,7 @@ module Saml
         validate :must_be_trusted
       end
 
+      # Returns true when the document has an embedded XML Signature or has been verified externally.
       def signed?
         signature_manually_verified || signature.present?
       end
@@ -19,6 +20,7 @@ module Saml
         xml_hash ? Signature.new(xml_hash) : nil
       end
 
+      # Returns true when documents is signed and the signing certificate belongs to a known service entity.
       def trusted?
         return true if signature_manually_verified
         return false unless signed?
lib/saml/kit/version.rb
@@ -1,5 +1,5 @@
 module Saml
   module Kit
-    VERSION = "0.2.14"
+    VERSION = "0.2.15"
   end
 end
lib/saml/kit/xml.rb
@@ -10,8 +10,6 @@ module Saml
         "samlp": Namespaces::PROTOCOL,
       }.freeze
 
-      attr_reader :raw_xml, :document
-
       validate :validate_signatures
       validate :validate_certificates
 
@@ -20,27 +18,31 @@ module Saml
         @document = Nokogiri::XML(raw_xml)
       end
 
-      def x509_certificates
-        xpath = "//ds:KeyInfo/ds:X509Data/ds:X509Certificate"
-        document.search(xpath, Xmldsig::NAMESPACES).map do |item|
-          Certificate.to_x509(item.text)
-        end
-      end
-
+      # Returns the first XML node found by searching the document with the provided XPath.
+      #
+      # @param xpath [String] the XPath to use to search the document
       def find_by(xpath)
         document.at_xpath(xpath, NAMESPACES)
       end
 
+      # Returns all XML nodes found by searching the document with the provided XPath.
+      #
+      # @param xpath [String] the XPath to use to search the document
       def find_all(xpath)
         document.search(xpath, NAMESPACES)
       end
 
+      # Return the XML document as a [String].
+      #
+      # @param pretty [Boolean] return the XML string in a human readable format if true.
       def to_xml(pretty: true)
         pretty ? document.to_xml(indent: 2) : raw_xml
       end
 
       private
 
+      attr_reader :raw_xml, :document
+
       def validate_signatures
         invalid_signatures.flat_map(&:errors).uniq.each do |error|
           errors.add(error, "is invalid")
@@ -69,6 +71,13 @@ module Saml
           end
         end
       end
+
+      def x509_certificates
+        xpath = "//ds:KeyInfo/ds:X509Data/ds:X509Certificate"
+        document.search(xpath, Xmldsig::NAMESPACES).map do |item|
+          Certificate.to_x509(item.text)
+        end
+      end
     end
   end
 end
lib/saml/kit/xml_decryption.rb
@@ -1,12 +1,16 @@
 module Saml
   module Kit
     class XmlDecryption
+      # The list of private keys to use to attempt to decrypt the document.
       attr_reader :private_keys
 
       def initialize(configuration: Saml::Kit.configuration)
         @private_keys = configuration.private_keys(use: :encryption)
       end
 
+      # Decrypts an EncryptedData section of an XML document.
+      #
+      # @param data [Hash] the XML document converted to a [Hash] using Hash.from_xml.
       def decrypt(data)
         encrypted_data = data['EncryptedData']
         symmetric_key = symmetric_key_from(encrypted_data)
spec/saml/signatures_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
 RSpec.describe Saml::Kit::Signatures do
   let(:configuration) do
     config = Saml::Kit::Configuration.new
-    config.add_key_pair(certificate, private_key, password: password, use: :signing)
+    config.add_key_pair(certificate, private_key, passphrase: passphrase, use: :signing)
     config
   end
 
@@ -21,8 +21,8 @@ RSpec.describe Saml::Kit::Signatures do
     x.sign(rsa_key, OpenSSL::Digest::SHA256.new)
     x.to_pem
   end
-  let(:private_key) { rsa_key.to_pem(OpenSSL::Cipher.new('des3'), password) }
-  let(:password) { "password" }
+  let(:private_key) { rsa_key.to_pem(OpenSSL::Cipher.new('des3'), passphrase) }
+  let(:passphrase) { "password" }
 
   it 'generates a signature' do
     options = {