Skip to content

Commit fcee903

Browse files
author
Giuseppe De Marco
authored
Merge pull request #392 from prauscher/issue-391-add-csp
Make sure djangosaml2 works in csp-enabled applications too (fix #391)
2 parents 4cfcc07 + 1ae2905 commit fcee903

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

djangosaml2/views.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,26 @@
7878

7979
logger = logging.getLogger("djangosaml2")
8080

81+
# Update Content-Security-Policy headers for POST-Bindings
82+
try:
83+
from csp.decorators import csp_update
84+
except ModuleNotFoundError:
85+
# If csp is not installed, do not update fields as Content-Security-Policy
86+
# is not used
87+
def saml2_csp_update(view):
88+
return view
89+
90+
logger.warning("django-csp could not be found, not updating Content-Security-Policy. Please "
91+
"make sure CSP is configured at least by httpd or setup django-csp. See "
92+
"https://djangosaml2.readthedocs.io/contents/security.html#content-security-policy"
93+
" for more information")
94+
else:
95+
# script-src 'unsafe-inline' to autosubmit forms,
96+
# form-action https: to send data to IdPs
97+
saml2_csp_update = csp_update(
98+
SCRIPT_SRC=["'unsafe-inline'"], FORM_ACTION=["https:"]
99+
)
100+
81101

82102
def _set_subject_id(session, subject_id):
83103
session["_saml2_subject_id"] = code(subject_id)
@@ -123,6 +143,7 @@ def get_state_client(self, request: HttpRequest):
123143
return state, client
124144

125145

146+
@method_decorator(saml2_csp_update, name='dispatch')
126147
class LoginView(SPConfigMixin, View):
127148
"""SAML Authorization Request initiator.
128149
@@ -671,6 +692,7 @@ def get(self, request, *args, **kwargs):
671692
)
672693

673694

695+
@method_decorator(saml2_csp_update, name='dispatch')
674696
class LogoutInitView(LoginRequiredMixin, SPConfigMixin, View):
675697
"""SAML Logout Request initiator
676698
@@ -749,7 +771,7 @@ def handle_unsupported_slo_exception(self, request, exception, *args, **kwargs):
749771
return HttpResponseRedirect(getattr(settings, "LOGOUT_REDIRECT_URL", "/"))
750772

751773

752-
@method_decorator(csrf_exempt, name="dispatch")
774+
@method_decorator([saml2_csp_update, csrf_exempt], name="dispatch")
753775
class LogoutView(SPConfigMixin, View):
754776
"""SAML Logout Response endpoint
755777

docs/source/contents/security.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Introduction
2+
============
3+
4+
Authentication and Authorization are quite security relevant topics on its own.
5+
Make sure you understand SAML2 and its implications, specifically the
6+
separation of duties between Service Provider (SP) and Identity Provider (IdP):
7+
this library aims to support a Service Provider in getting authenticated with
8+
with one or more Identity Provider.
9+
10+
Communication between SP and IdP is routed via the Browser, eliminating the
11+
need for direct communication between SP and IdP. However, for security the use
12+
of cryptographic signatures (both while sending and receiving messages) must be
13+
examined and the private keys in use must be kept closely guarded.
14+
15+
Content Security Policy
16+
=======================
17+
18+
When using POST-Bindings, the Browser is presented with a small HTML-Form for
19+
every redirect (both Login and Logout), which is sent using JavaScript and
20+
sends the Data to the selected IdP. If your application uses technices such as
21+
Content Security Policy, this might affect the calls. Since Version 1.9.0
22+
djangosaml2 will detect if django-csp is installed and update the Content
23+
Security Policy accordingly.
24+
25+
[Content Security Policy](https://content-security-policy.com/) is an important
26+
HTTP-Extension to prevent User Input or other harmful sources from manipulating
27+
application data. Usage is strongly advised, see
28+
[OWASP Control](https://owasp.org/www-community/controls/Content_Security_Policy).
29+
30+
To enable CSP with [django-csp](https://django-csp.readthedocs.io/), simply
31+
follow their [installation](https://django-csp.readthedocs.io/en/latest/installation.html)
32+
and [configuration](https://django-csp.readthedocs.io/en/latest/configuration.html)
33+
guides: djangosaml2 will automatically blend in and update the headers for
34+
POST-bindings, so you must not include exceptions for djangosaml2 in your
35+
global configuration.

docs/source/index.rst

+6
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ under the `Apache 2.0 <https://en.wikipedia.org/wiki/Apache_License>`_.
4141
:caption: FAQ
4242

4343
contents/faq.md
44+
45+
.. toctree::
46+
:maxdepth: 2
47+
:caption: Security considerations
48+
49+
contents/security.md

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def read(*rnames):
2727

2828
setup(
2929
name="djangosaml2",
30-
version="1.8.0",
30+
version="1.9.0",
3131
description="pysaml2 integration for Django",
3232
long_description=read("README.md"),
3333
long_description_content_type="text/markdown",

0 commit comments

Comments
 (0)