Internal
Public Access
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>
62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
"""
|
|
Middleware to allow iframe embedding for the KeepItGoing mobile app.
|
|
|
|
The mobile app uses Capacitor WebView which embeds the website in an iframe.
|
|
This middleware detects requests from the mobile app and removes both
|
|
X-Frame-Options and Content-Security-Policy frame-ancestors headers to allow
|
|
iframe embedding, while keeping clickjacking protection for regular web browsers.
|
|
"""
|
|
|
|
|
|
class AllowMobileAppFramingMiddleware:
|
|
"""
|
|
Remove frame-blocking headers for requests from KeepItGoing mobile app.
|
|
|
|
The mobile app uses a Capacitor WebView. We detect these requests via
|
|
User-Agent and remove X-Frame-Options and CSP frame-ancestors headers.
|
|
"""
|
|
|
|
def __init__(self, get_response):
|
|
self.get_response = get_response
|
|
|
|
def __call__(self, request):
|
|
response = self.get_response(request)
|
|
|
|
# Check if request is from KeepItGoing mobile app
|
|
user_agent = request.META.get('HTTP_USER_AGENT', '')
|
|
|
|
# Detect Capacitor/Android WebView patterns
|
|
is_mobile_app = (
|
|
'wv' in user_agent.lower() or # Android WebView
|
|
'CapacitorHttp' in user_agent or
|
|
'com.firebugit.keepitgoing' in user_agent or
|
|
('KeepItGoing' in user_agent and 'Mobile' in user_agent)
|
|
)
|
|
|
|
if is_mobile_app:
|
|
# Mobile app: Allow iframe embedding - don't add frame-blocking headers
|
|
# Remove any existing frame headers
|
|
if 'X-Frame-Options' in response:
|
|
del response['X-Frame-Options']
|
|
if 'Content-Security-Policy' in response:
|
|
del response['Content-Security-Policy']
|
|
else:
|
|
# Regular browsers: Add security headers for clickjacking protection
|
|
if 'X-Frame-Options' not in response:
|
|
response['X-Frame-Options'] = 'DENY'
|
|
|
|
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
|