Commit dd7fe18

mo <mo.khan@gmail.com>
2017-11-10 18:29:48
allow skipping signature.
1 parent 8897ee9
lib/saml/kit/service_provider_metadata.rb
@@ -17,7 +17,7 @@ module Saml
       private
 
       class Builder
-        attr_accessor :id, :entity_id, :acs_urls, :logout_urls, :name_id_formats
+        attr_accessor :id, :entity_id, :acs_urls, :logout_urls, :name_id_formats, :sign
 
         def initialize(configuration = Saml::Kit.configuration)
           @id = SecureRandom.uuid
@@ -26,6 +26,7 @@ module Saml
           @acs_urls = []
           @logout_urls = []
           @name_id_formats = [Namespaces::PERSISTENT]
+          @sign = true
         end
 
         def add_assertion_consumer_service(url, binding: :post)
@@ -37,31 +38,32 @@ module Saml
         end
 
         def to_xml
-          signature = Signature.new(id)
-          xml = ::Builder::XmlMarkup.new
-          xml.instruct!
-          xml.EntityDescriptor entity_descriptor_options do
-            signature.template(xml)
-            xml.SPSSODescriptor descriptor_options do
-              xml.KeyDescriptor use: "signing" do
-                xml.KeyInfo "xmlns": Namespaces::XMLDSIG do
-                  xml.X509Data do
-                    xml.X509Certificate @configuration.stripped_signing_certificate
+          Signature.sign(id, sign: sign) do |xml, signature|
+            xml.instruct!
+            xml.EntityDescriptor entity_descriptor_options do
+              signature.template(xml)
+              xml.SPSSODescriptor descriptor_options do
+                if @configuration.signing_certificate_pem.present?
+                  xml.KeyDescriptor use: "signing" do
+                    xml.KeyInfo "xmlns": Namespaces::XMLDSIG do
+                      xml.X509Data do
+                        xml.X509Certificate @configuration.stripped_signing_certificate
+                      end
+                    end
                   end
                 end
-              end
-              logout_urls.each do |item|
-                xml.SingleLogoutService Binding: item[:binding], Location: item[:location]
-              end
-              name_id_formats.each do |format|
-                xml.NameIDFormat format
-              end
-              acs_urls.each_with_index do |item, index|
-                xml.AssertionConsumerService Binding: item[:binding], Location: item[:location], index: index, isDefault: index == 0 ? true : false
+                logout_urls.each do |item|
+                  xml.SingleLogoutService Binding: item[:binding], Location: item[:location]
+                end
+                name_id_formats.each do |format|
+                  xml.NameIDFormat format
+                end
+                acs_urls.each_with_index do |item, index|
+                  xml.AssertionConsumerService Binding: item[:binding], Location: item[:location], index: index, isDefault: index == 0 ? true : false
+                end
               end
             end
           end
-          signature.finalize(xml)
         end
 
         def build
lib/saml/kit/signature.rb
@@ -16,14 +16,16 @@ module Saml
         SHA512: "http://www.w3.org/2001/04/xmlenc#sha512",
       }.freeze
 
-      attr_reader :configuration, :reference_id
+      attr_reader :configuration, :reference_id, :sign
 
-      def initialize(reference_id, configuration = Saml::Kit.configuration)
+      def initialize(reference_id, configuration: Saml::Kit.configuration, sign: true)
         @reference_id = reference_id
         @configuration = configuration
+        @sign = sign
       end
 
       def template(xml = ::Builder::XmlMarkup.new)
+        return unless sign
         return if reference_id.blank?
 
         xml.Signature "xmlns" => Namespaces::XMLDSIG do
@@ -49,13 +51,20 @@ module Saml
       end
 
       def finalize(xml)
-        if reference_id.present?
+        if sign && reference_id.present?
           document = Xmldsig::SignedDocument.new(xml.target!)
           document.sign(configuration.signing_private_key)
         else
           xml.target!
         end
       end
+
+      def self.sign(id, sign: true)
+        xml = ::Builder::XmlMarkup.new
+        signature = new(id, sign: sign)
+        yield xml, signature
+        signature.finalize(xml)
+      end
     end
   end
 end
spec/saml/signature_spec.rb
@@ -1,7 +1,7 @@
 require "spec_helper"
 
 RSpec.describe Saml::Kit::Signature do
-  subject { described_class.new(reference_id, configuration) }
+  subject { described_class.new(reference_id, configuration: configuration) }
   let(:configuration) do
     config = Saml::Kit::Configuration.new
     config.signing_certificate_pem = certificate
@@ -61,4 +61,16 @@ RSpec.describe Saml::Kit::Signature do
     expect(signature['SignatureValue']).to be_present
     expect(OpenSSL::X509::Certificate.new(Base64.decode64(signature['KeyInfo']['X509Data']['X509Certificate']))).to be_present
   end
+
+  it 'does not add a signature' do
+    subject = described_class.new(reference_id, sign: false, configuration: configuration)
+    xml = ::Builder::XmlMarkup.new
+    xml.AuthnRequest do
+      subject.template(xml)
+      xml.Issuer "MyEntityID"
+    end
+    result = Hash.from_xml(subject.finalize(xml))
+    expect(result['AuthnRequest']).to be_present
+    expect(result["AuthnRequest"]["Signature"]).to be_nil
+  end
 end