Commit 5d10b20

mo <mo.khan@gmail.com>
2018-02-16 22:11:29
add metadata#signature.
1 parent 3d4909c
lib/saml/kit/metadata.rb
@@ -179,25 +179,31 @@ module Saml
         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"]
-        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)
+      def signature
+        @signature ||= Signature.new(at_xpath("/md:EntityDescriptor/ds:Signature"))
+      end
+
+      class << self
+        # 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 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
-      end
 
-      # @!visibility private
-      def self.builder_class
-        Saml::Kit::Builders::Metadata
+        # @!visibility private
+        def builder_class
+          Saml::Kit::Builders::Metadata
+        end
       end
 
       private
@@ -208,6 +214,10 @@ module Saml
         @document ||= ::Xml::Kit::Document.new(xml, namespaces: NAMESPACES)
       end
 
+      def at_xpath(xpath)
+        document.find_by(xpath)
+      end
+
       def metadata
         document.find_by("/md:EntityDescriptor/md:#{name}").present?
       end
@@ -221,11 +231,11 @@ module Saml
       end
 
       def must_have_valid_signature
-        return if to_xml.blank?
+        return unless signature.present?
 
-        document.valid?
-        document.errors.each do |attribute, message|
-          errors[attribute] << message
+        signature.valid?
+        signature.errors.each do |attribute, error|
+          errors[attribute] << error
         end
       end
     end
spec/saml/identity_provider_metadata_spec.rb
@@ -112,8 +112,8 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
       subject = described_class.new(metadata_xml)
       expect(subject).to be_invalid
       expect(subject.errors[:base]).to be_empty
-      expect(subject.errors[:digest_value]).to match_array(["is invalid"])
-      expect(subject.errors[:signature]).to match_array(["is invalid"])
+      expect(subject.errors[:digest_value]).to match_array(["is invalid."])
+      expect(subject.errors[:signature]).to match_array(["is invalid."])
     end
   end
 
spec/saml/metadata_spec.rb
@@ -62,4 +62,15 @@ RSpec.describe Saml::Kit::Metadata do
       expect(subject.certificates.count).to eql(1)
     end
   end
+
+  describe "#signature" do
+    it 'returns the signature' do
+      subject = Saml::Kit::Metadata.build do |x|
+        x.sign_with(::Xml::Kit::KeyPair.generate(use: :signing))
+        x.build_identity_provider
+      end
+
+      expect(subject.signature).to be_present
+    end
+  end
 end
spec/saml/service_provider_metadata_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Saml::Kit::ServiceProviderMetadata do
       metadata_xml = service_provider_metadata.gsub(acs_post_url, new_url)
       subject = described_class.new(metadata_xml)
       expect(subject).to be_invalid
-      expect(subject.errors[:digest_value]).to include("is invalid")
+      expect(subject.errors[:digest_value]).to include("is invalid.")
     end
 
     it 'is invalid when 0 ACS endpoints are specified' do