Skip to content

Commit

Permalink
Merge pull request #392 from prauscher/issue-391-add-csp
Browse files Browse the repository at this point in the history
Make sure djangosaml2 works in csp-enabled applications too (fix #391)
  • Loading branch information
Giuseppe De Marco authored Dec 27, 2023
2 parents 4cfcc07 + 1ae2905 commit fcee903
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
24 changes: 23 additions & 1 deletion djangosaml2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@

logger = logging.getLogger("djangosaml2")

# 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

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
saml2_csp_update = csp_update(
SCRIPT_SRC=["'unsafe-inline'"], FORM_ACTION=["https:"]
)


def _set_subject_id(session, subject_id):
session["_saml2_subject_id"] = code(subject_id)
Expand Down Expand Up @@ -123,6 +143,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.
Expand Down Expand Up @@ -671,6 +692,7 @@ def get(self, request, *args, **kwargs):
)


@method_decorator(saml2_csp_update, name='dispatch')
class LogoutInitView(LoginRequiredMixin, SPConfigMixin, View):
"""SAML Logout Request initiator
Expand Down Expand Up @@ -749,7 +771,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
Expand Down
35 changes: 35 additions & 0 deletions docs/source/contents/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Introduction
============

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
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
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.
6 changes: 6 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,9 @@ under the `Apache 2.0 <https://en.wikipedia.org/wiki/Apache_License>`_.
:caption: FAQ

contents/faq.md

.. toctree::
:maxdepth: 2
:caption: Security considerations

contents/security.md
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit fcee903

Please sign in to comment.