Commit 6707168

mo <mo@mokhan.ca>
2018-03-03 03:02:36
begin work to support building a response without a request.
1 parent 94554ea
Changed files (5)
lib/saml/kit/builders/templates/assertion.builder
@@ -9,9 +9,11 @@ xml.Assertion(assertion_options) do
       xml.SubjectConfirmationData '', subject_confirmation_data_options
     end
   end
-  xml.Conditions conditions_options do
-    xml.AudienceRestriction do
-      xml.Audience request.issuer
+  if request.present?
+    xml.Conditions conditions_options do
+      xml.AudienceRestriction do
+        xml.Audience request.issuer
+      end
     end
   end
   xml.AuthnStatement authn_statement_options do
lib/saml/kit/builders/assertion.rb
@@ -16,7 +16,7 @@ module Saml
         end
 
         def name_id_format
-          request.name_id_format
+          request.try(:name_id_format) || Saml::Kit::Namespaces::PERSISTENT
         end
 
         def name_id
@@ -43,11 +43,12 @@ module Saml
         end
 
         def subject_confirmation_data_options
-          {
-            InResponseTo: request.id,
+          options = {
             NotOnOrAfter: 3.hours.since(now).utc.iso8601,
             Recipient: destination,
           }
+          options[:InResponseTo] = request.id if request.present?
+          options
         end
 
         def conditions_options
lib/saml/kit/builders/response.rb
@@ -13,7 +13,7 @@ module Saml
         attr_accessor :issuer, :destination
         attr_reader :configuration
 
-        def initialize(user, request, configuration: Saml::Kit.configuration)
+        def initialize(user, request = nil, configuration: Saml::Kit.configuration)
           @user = user
           @request = request
           @id = ::Xml::Kit::Id.generate
@@ -28,7 +28,7 @@ module Saml
         end
 
         def build
-          Saml::Kit::Response.new(to_xml, request_id: request.id, configuration: configuration)
+          Saml::Kit::Response.new(to_xml, request_id: request.try(:id), configuration: configuration)
         end
 
         def assertion
@@ -46,15 +46,16 @@ module Saml
         private
 
         def response_options
-          {
+          options = {
             ID: id,
             Version: version,
             IssueInstant: now.iso8601,
             Destination: destination,
             Consent: Namespaces::UNSPECIFIED,
-            InResponseTo: request.id,
             xmlns: Namespaces::PROTOCOL,
           }
+          options[:InResponseTo] = request.id if request.present?
+          options
         end
       end
     end
lib/saml/kit/assertion.rb
@@ -109,6 +109,7 @@ module Saml
       end
 
       def must_match_issuer
+        return if audiences.empty?
         return if audiences.include?(configuration.entity_id)
         errors[:audience] << error_message(:must_match_issuer)
       end
spec/saml/kit/response_spec.rb
@@ -555,4 +555,22 @@ XML
       expect(subject.attributes).to eql('name' => 'mo', 'age' => '33')
     end
   end
+
+  describe "#build" do
+    it 'can build a response without a request' do
+      configuration = Saml::Kit::Configuration.new do |config|
+        config.entity_id = FFaker::Internet.uri("https")
+      end
+      sp = Saml::Kit::Metadata.build do |x|
+        x.build_service_provider
+      end
+      allow(configuration.registry).to receive(:metadata_for).with(configuration.entity_id).and_return(sp)
+      result = described_class.build(user, configuration: configuration)
+      expect(result).to be_instance_of(described_class)
+      puts result.valid?
+      puts result.errors.full_messages.inspect
+      puts result.to_xml(pretty: true)
+      expect(result).to be_valid
+    end
+  end
 end