Repository: goauthentik/authentik

Issue:
Add WantAuthnRequestsSigned Parameter to SAML Metadata Endpoint for Improved Integration with Spring Boot SAML Library
**Is your feature request related to a problem? Please describe.**
Yes, I consistently encounter an issue when integrating with the Spring Boot SAML Library. When the **WantAuthnRequestsSigned** parameter is missing in the SAML metadata endpoint within the XML file, the authentication page displays the message: "Verification Certificate configured, but request is not signed."

**Describe the solution you'd like**
I would like the **WantAuthnRequestsSigned="true"** parameter to be added to the XML file in the SAML metadata endpoint for the element **<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">**.

**Describe alternatives you've considered**
A potential alternative would be to modify the Spring Boot SAML Library to function even without the **WantAuthnRequestsSigned** parameter. However, this could lead to security concerns and is not the recommended approach.

**Additional context**
Adding this parameter is crucial for the correct functioning of authentication and the security of the system. It would be highly beneficial if this parameter were included in the XML file by default to prevent future integration issues.


Discussion:
![image](https://github.com/goauthentik/authentik/assets/28624736/d1732fc4-8c79-449e-8407-636089379192)


Resolving patch:
diff --git a/authentik/providers/saml/processors/metadata.py b/authentik/providers/saml/processors/metadata.py
--- a/authentik/providers/saml/processors/metadata.py
+++ b/authentik/providers/saml/processors/metadata.py
@@ -171,6 +171,8 @@ def build_entity_descriptor(self) -> str:
             entity_descriptor, f"{{{NS_SAML_METADATA}}}IDPSSODescriptor"
         )
         idp_sso_descriptor.attrib["protocolSupportEnumeration"] = NS_SAML_PROTOCOL
+        if self.provider.verification_kp:
+            idp_sso_descriptor.attrib["WantAuthnRequestsSigned"] = "true"
 
         signing_descriptor = self.get_signing_key_descriptor()
         if signing_descriptor is not None:


Test patch:
diff --git a/authentik/providers/saml/tests/test_metadata.py b/authentik/providers/saml/tests/test_metadata.py
--- a/authentik/providers/saml/tests/test_metadata.py
+++ b/authentik/providers/saml/tests/test_metadata.py
@@ -12,7 +12,7 @@
 from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
 from authentik.providers.saml.processors.metadata import MetadataProcessor
 from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
-from authentik.sources.saml.processors.constants import NS_MAP
+from authentik.sources.saml.processors.constants import NS_MAP, NS_SAML_METADATA
 
 
 class TestServiceProviderMetadataParser(TestCase):
@@ -55,6 +55,24 @@ def test_schema(self):
         schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd"))  # nosec
         self.assertTrue(schema.validate(metadata))
 
+    def test_schema_want_authn_requests_signed(self):
+        """Test metadata generation with WantAuthnRequestsSigned"""
+        cert = create_test_cert()
+        provider = SAMLProvider.objects.create(
+            name=generate_id(),
+            authorization_flow=self.flow,
+            verification_kp=cert,
+        )
+        Application.objects.create(
+            name=generate_id(),
+            slug=generate_id(),
+            provider=provider,
+        )
+        request = self.factory.get("/")
+        metadata = lxml_from_string(MetadataProcessor(provider, request).build_entity_descriptor())
+        idp_sso_descriptor = metadata.findall(f"{{{NS_SAML_METADATA}}}IDPSSODescriptor")[0]
+        self.assertEqual(idp_sso_descriptor.attrib["WantAuthnRequestsSigned"], "true")
+
     def test_simple(self):
         """Test simple metadata without Signing"""
         metadata = ServiceProviderMetadataParser().parse(load_fixture("fixtures/simple.xml"))