Commit 73608e4

mo <mo.khan@gmail.com>
2017-11-10 20:40:35
allow idp metadata to generate auth request.
1 parent 7223baf
lib/saml/kit/authentication_request.rb
@@ -44,10 +44,18 @@ module Saml
         Fingerprint.new(certificate)
       end
 
+      def signed?
+        @hash[name]['Signature'].present?
+      end
+
       def to_xml
         @content
       end
 
+      def serialize
+        Saml::Kit::Content.encode_raw_saml(to_xml)
+      end
+
       def response_for(user)
         Response::Builder.new(user, self).build
       end
@@ -106,22 +114,24 @@ module Saml
 
       class Builder
         attr_accessor :id, :issued_at, :issuer, :acs_url, :name_id_format
+        attr_reader :sign
 
-        def initialize(configuration = Saml::Kit.configuration)
+        def initialize(configuration = Saml::Kit.configuration, sign: true)
           @id = SecureRandom.uuid
           @issued_at = Time.now.utc
           @issuer = configuration.issuer
           @name_id_format = Namespaces::PERSISTENT
+          @sign = sign
         end
 
-        def to_xml(xml = ::Builder::XmlMarkup.new)
-          signature = Signature.new(id)
-          xml.tag!('samlp:AuthnRequest', request_options) do
-            xml.tag!('saml:Issuer', issuer)
-            signature.template(xml)
-            xml.tag!('samlp:NameIDPolicy', Format: name_id_format)
+        def to_xml
+          Signature.sign(id, sign: sign) do |xml, signature|
+            xml.tag!('samlp:AuthnRequest', request_options) do
+              xml.tag!('saml:Issuer', issuer)
+              signature.template(xml)
+              xml.tag!('samlp:NameIDPolicy', Format: name_id_format)
+            end
           end
-          signature.finalize(xml)
         end
 
         def build
lib/saml/kit/identity_provider_metadata.rb
@@ -39,7 +39,11 @@ module Saml
         end
       end
 
-      private
+      def build_authentication_request
+        builder = AuthenticationRequest::Builder.new(sign: want_authn_requests_signed)
+        yield builder if block_given?
+        builder.build
+      end
 
       class Builder
         attr_accessor :id, :organization_name, :organization_url, :contact_email, :entity_id, :attributes, :name_id_formats
lib/saml/kit/signature.rb
@@ -59,8 +59,7 @@ module Saml
         end
       end
 
-      def self.sign(id, sign: true)
-        xml = ::Builder::XmlMarkup.new
+      def self.sign(id, sign: true, xml: ::Builder::XmlMarkup.new)
         signature = new(id, sign: sign)
         yield xml, signature
         signature.finalize(xml)
spec/saml/authentication_request_spec.rb
@@ -173,4 +173,15 @@ RSpec.describe Saml::Kit::AuthenticationRequest do
       expect(subject.acs_url).to eql(acs_url)
     end
   end
+
+  describe "#serialize" do
+    it 'returns a compressed and base64 encoded document' do
+      builder = described_class::Builder.new
+      xml = builder.to_xml
+      subject = described_class.new(xml)
+
+      expected_value = Base64.encode64(Zlib::Deflate.deflate(xml, 9)).gsub(/\n/, '')
+      expect(subject.serialize).to eql(expected_value)
+    end
+  end
 end
spec/saml/identity_provider_metadata_spec.rb
@@ -246,7 +246,7 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
   end
 
   describe "#want_authn_requests_signed" do
-    let(:builder) { Saml::Kit::IdentityProviderMetadata::Builder.new }
+    let(:builder) { described_class::Builder.new }
 
     it 'returns true when enabled' do
       builder.want_authn_requests_signed = true
@@ -267,4 +267,22 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
       expect(subject.want_authn_requests_signed).to be(true)
     end
   end
+
+  describe "#build_authentication_request" do
+    let(:builder) { described_class::Builder.new }
+
+    it 'it signs the authentication request when the idp metadata demands it' do
+      builder.want_authn_requests_signed = true
+      subject = builder.build
+
+      expect(subject.build_authentication_request).to be_signed
+    end
+
+    it 'does not sign the authentication request when the idp does not require it' do
+      builder.want_authn_requests_signed = false
+      subject = builder.build
+
+      expect(subject.build_authentication_request).to_not be_signed
+    end
+  end
 end