From 60b0bc78343ac164910d814fc8a1c91c5e815320 Mon Sep 17 00:00:00 2001 From: "Gabriel Y. Salem" Date: Tue, 13 May 2025 10:52:39 -0400 Subject: [PATCH 1/3] Add django-csp 4.0 compatibility (#415) --- djangosaml2/utils.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/djangosaml2/utils.py b/djangosaml2/utils.py index 3426ec1..02876ed 100644 --- a/djangosaml2/utils.py +++ b/djangosaml2/utils.py @@ -239,6 +239,7 @@ def _django_csp_update_decorator(): """Returns a view CSP decorator if django-csp is available, otherwise None.""" try: from csp.decorators import csp_update + import csp except ModuleNotFoundError: # If csp is not installed, do not update fields as Content-Security-Policy # is not used @@ -254,4 +255,29 @@ def _django_csp_update_decorator(): else: # autosubmit of forms uses nonce per default # form-action https: to send data to IdPs - return csp_update(FORM_ACTION=["https:"]) + + # Check django-csp version to determine the appropriate format + try: + version = getattr(csp, "__version__", "0.0") + major_version = int(version.split(".")[0]) + + # Version detection successful + if major_version >= 4: + # django-csp 4.0+ uses dict format with named 'config' parameter + return csp_update(config={"form-action": ["https:"]}) + else: + # django-csp < 4.0 uses kwargs format + return csp_update(FORM_ACTION=["https:"]) + except (AttributeError, ValueError, IndexError): + # Version detection failed, we need to try both formats + + # Try v4.0+ style first because: + # 1. It has better error handling with clear messages + # 2. Newer versions are more likely to be supported in the future + # 3. If using kwargs with v4.0, it raises a specific RuntimeError we can catch + try: + return csp_update(config={"form-action": ["https:"]}) + except (TypeError, RuntimeError): + # TypeErrors could happen if config is not a recognized parameter (v3.x) + # RuntimeErrors could happen in v4.0+ if we try the wrong approach + return csp_update(FORM_ACTION=["https:"]) From e6157cb639231959f280d5ae62e8847b44a9ff84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Rodr=C3=ADguez=20Texidor?= Date: Tue, 13 May 2025 17:26:18 -0300 Subject: [PATCH 2/3] utils.py: update CSP handling for django-csp version compatibility --- djangosaml2/utils.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/djangosaml2/utils.py b/djangosaml2/utils.py index 3426ec1..7820f54 100644 --- a/djangosaml2/utils.py +++ b/djangosaml2/utils.py @@ -18,6 +18,7 @@ import zlib from functools import lru_cache, wraps from typing import Optional +import importlib.metadata from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -254,4 +255,14 @@ def _django_csp_update_decorator(): else: # autosubmit of forms uses nonce per default # form-action https: to send data to IdPs - return csp_update(FORM_ACTION=["https:"]) + try: + csp_version = importlib.metadata.version("django-csp") + except importlib.metadata.PackageNotFoundError: + csp_version = "0" + + major_version = int(csp_version.split(".")[0]) + + if major_version >= 4: + return csp_update({"form-action": ["https:"]}) + else: + return csp_update(FORM_ACTION=["https:"]) From 7398c26fe1b02f6a4c107dd50ed801c7fcab0967 Mon Sep 17 00:00:00 2001 From: "Gabriel Y. Salem" Date: Wed, 14 May 2025 10:58:09 -0400 Subject: [PATCH 3/3] Fix csp version detection --- djangosaml2/utils.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/djangosaml2/utils.py b/djangosaml2/utils.py index 02876ed..10d022d 100644 --- a/djangosaml2/utils.py +++ b/djangosaml2/utils.py @@ -18,6 +18,7 @@ import zlib from functools import lru_cache, wraps from typing import Optional +from importlib.metadata import version, PackageNotFoundError from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -255,22 +256,19 @@ def _django_csp_update_decorator(): else: # autosubmit of forms uses nonce per default # form-action https: to send data to IdPs - # Check django-csp version to determine the appropriate format try: - version = getattr(csp, "__version__", "0.0") - major_version = int(version.split(".")[0]) - + csp_version = version('django-csp') + major_version = int(csp_version.split('.')[0]) + # Version detection successful if major_version >= 4: # django-csp 4.0+ uses dict format with named 'config' parameter return csp_update(config={"form-action": ["https:"]}) - else: - # django-csp < 4.0 uses kwargs format - return csp_update(FORM_ACTION=["https:"]) - except (AttributeError, ValueError, IndexError): + # django-csp < 4.0 uses kwargs format + return csp_update(FORM_ACTION=["https:"]) + except (PackageNotFoundError, ValueError, RuntimeError, AttributeError, IndexError): # Version detection failed, we need to try both formats - # Try v4.0+ style first because: # 1. It has better error handling with clear messages # 2. Newer versions are more likely to be supported in the future