Update middleware to ADD security headers for browsers

Middleware now:
- Detects mobile app vs browser via User-Agent
- Mobile app: Removes frame-blocking headers (allows iframe)
- Browsers: Adds CSP and X-Frame-Options headers (security)

This ensures:
✓ Browsers get full CSP protection
✓ Mobile app can embed content
✓ No need for django-csp package
✓ All security managed in one place

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Keith Smith
2025-12-26 22:29:00 -07:00
co-authored by Claude Sonnet 4.5
parent c686021f96
commit 123d6af430
+20 -11
View File
@@ -26,7 +26,6 @@ class AllowMobileAppFramingMiddleware:
user_agent = request.META.get('HTTP_USER_AGENT', '') user_agent = request.META.get('HTTP_USER_AGENT', '')
# Detect Capacitor/Android WebView patterns # Detect Capacitor/Android WebView patterns
# Note: We're being permissive here to catch all mobile app requests
is_mobile_app = ( is_mobile_app = (
'wv' in user_agent.lower() or # Android WebView 'wv' in user_agent.lower() or # Android WebView
'CapacitorHttp' in user_agent or 'CapacitorHttp' in user_agent or
@@ -34,19 +33,29 @@ class AllowMobileAppFramingMiddleware:
('KeepItGoing' in user_agent and 'Mobile' in user_agent) ('KeepItGoing' in user_agent and 'Mobile' in user_agent)
) )
# Remove frame-blocking headers for mobile app requests
if is_mobile_app: if is_mobile_app:
# Remove X-Frame-Options # Mobile app: Allow iframe embedding - don't add frame-blocking headers
# Remove any existing frame headers
if 'X-Frame-Options' in response: if 'X-Frame-Options' in response:
del response['X-Frame-Options'] del response['X-Frame-Options']
# Remove or modify Content-Security-Policy
if 'Content-Security-Policy' in response: if 'Content-Security-Policy' in response:
csp = response['Content-Security-Policy'] del response['Content-Security-Policy']
# Remove frame-ancestors directive else:
if 'frame-ancestors' in csp: # Regular browsers: Add security headers for clickjacking protection
# Remove the entire CSP header for simplicity if 'X-Frame-Options' not in response:
# In production, you'd want to parse and modify it properly response['X-Frame-Options'] = 'DENY'
del response['Content-Security-Policy']
if 'Content-Security-Policy' not in response:
response['Content-Security-Policy'] = (
"default-src 'self'; "
"script-src 'self' 'unsafe-inline'; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data: https:; "
"font-src 'self' data:; "
"connect-src 'self'; "
"frame-ancestors 'none'; "
"base-uri 'self'; "
"form-action 'self';"
)
return response return response