Commit 3b8db92

mo <mo.khan@gmail.com>
2017-11-10 21:29:05
check if request is trusted.
1 parent 20d3189
Changed files (3)
lib/saml/kit/authentication_request.rb
@@ -60,6 +60,12 @@ module Saml
         Response::Builder.new(user, self).build
       end
 
+      def trusted?
+        return false if provider.nil?
+        return false unless signed?
+        provider.matches?(fingerprint, use: :signing)
+      end
+
       private
 
       def registered_acs_url
@@ -82,8 +88,7 @@ module Saml
           errors[:service_provider] << error_message(:unregistered)
           return
         end
-        return if provider.matches?(fingerprint, use: :signing)
-
+        return if trusted?
         errors[:fingerprint] << error_message(:invalid_fingerprint)
       end
 
lib/saml/kit/response.rb
@@ -68,8 +68,8 @@ module Saml
         content
       end
 
-      def encode
-        Base64.strict_encode64(to_xml)
+      def serialize
+        Saml::Kit::Content.encode_raw_saml(to_xml)
       end
 
       def certificate
@@ -97,8 +97,20 @@ module Saml
         Time.current > started_at && !expired?
       end
 
-      def self.deserialize(saml_response)
-        new(Saml::Kit::Content.decode_raw_saml(saml_response))
+      def signed?
+        @xml_hash[name]['Signature'].present?
+      end
+
+      def trusted?
+        return false if provider.nil?
+        return false unless signed?
+        provider.matches?(fingerprint, use: :signing)
+      end
+
+      class << self
+        def deserialize(saml_response)
+          new(Saml::Kit::Content.decode_raw_saml(saml_response))
+        end
       end
 
       private
@@ -129,7 +141,7 @@ module Saml
 
       def must_be_registered
         return unless login_response?
-        return if provider.present? && provider.matches?(fingerprint, use: :signing)
+        return if trusted?
 
         errors[:base] << error_message(:unregistered)
       end
@@ -186,6 +198,7 @@ module Saml
         attr_reader :user, :request
         attr_accessor :id, :reference_id, :now
         attr_accessor :version, :status_code
+        attr_accessor :issuer
 
         def initialize(user, request)
           @user = user
@@ -195,19 +208,20 @@ module Saml
           @now = Time.now.utc
           @version = "2.0"
           @status_code = Namespaces::SUCCESS
+          @issuer = configuration.issuer
         end
 
         def to_xml
           signature = Signature.new(id)
           xml = ::Builder::XmlMarkup.new
           xml.Response response_options do
-            xml.Issuer(configuration.issuer, xmlns: Namespaces::ASSERTION)
+            xml.Issuer(issuer, xmlns: Namespaces::ASSERTION)
             signature.template(xml)
             xml.Status do
               xml.StatusCode Value: status_code
             end
             xml.Assertion(assertion_options) do
-              xml.Issuer configuration.issuer
+              xml.Issuer issuer
               xml.Subject do
                 xml.NameID user.name_id_for(request), Format: request.name_id_format
                 xml.SubjectConfirmation Method: Namespaces::BEARER do
@@ -224,10 +238,13 @@ module Saml
                   xml.AuthnContextClassRef Namespaces::PASSWORD
                 end
               end
-              xml.AttributeStatement do
-                user.assertion_attributes_for(request).each do |key, value|
-                  xml.Attribute Name: key, NameFormat: Namespaces::URI, FriendlyName: key do
-                    xml.AttributeValue value.to_s
+              assertion_attributes = user.assertion_attributes_for(request)
+              if assertion_attributes.any?
+                xml.AttributeStatement do
+                  assertion_attributes.each do |key, value|
+                    xml.Attribute Name: key, NameFormat: Namespaces::URI, FriendlyName: key do
+                      xml.AttributeValue value.to_s
+                    end
                   end
                 end
               end
spec/saml/response_spec.rb
@@ -222,4 +222,20 @@ RSpec.describe Saml::Kit::Response do
       expect(subject.errors[:audience]).to be_present
     end
   end
+
+  describe "#serialize" do
+    let(:user) { double(:user, name_id_for: SecureRandom.uuid, assertion_attributes_for: { }) }
+    let(:request) { double(id: SecureRandom.uuid, acs_url: acs_url, issuer: issuer, name_id_format: Saml::Kit::Namespaces::PERSISTENT) }
+    let(:acs_url) { FFaker::Internet.http_url }
+    let(:issuer) { FFaker::Internet.http_url }
+
+    it 'returns a compressed and base64 encoded document' do
+      builder = described_class::Builder.new(user, request)
+      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