main
 1# frozen_string_literal: true
 2
 3module Saml
 4  module Kit
 5    # This class is responsible for validating and
 6    # parsing a SAML Response document.
 7    # {include:file:spec/examples/response_spec.rb}
 8    class Response < Document
 9      include Respondable
10      extend Forwardable
11
12      def_delegators :assertion, :name_id, :[], :attributes
13
14      validate :must_be_valid_assertion
15      validate :must_contain_single_assertion
16
17      def initialize(
18        xml,
19        request_id: nil,
20        configuration: Saml::Kit.configuration
21      )
22        @request_id = request_id
23        super(xml, name: 'Response', configuration: configuration)
24      end
25
26      def assertion(private_keys = configuration.private_keys(use: :encryption))
27        @assertion ||=
28          begin
29            node = assertion_nodes.last
30            if node.nil?
31              Saml::Kit::NullAssertion.new
32            else
33              Saml::Kit::Assertion.new(
34                node,
35                configuration: @configuration,
36                private_keys: private_keys
37              )
38            end
39          end
40      end
41
42      private
43
44      def must_be_valid_assertion
45        assertion.valid?
46        assertion.each_error do |attribute, error|
47          errors.add(attribute == :base ? :assertion : attribute, error)
48        end
49      end
50
51      def must_contain_single_assertion
52        return if assertion_nodes.count <= 1
53
54        errors.add(:base, error_message(:must_contain_single_assertion))
55      end
56
57      def assertion_nodes
58        search(Saml::Kit::Assertion::XPATH)
59      end
60    end
61  end
62end