Commit 7223baf

mo <mo.khan@gmail.com>
2017-11-10 20:21:38
parse WantAuthnRequestsSigned
1 parent 94d278f
lib/saml/kit/identity_provider_metadata.rb
@@ -5,10 +5,20 @@ module Saml
         super("IDPSSODescriptor", xml)
       end
 
+      def want_authn_requests_signed
+        xpath = "/md:EntityDescriptor/md:#{name}"
+        attribute = find_by(xpath).attribute("WantAuthnRequestsSigned")
+        return true if attribute.nil?
+        attribute.text.downcase == "true"
+      end
+
       def single_sign_on_services
         xpath = "/md:EntityDescriptor/md:#{name}/md:SingleSignOnService"
         find_all(xpath).map do |item|
-          { binding: item.attribute("Binding").value, location: item.attribute("Location").value }
+          {
+            binding: item.attribute("Binding").value,
+            location: item.attribute("Location").value,
+          }
         end
       end
 
@@ -33,6 +43,7 @@ module Saml
 
       class Builder
         attr_accessor :id, :organization_name, :organization_url, :contact_email, :entity_id, :attributes, :name_id_formats
+        attr_accessor :want_authn_requests_signed
         attr_reader :logout_urls, :single_sign_on_urls
 
         def initialize(configuration = Saml::Kit.configuration)
@@ -43,6 +54,7 @@ module Saml
           @single_sign_on_urls = []
           @logout_urls = []
           @configuration = configuration
+          @want_authn_requests_signed = true
         end
 
         def add_single_sign_on_service(url, binding: :post)
@@ -59,7 +71,7 @@ module Saml
           xml.instruct!
           xml.EntityDescriptor entity_descriptor_options do
             signature.template(xml)
-            xml.IDPSSODescriptor protocolSupportEnumeration: Namespaces::PROTOCOL do
+            xml.IDPSSODescriptor idp_sso_descriptor_options do
               xml.KeyDescriptor use: "signing" do
                 xml.KeyInfo "xmlns": Namespaces::XMLDSIG do
                   xml.X509Data do
@@ -107,6 +119,13 @@ module Saml
             entityID: entity_id,
           }
         end
+
+        def idp_sso_descriptor_options
+          {
+            protocolSupportEnumeration: Namespaces::PROTOCOL,
+            WantAuthnRequestsSigned: want_authn_requests_signed
+          }
+        end
       end
     end
   end
spec/saml/identity_provider_metadata_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
       expect(result['EntityDescriptor']['ID']).to be_present
       expect(result['EntityDescriptor']['entityID']).to eql(entity_id)
       expect(result['EntityDescriptor']['IDPSSODescriptor']['protocolSupportEnumeration']).to eql('urn:oasis:names:tc:SAML:2.0:protocol')
+      expect(result['EntityDescriptor']['IDPSSODescriptor']['WantAuthnRequestsSigned']).to eql('true')
       expect(result['EntityDescriptor']['IDPSSODescriptor']['NameIDFormat']).to match_array([
         Saml::Kit::Namespaces::PERSISTENT,
         Saml::Kit::Namespaces::TRANSIENT,
@@ -243,4 +244,27 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
       expect(subject.single_sign_on_service_for(binding: :soap)).to be_nil
     end
   end
+
+  describe "#want_authn_requests_signed" do
+    let(:builder) { Saml::Kit::IdentityProviderMetadata::Builder.new }
+
+    it 'returns true when enabled' do
+      builder.want_authn_requests_signed = true
+      subject = builder.build
+      expect(subject.want_authn_requests_signed).to be(true)
+    end
+
+    it 'returns false when disabled' do
+      builder.want_authn_requests_signed = false
+      subject = builder.build
+      expect(subject.want_authn_requests_signed).to be(false)
+    end
+
+    it 'returns true when the attribute is missing' do
+      builder.want_authn_requests_signed = false
+      xml = builder.to_xml.gsub("WantAuthnRequestsSigned=\"false\"", "")
+      subject = described_class.new(xml)
+      expect(subject.want_authn_requests_signed).to be(true)
+    end
+  end
 end