Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions csp/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class CSPMiddleware(MiddlewareMixin):
Can be customised by subclassing and extending the get_policy_parts method.
"""

always_generate_nonce = False

def _make_nonce(self, request: HttpRequest) -> str:
# Ensure that any subsequent calls to request.csp_nonce return the same value
stored_nonce = getattr(request, "_csp_nonce", None)
Expand All @@ -71,8 +69,6 @@ def _csp_nonce_post_response() -> None:
def process_request(self, request: HttpRequest) -> None:
nonce = partial(self._make_nonce, request)
setattr(request, "csp_nonce", CheckableLazyObject(nonce))
if self.always_generate_nonce:
str(getattr(request, "csp_nonce"))

def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase:
# Check for debug view
Expand Down Expand Up @@ -143,17 +139,3 @@ def get_policy_parts(
nonce = getattr(request, "_csp_nonce", None)

return PolicyParts(config, update, replace, nonce)


class CSPMiddlewareAlwaysGenerateNonce(CSPMiddleware):
"""
A middleware variant that always generates a nonce.

This is useful when a later process needs a nonce, whether or not the wrapped
request uses a nonce. One example is django-debug-toolbar (DDT). The DDT
middleware needs to be high in the MIDDLEWARE list, so it can inject its
HTML, CSS, and JS describing the response generation. DDT users can use
this middleware instead of CSPMiddleware.
"""

always_generate_nonce = True
47 changes: 1 addition & 46 deletions csp/tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@

from csp.constants import HEADER, HEADER_REPORT_ONLY, SELF
from csp.exceptions import CSPNonceError
from csp.middleware import (
CheckableLazyObject,
CSPMiddleware,
CSPMiddlewareAlwaysGenerateNonce,
)
from csp.middleware import CheckableLazyObject, CSPMiddleware
from csp.tests.utils import response

mw = CSPMiddleware(response())
Expand Down Expand Up @@ -291,44 +287,3 @@ def test_set_nonce_access_after_middleware_is_ok() -> None:
mw.process_response(request, HttpResponse())
assert bool(getattr(request, "csp_nonce", False)) is True
assert str(getattr(request, "csp_nonce")) == nonce


def test_csp_always_nonce_middleware_has_nonce() -> None:
request = rf.get("/")
mw_agn = CSPMiddlewareAlwaysGenerateNonce(response())
mw_agn.process_request(request)
nonce = getattr(request, "csp_nonce")
assert bool(nonce) is True
resp = HttpResponse()
mw_agn.process_response(request, resp)
assert str(nonce) in resp[HEADER]


def test_csp_always_nonce_middleware_nonce_regenerated_on_new_request() -> None:
mw_agn = CSPMiddlewareAlwaysGenerateNonce(response())
request1 = rf.get("/")
request2 = rf.get("/")
mw_agn.process_request(request1)
mw_agn.process_request(request2)
nonce1 = str(getattr(request1, "csp_nonce"))
nonce2 = str(getattr(request2, "csp_nonce"))
assert nonce1 != nonce2

response1 = HttpResponse()
response2 = HttpResponse()
mw_agn.process_response(request1, response1)
mw_agn.process_response(request2, response2)
assert nonce1 not in response2[HEADER]
assert nonce2 not in response1[HEADER]


def test_csp_always_nonce_middleware_access_after_middleware_is_ok() -> None:
# Test accessing a set nonce after the response has been processed is OK.
request = rf.get("/")
mw_agn = CSPMiddlewareAlwaysGenerateNonce(response())
mw_agn.process_request(request)
nonce = getattr(request, "csp_nonce")
assert bool(nonce) is True
mw_agn.process_response(request, HttpResponse())
assert bool(nonce) is True
assert str(getattr(request, "csp_nonce")) == nonce
2 changes: 0 additions & 2 deletions docs/nonce.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ If other middleware or a later process needs to access ``request.csp_nonce``, th

* The middleware can be placed after ``csp.middleware.CSPMiddleware`` in the ``MIDDLEWARE`` setting.
This ensures that the middleware generates the nonce before ``CSPMiddleware`` writes the CSP header.
* Use the alternate ``csp.middleware.CSPMiddlewareAlwaysGenerateNonce`` middleware, which always
generates a nonce and includes it in the CSP header.
* Add a later middleware that accesses the nonce. For example, this function:

.. code-block:: python
Expand Down