Files
GNX-mailEnterprise/venv/lib/python3.12/site-packages/allauth/socialaccount/providers/saml/utils.py
Iliyan Angelov c67067a2a4 Mail
2025-09-14 23:24:25 +03:00

142 lines
5.2 KiB
Python

from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.urls import reverse
from onelogin.saml2.constants import OneLogin_Saml2_Constants
from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
from allauth.socialaccount.adapter import get_adapter
from allauth.socialaccount.models import SocialApp
from .provider import SAMLProvider
def get_app_or_404(request, organization_slug):
adapter = get_adapter()
try:
return adapter.get_app(
request, provider=SAMLProvider.id, client_id=organization_slug
)
except SocialApp.DoesNotExist:
raise Http404(f"no SocialApp found with client_id={organization_slug}")
def prepare_django_request(request):
result = {
"https": "on" if request.is_secure() else "off",
"http_host": request.META["HTTP_HOST"],
"script_name": request.META["PATH_INFO"],
"get_data": request.GET.copy(),
# 'lowercase_urlencoding': True,
"post_data": request.POST.copy(),
}
return result
def build_sp_config(request, provider_config, org):
acs_url = request.build_absolute_uri(reverse("saml_acs", args=[org]))
sls_url = request.build_absolute_uri(reverse("saml_sls", args=[org]))
metadata_url = request.build_absolute_uri(reverse("saml_metadata", args=[org]))
sp_config = {
"entityId": metadata_url,
"assertionConsumerService": {
"url": acs_url,
"binding": OneLogin_Saml2_Constants.BINDING_HTTP_POST,
},
"singleLogoutService": {
"url": sls_url,
"binding": OneLogin_Saml2_Constants.BINDING_HTTP_REDIRECT,
},
}
avd = provider_config.get("advanced", {})
if avd.get("x509cert") is not None:
sp_config["x509cert"] = avd["x509cert"]
if avd.get("x509cert_new"):
sp_config["x509certNew"] = avd["x509cert_new"]
if avd.get("private_key") is not None:
sp_config["privateKey"] = avd["private_key"]
if avd.get("name_id_format") is not None:
sp_config["NameIDFormat"] = avd["name_id_format"]
return sp_config
def fetch_metadata_url_config(idp_config):
metadata_url = idp_config["metadata_url"]
entity_id = idp_config["entity_id"]
cache_key = f"saml.metadata.{metadata_url}.{entity_id}"
saml_config = cache.get(cache_key)
if saml_config is None:
saml_config = OneLogin_Saml2_IdPMetadataParser.parse_remote(
metadata_url,
entity_id=entity_id,
timeout=idp_config.get("metadata_request_timeout", 10),
)
cache.set(
cache_key,
saml_config,
idp_config.get("metadata_cache_timeout", 60 * 60 * 4),
)
return saml_config
def build_saml_config(request, provider_config, org):
avd = provider_config.get("advanced", {})
security_config = {
"authnRequestsSigned": avd.get("authn_request_signed", False),
"digestAlgorithm": avd.get("digest_algorithm", OneLogin_Saml2_Constants.SHA256),
"logoutRequestSigned": avd.get("logout_request_signed", False),
"logoutResponseSigned": avd.get("logout_response_signed", False),
"requestedAuthnContext": False,
"signatureAlgorithm": avd.get(
"signature_algorithm", OneLogin_Saml2_Constants.RSA_SHA256
),
"signMetadata": avd.get("metadata_signed", False),
"wantAssertionsEncrypted": avd.get("want_assertion_encrypted", False),
"wantAssertionsSigned": avd.get("want_assertion_signed", False),
"wantMessagesSigned": avd.get("want_message_signed", False),
"nameIdEncrypted": avd.get("name_id_encrypted", False),
"wantNameIdEncrypted": avd.get("want_name_id_encrypted", False),
"allowSingleLabelDomains": avd.get("allow_single_label_domains", False),
"rejectDeprecatedAlgorithm": avd.get("reject_deprecated_algorithm", True),
"wantNameId": avd.get("want_name_id", False),
"wantAttributeStatement": avd.get("want_attribute_statement", True),
"allowRepeatAttributeName": avd.get("allow_repeat_attribute_name", True),
}
saml_config = {
"strict": avd.get("strict", True),
"security": security_config,
}
contact_person = provider_config.get("contact_person")
if contact_person:
saml_config["contactPerson"] = contact_person
organization = provider_config.get("organization")
if organization:
saml_config["organization"] = organization
idp = provider_config.get("idp")
if idp is None:
raise ImproperlyConfigured("`idp` missing")
metadata_url = idp.get("metadata_url")
if metadata_url:
meta_config = fetch_metadata_url_config(idp)
saml_config["idp"] = meta_config["idp"]
else:
saml_config["idp"] = {
"entityId": idp["entity_id"],
"x509cert": idp["x509cert"],
"singleSignOnService": {"url": idp["sso_url"]},
}
slo_url = idp.get("slo_url")
if slo_url:
saml_config["idp"]["singleLogoutService"] = {"url": slo_url}
saml_config["sp"] = build_sp_config(request, provider_config, org)
return saml_config