Missing Authentication in Django with Mutual Tls
Missing Authentication in Django with Mutual Tls — how this specific combination creates or exposes the vulnerability
Mutual Transport Layer Security (mTLS) requires both the client and the server to present valid certificates during the TLS handshake. In Django, developers often assume that mTLS alone is sufficient for strong access control. This can create a false sense of security because mTLS handles identity verification at the transport layer, but it does not automatically map a verified client certificate to an authenticated user or permission inside the application.
When authentication checks are missing or incomplete at the Django view or middleware layer, an endpoint that relies on mTLS can still be accessed by any client that possesses a trusted certificate. middleBrick’s Authentication check flags this as a risk because the unauthenticated attack surface remains exposed: the API does not enforce token-based or session-based authentication on top of mTLS. For example, if a view does not verify request.user or use Django’s permission decorators, any mTLS‑enabled client can read, modify, or delete resources.
Consider a Django endpoint that returns sensitive billing data:
from django.http import JsonResponse
from django.views import View
class BillingView(View):
def get(self, request):
# WARNING: No check for request.user or token validation
return JsonResponse({
'balance': 1234.56,
'currency': 'USD'
})
Even if mTLS is enforced at the load balancer or reverse proxy, this view is vulnerable because it does not validate that the request originates from an authenticated and authorized user. An attacker with a valid client certificate can call this endpoint directly and exfiltrate data. The combination of mTLS and missing Django-level authentication is especially dangerous because developers may believe the transport-layer check is enough, while the API’s unauthenticated surface remains wide open.
middleBrick’s BOLA/IDOR and Authentication checks are designed to detect these gaps by sending unauthenticated requests and analyzing whether endpoints rely solely on mTLS. Findings include missing decorators like @login_required, absence of token validation, or improper permission classes in viewsets. Remediation requires explicit authentication enforcement in Django, as detailed in the next section.
Mutual Tls-Specific Remediation in Django — concrete code fixes
To secure Django endpoints when mTLS is in use, you must enforce authentication and authorization at the application layer. mTLS can be used to extract client certificate details, but Django still needs to map those details to users and apply proper permissions.
1. Use mTLS to extract client identity and enforce login_required
Configure your web server (e.g., Nginx) to require client certificates and pass selected certificate fields to Django via headers. Then use a middleware or decorator to ensure the request is authenticated.
from django.contrib.auth.decorators import login_required
@login_required
def sensitive_view(request):
return JsonResponse({'message': 'Authenticated access'})
2. Middleware to map certificate to Django user
Create a middleware that reads the client certificate information from HTTP headers (set by your proxy) and authenticates the user in Django:
import json
from django.contrib.auth import authenticate, login
from django.utils.deprecation import MiddlewareMixin
class MutualTlsAuthMiddleware(MiddlewareMixin):
def process_request(self, request):
# Headers set by the reverse proxy when mTLS is terminated upstream
cert_subject = request.META.get('SSL_CLIENT_S_DN_CN')
cert_serial = request.META.get('SSL_CLIENT_SERIAL')
if cert_subject and cert_serial:
# Map certificate fields to a Django user
user = authenticate(request, cert_subject=cert_subject, cert_serial=cert_serial)
if user:
login(request, user)
else:
# Optionally reject request if mTLS is required
pass
3. Token-based enforcement for API views
For REST APIs, combine mTLS with token authentication. Validate that a valid token is present even when mTLS provides transport-layer identity:
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class SecureApiView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({'data': 'protected'})
4. Apply permission classes and ownership checks
Use Django REST Framework’s permission classes and object-level permissions to prevent BOLA/IDOR. Do not rely on mTLS to decide whether a user can access a specific resource:
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
class AccountDetail(generics.RetrieveUpdateAPIView):
queryset = Account.objects.all()
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
5. Validate and log mTLS details for audit
Even with mTLS, log certificate metadata to support monitoring and incident response. Do not treat mTLS as a replacement for audit trails:
import logging
logger = logging.getLogger(__name__)
class AuditMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
cert_fingerprint = request.META.get('SSL_CLIENT_CERT_FINGERPRINT')
if cert_fingerprint:
logger.info('mTLS cert used', extra={'fingerprint': cert_fingerprint})
return response
By layering explicit authentication, permission checks, and audit logging on top of mTLS, you eliminate the unauthenticated attack surface while retaining the security benefits of mutual TLS. middleBrick’s scans can verify that these controls are present and correctly enforced.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |