From 93b7c09abd704bac49fb7f70e36709a7cf84ede0 Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Thu, 21 Dec 2023 23:00:21 +0000 Subject: [PATCH 1/6] Make sure djangosaml2 works in csp-enabled applications too (fix #391) --- djangosaml2/views.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/djangosaml2/views.py b/djangosaml2/views.py index 9b2d9e93..1a6107d8 100644 --- a/djangosaml2/views.py +++ b/djangosaml2/views.py @@ -75,6 +75,21 @@ validate_referral_url, ) +# Update Content-Security-Policy headers for POST-Bindings +try: + from csp.decorators import csp_update +except ModuleNotFoundError: + # If csp is not installed, do not update fields as Content-Security-Policy + # is not used + def saml2_csp_update(view): + return view +else: + # script-src 'unsafe-inline' to autosubmit forms, + # form-action https: to send data to IdPs + saml2_csp_update = csp_update( + SCRIPT_SRC=["'unsafe-inline'"], FORM_ACTION=["https:"] + ) + logger = logging.getLogger("djangosaml2") @@ -109,6 +124,7 @@ def get_state_client(self, request: HttpRequest): return state, client +@method_decorator(saml2_csp_update, name='dispatch') class LoginView(SPConfigMixin, View): """SAML Authorization Request initiator. @@ -636,6 +652,7 @@ def get(self, request, *args, **kwargs): ) +@method_decorator(saml2_csp_update, name='dispatch') class LogoutInitView(LoginRequiredMixin, SPConfigMixin, View): """SAML Logout Request initiator @@ -714,7 +731,7 @@ def handle_unsupported_slo_exception(self, request, exception, *args, **kwargs): return HttpResponseRedirect(getattr(settings, "LOGOUT_REDIRECT_URL", "/")) -@method_decorator(csrf_exempt, name="dispatch") +@method_decorator([saml2_csp_update, csrf_exempt], name="dispatch") class LogoutView(SPConfigMixin, View): """SAML Logout Response endpoint From decef2f3b18c1297ad8e43d3c98b0e54e08beb97 Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Fri, 22 Dec 2023 11:06:38 +0000 Subject: [PATCH 2/6] Bump version to 1.9.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index db40249c..2e16f8fd 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def read(*rnames): setup( name="djangosaml2", - version="1.8.0", + version="1.9.0", description="pysaml2 integration for Django", long_description=read("README.md"), long_description_content_type="text/markdown", From 8f545f1b7e0951b3c42be480f3c3ecc6d4e083da Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Fri, 22 Dec 2023 11:30:13 +0000 Subject: [PATCH 3/6] add draft for security considerations --- docs/source/contents/security.md | 20 ++++++++++++++++++++ docs/source/index.rst | 6 ++++++ 2 files changed, 26 insertions(+) create mode 100644 docs/source/contents/security.md diff --git a/docs/source/contents/security.md b/docs/source/contents/security.md new file mode 100644 index 00000000..1a66d470 --- /dev/null +++ b/docs/source/contents/security.md @@ -0,0 +1,20 @@ +Security considerations +======================= + +Authentication and Authorization are quite security relevant topics on its own. +Make sure you understand SAML2 and its implications, specifically the +separation of duties between Service Provider (SP) and Identity Provider (IdP): +This Library aims to support a Service Provider in running Authentication +against one or more IdP. + +Communication between SP and IdP is routed via the Browser, eliminating the +need for direct communication between SP and IdP. However, for security the use +of cryptographic signatures (both while sending and receiving messages) must be +examined and the private keys in use must be kept closely guarded. + +When using POST-Bindings, the Browser is presented with a small HTML-Form for +every redirect (both Login and Logout), which is sent using JavaScript and +sends the Data to the selected IdP. If your application uses technices such as +Content Security Policy, this might affect the calls. Since Version 1.9.0 +djangosaml2 will detect if django-csp is installed and update the Content +Security Policy accordingly. diff --git a/docs/source/index.rst b/docs/source/index.rst index df441c40..4868dcda 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -41,3 +41,9 @@ under the `Apache 2.0 `_. :caption: FAQ contents/faq.md + +.. toctree:: + :maxdepth: 2 + :caption: Security considerations + + contents/security.md \ No newline at end of file From 933ab51624519087c63c4950f855a58b727abac8 Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Wed, 27 Dec 2023 16:40:50 +0100 Subject: [PATCH 4/6] Update docs/source/contents/security.md Co-authored-by: Giuseppe De Marco --- docs/source/contents/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contents/security.md b/docs/source/contents/security.md index 1a66d470..e512d84c 100644 --- a/docs/source/contents/security.md +++ b/docs/source/contents/security.md @@ -4,7 +4,7 @@ Security considerations Authentication and Authorization are quite security relevant topics on its own. Make sure you understand SAML2 and its implications, specifically the separation of duties between Service Provider (SP) and Identity Provider (IdP): -This Library aims to support a Service Provider in running Authentication +this library aims to support a Service Provider in getting authenticated with against one or more IdP. Communication between SP and IdP is routed via the Browser, eliminating the From 0b33457ef98f1e2f0147a7174263cfb3b8097315 Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Wed, 27 Dec 2023 16:40:56 +0100 Subject: [PATCH 5/6] Update docs/source/contents/security.md Co-authored-by: Giuseppe De Marco --- docs/source/contents/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contents/security.md b/docs/source/contents/security.md index e512d84c..8cce6936 100644 --- a/docs/source/contents/security.md +++ b/docs/source/contents/security.md @@ -5,7 +5,7 @@ Authentication and Authorization are quite security relevant topics on its own. Make sure you understand SAML2 and its implications, specifically the separation of duties between Service Provider (SP) and Identity Provider (IdP): this library aims to support a Service Provider in getting authenticated with -against one or more IdP. +with one or more Identity Provider. Communication between SP and IdP is routed via the Browser, eliminating the need for direct communication between SP and IdP. However, for security the use From 1ae29057d44a8fae9e6d9858c978b9f45a3ec458 Mon Sep 17 00:00:00 2001 From: Patrick Rauscher Date: Tue, 26 Dec 2023 10:35:55 +0000 Subject: [PATCH 6/6] Add warning and documentation iff django-csp can not be found --- djangosaml2/views.py | 9 +++++++-- docs/source/contents/security.md | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/djangosaml2/views.py b/djangosaml2/views.py index 506fe52b..fb199b0a 100644 --- a/djangosaml2/views.py +++ b/djangosaml2/views.py @@ -76,6 +76,8 @@ validate_referral_url, ) +logger = logging.getLogger("djangosaml2") + # Update Content-Security-Policy headers for POST-Bindings try: from csp.decorators import csp_update @@ -84,6 +86,11 @@ # is not used def saml2_csp_update(view): return view + + logger.warning("django-csp could not be found, not updating Content-Security-Policy. Please " + "make sure CSP is configured at least by httpd or setup django-csp. See " + "https://djangosaml2.readthedocs.io/contents/security.html#content-security-policy" + " for more information") else: # script-src 'unsafe-inline' to autosubmit forms, # form-action https: to send data to IdPs @@ -91,8 +98,6 @@ def saml2_csp_update(view): SCRIPT_SRC=["'unsafe-inline'"], FORM_ACTION=["https:"] ) -logger = logging.getLogger("djangosaml2") - def _set_subject_id(session, subject_id): session["_saml2_subject_id"] = code(subject_id) diff --git a/docs/source/contents/security.md b/docs/source/contents/security.md index 8cce6936..4ccd6cab 100644 --- a/docs/source/contents/security.md +++ b/docs/source/contents/security.md @@ -1,5 +1,5 @@ -Security considerations -======================= +Introduction +============ Authentication and Authorization are quite security relevant topics on its own. Make sure you understand SAML2 and its implications, specifically the @@ -12,9 +12,24 @@ need for direct communication between SP and IdP. However, for security the use of cryptographic signatures (both while sending and receiving messages) must be examined and the private keys in use must be kept closely guarded. +Content Security Policy +======================= + When using POST-Bindings, the Browser is presented with a small HTML-Form for every redirect (both Login and Logout), which is sent using JavaScript and sends the Data to the selected IdP. If your application uses technices such as Content Security Policy, this might affect the calls. Since Version 1.9.0 djangosaml2 will detect if django-csp is installed and update the Content Security Policy accordingly. + +[Content Security Policy](https://content-security-policy.com/) is an important +HTTP-Extension to prevent User Input or other harmful sources from manipulating +application data. Usage is strongly advised, see +[OWASP Control](https://owasp.org/www-community/controls/Content_Security_Policy). + +To enable CSP with [django-csp](https://django-csp.readthedocs.io/), simply +follow their [installation](https://django-csp.readthedocs.io/en/latest/installation.html) +and [configuration](https://django-csp.readthedocs.io/en/latest/configuration.html) +guides: djangosaml2 will automatically blend in and update the headers for +POST-bindings, so you must not include exceptions for djangosaml2 in your +global configuration.