Skip to main content

django-modern-csrf

PyPI version PyPI Supported Python Versions tests codecov

Django modern CSRF protection using Fetch metadata request headers, without tokens, cookies or custom headers. No more CSRF token errors, csrf_token in your templates or configuring frontend clients to deal with X-CSRFToken.

Rationale

Django's default CSRF protection relies on tokens and cookies. While this works well and is secure, there are more modern ways to protect against CSRF attacks, without requiring to submit CSRF tokens to the server via forms, cookies or custom headers. Fetch metadata request headers provide a way to protect against CSRF attacks without requiring token verifications. The Sec-Fetch-Site in particular, tells the server whether the request is same origin, cross-origin, same site or user initiated. With that information, the server can decide whether to allow the request or not.

To learn more about Fetch metadata request headers and how they can be used for web security, check out this article by Google.

According to Can I Use, the Sec-Fetch-Site header is supported by 97.63% and Origin by 99.83% of all tracked browsers.

Installation

This package is designed to require minimal changes to your existing Django project.

  1. Install the package:
pip install django-modern-csrf
  1. Add modern_csrf to your INSTALLED_APPS:
# settings.py

INSTALLED_APPS = [
    ...
    "modern_csrf",
    ...
]
  1. Replace the default CSRF middleware with the new one (in the same position):
# settings.py

# Old
MIDDLEWARE = [
    ...
    "django.middleware.csrf.CsrfViewMiddleware",
    ...
]

# New
MIDDLEWARE = [
    ...
    "modern_csrf.middleware.ModernCsrfViewMiddleware",
    ...
]
  1. That should be it for most projects. However, if you are using the @csrf_protect decorator, you will need to replace it with this package's @csrf_protect.
# Old
from django.views.decorators.csrf import csrf_protect

# Replace with
from modern_csrf.decorators import csrf_protect
  1. That's it! You can remove all references to {% csrf_token %} or {{ csrf_token }} from your templates. You can also remove any code in your JavaScript clients that sets the X-CSRFToken header, as there are no more token checks in place. Enjoy your tokenless CSRF protection!

Implementation

The implementation for this package is based on the Go standard library's protection against CSRF attacks. The implementation can be seen here, along with the research by the author who implemented it.

The ModernCsrfViewMiddleware is a drop-in replacement for the default CsrfViewMiddleware that uses the Sec-Fetch-Site header to determine whether to allow the request or not. Below is a description of how it works:

  1. Skip CSRF protection if the view is explicitly marked as CSRF-exempt.

  2. Allow all GET, HEAD, OPTIONS, or TRACE requests.

    These are safe methods as defined by RFC 9110, and are assumed not to change state.

  3. If the Sec-Fetch-Site header is present:

    • if its value is same-origin or none, allow the request;
    • otherwise, check if the Origin header is verified against trusted origins (Django's CSRF_TRUSTED_ORIGINS);
    • if the Origin is verified, allow the request;
    • otherwise, reject the request.

    This leverages modern browser security headers to detect cross-origin requests. The Sec-Fetch-Site header is automatically sent by modern browsers and provides reliable origin information.

  4. If the Origin header is present but doesn't match any trusted origin, reject the request.

    This catches cross-origin requests from browsers that don't support Sec-Fetch-Site but do send Origin headers.

  5. If neither the Sec-Fetch-Site nor the Origin headers triggered a rejection, allow the request.

    This is the default fallback for requests that don't present obvious cross-origin indicators. Those requests are most likely from command line tools or other non-browser clients.

Origin verification checks three conditions:

  • (1) the Origin matches the current request's origin (scheme + host + port if present),
  • (2) the Origin is in the CSRF_TRUSTED_ORIGINS allow-list as an exact match,
  • (3) the Origin's domain is a subdomain of an allowed wildcard entry in CSRF_TRUSTED_ORIGINS.

This approach prioritizes the Sec-Fetch-Site header, which provides the most reliable protection for modern browsers, while maintaining backward compatibility through Origin header validation. The algorithm has no false negatives in browsers that support Sec-Fetch-Site (all major browsers since 2020), and degrades gracefully for older browsers.

Acknowledgements

Thanks to Filippo Valsorda for the research and implementation of Go's CrossOriginProtection which this package is based on.

Metadata

Release files for django-modern-csrf 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-modern-csrf 1.0.1
File Size Uploaded
django_modern_csrf-1.0.1.tar.gz 5.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-modern-csrf 1.0.1
File Interpreter ABI Platform
django_modern_csrf-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 12.2 kB

Release files / django_modern_csrf-1.0.1.tar.gz

Download URL django_modern_csrf-1.0.1.tar.gz
Size 5.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6d13bf8eb887457f676d6f70987e9670353ef495e81d695d27c26e71e727a7f7
BLAKE2b-256 checksum
How to use checksums
84f6bb760a2b01f77f3b4004578f69787267e113c8bae19ff3af647724df852f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.5

Release files / django_modern_csrf-1.0.1-py3-none-any.whl

Download URL django_modern_csrf-1.0.1-py3-none-any.whl
Size 6.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fce69521d2a832a6f3243fc5985cbd61a925fc782e7308e0f3b9ad0b4d219e11
BLAKE2b-256 checksum
How to use checksums
6f3e7aedb5a679da43ac01e421956b45bf97d3d7f48db30c55f093c0a28ddb64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.5

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page