providers/saml: add ?force_binding to limit bindings for metadata endpoint

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-12-05 11:14:42 +01:00
parent 2b78c4ba86
commit 6a3f7e45cf
3 changed files with 29 additions and 2 deletions

View File

@ -36,6 +36,7 @@ from authentik.flows.models import Flow, FlowDesignation
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor from authentik.providers.saml.processors.metadata import MetadataProcessor
from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
from authentik.sources.saml.processors.constants import SAML_BINDING_POST, SAML_BINDING_REDIRECT
LOGGER = get_logger() LOGGER = get_logger()
@ -109,7 +110,19 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet):
name="download", name="download",
location=OpenApiParameter.QUERY, location=OpenApiParameter.QUERY,
type=OpenApiTypes.BOOL, type=OpenApiTypes.BOOL,
),
OpenApiParameter(
name="force_binding",
location=OpenApiParameter.QUERY,
type=OpenApiTypes.STR,
enum=[
SAML_BINDING_REDIRECT,
SAML_BINDING_POST,
],
description=(
"Optionally force the metadata to only include one binding."
) )
),
], ],
) )
@action(methods=["GET"], detail=True, permission_classes=[AllowAny]) @action(methods=["GET"], detail=True, permission_classes=[AllowAny])
@ -122,7 +135,9 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet):
except ValueError: except ValueError:
raise Http404 raise Http404
try: try:
metadata = MetadataProcessor(provider, request).build_entity_descriptor() proc = MetadataProcessor(provider, request)
proc.force_binding = request.query_params.get("force_binding", None)
metadata = proc.build_entity_descriptor()
if "download" in request.query_params: if "download" in request.query_params:
response = HttpResponse(metadata, content_type="application/xml") response = HttpResponse(metadata, content_type="application/xml")
response[ response[

View File

@ -29,10 +29,12 @@ class MetadataProcessor:
provider: SAMLProvider provider: SAMLProvider
http_request: HttpRequest http_request: HttpRequest
force_binding: Optional[str]
def __init__(self, provider: SAMLProvider, request: HttpRequest): def __init__(self, provider: SAMLProvider, request: HttpRequest):
self.provider = provider self.provider = provider
self.http_request = request self.http_request = request
self.force_binding = None
self.xml_id = get_random_id() self.xml_id = get_random_id()
def get_signing_key_descriptor(self) -> Optional[Element]: def get_signing_key_descriptor(self) -> Optional[Element]:
@ -79,6 +81,8 @@ class MetadataProcessor:
), ),
} }
for binding, url in binding_url_map.items(): for binding, url in binding_url_map.items():
if self.force_binding and self.force_binding != binding:
continue
element = Element(f"{{{NS_SAML_METADATA}}}SingleSignOnService") element = Element(f"{{{NS_SAML_METADATA}}}SingleSignOnService")
element.attrib["Binding"] = binding element.attrib["Binding"] = binding
element.attrib["Location"] = url element.attrib["Location"] = url

View File

@ -11645,6 +11645,14 @@ paths:
name: download name: download
schema: schema:
type: boolean type: boolean
- in: query
name: force_binding
schema:
type: string
enum:
- urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
- urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
description: Optionally force the metadata to only include one binding.
- in: path - in: path
name: id name: id
schema: schema: