Security and Authentication
This project provides a robust security and authentication framework centered around middleware, cryptographic signing, and a flexible user authentication system. These components work together to protect against common web vulnerabilities while providing a consistent API for managing user sessions.
User Authentication
The core authentication logic resides in django.contrib.auth. It decouples the verification of credentials from the management of user sessions, allowing for both synchronous and asynchronous workflows.
Authentication and Session Management
The framework provides three primary functions for handling users, located in django/contrib/auth/__init__.py:
authenticate(request=None, **credentials): Verifies credentials against a list of configured backends (defined insettings.AUTHENTICATION_BACKENDS). If valid, it returns a user object annotated with the backend used.login(request, user, backend=None): Persists a user's ID in the session using theSESSION_KEY(_auth_user_id). It also handles session rotation viarotate_token(request)to prevent session fixation attacks.logout(request): Completely clears the session data and removes the authenticated user's ID from the request.
For asynchronous environments, the framework provides aauthenticate(), alogin(), and alogout(). These functions utilize asgiref.sync.sync_to_async or native async implementations to avoid blocking the event loop.
Authentication Backends
Authentication is extensible through backends. The _get_backends() function in django/contrib/auth/__init__.py loads the classes specified in settings.AUTHENTICATION_BACKENDS. By default, this typically includes django.contrib.auth.backends.ModelBackend.
Built-in Views
The django.contrib.auth.views module provides standard implementations for common tasks. For example, LoginView (a subclass of FormView) handles the login logic:
# django/contrib/auth/views.py
class LoginView(RedirectURLMixin, FormView):
# ...
def form_valid(self, form):
"""Security check complete. Log the user in."""
auth_login(self.request, form.get_user())
return HttpResponseRedirect(self.get_success_url())
CSRF Protection
The CsrfViewMiddleware in django/middleware/csrf.py provides protection against Cross-Site Request Forgery. It ensures that "unsafe" HTTP methods (POST, PUT, DELETE, PATCH) contain a valid CSRF token that matches the secret stored in the user's cookie or session.
How it Works
- Token Generation: The
get_token(request)function generates a masked CSRF secret. - Validation: For non-safe methods,
process_viewcalls_check_token(request). This compares the token provided in the request (either inPOSTdata ascsrfmiddlewaretokenor in theX-CSRFTokenheader) against thecsrf_secretretrieved via_get_secret(request). - Strict Referer Checking: For HTTPS requests, the middleware performs strict referer checking in
_check_referer(request)to ensure the request originated from a trusted domain.
Configuration
CSRF_USE_SESSIONS: IfTrue, the CSRF secret is stored inrequest.sessionunder the_csrftokenkey instead of a cookie. This requiresSessionMiddlewareto be placed beforeCsrfViewMiddleware.CSRF_TRUSTED_ORIGINS: A list of hosts trusted for cross-site unsafe requests. The middleware uses_origin_verified(request)to validate theHTTP_ORIGINheader against this list.
Cryptographic Signing
The django.core.signing module provides a way to generate URL-safe signed JSON objects. This is used to protect data sent to untrusted environments (like a user's browser) from tampering.
Signer and TimestampSigner
The Signer class uses HMAC with SHA-256 (by default) to sign values.
# django/core/signing.py usage example
from django.core import signing
signer = signing.Signer()
value = signer.sign('hello')
# Result: 'hello:signature'
TimestampSigner extends Signer by appending a base62-encoded timestamp to the value. This allows for expiring signatures using the max_age parameter in unsign():
# django/core/signing.py
class TimestampSigner(Signer):
def unsign(self, value, max_age=None):
# ... checks if (current_time - timestamp) > max_age
High-level API
The dumps() and loads() functions provide a high-level interface for signing complex objects. They use a JSONSerializer to convert objects to strings before signing and support optional compression via zlib.
Security Middleware
The SecurityMiddleware in django/middleware/security.py implements several HTTP-level security enhancements based on project settings:
- SSL Redirection: If
SECURE_SSL_REDIRECTis enabled, it redirects all non-HTTPS requests to HTTPS. - HSTS: Sets the
Strict-Transport-Securityheader ifSECURE_HSTS_SECONDSis configured. - Content-Type Sniffing: Sets
X-Content-Type-Options: nosniffifSECURE_CONTENT_TYPE_NOSNIFFisTrue. - Referrer Policy: Sets the
Referrer-Policyheader based onSECURE_REFERRER_POLICY.
Additionally, XFrameOptionsMiddleware (in django/middleware/clickjacking.py) sets the X-Frame-Options header to prevent clickjacking attacks, defaulting to the value in settings.X_FRAME_OPTIONS (usually SAMEORIGIN).
Key Security Settings
| Setting | Description |
|---|---|
SECRET_KEY | Used for all cryptographic signing and CSRF secret generation. |
AUTHENTICATION_BACKENDS | Defines the classes used to verify user credentials. |
AUTH_USER_MODEL | The model used to represent users (retrieved via get_user_model()). |
CSRF_COOKIE_HTTPONLY | Whether the CSRF cookie should be accessible via JavaScript. |
SECURE_HSTS_SECONDS | Duration for the HSTS header. |
X_FRAME_OPTIONS | Controls whether the site can be embedded in an iframe. |