Secure ASGI Apps with Double Submit CSRF Middleware
Protect ASGI apps from CSRF using asgi-csrf: pip install, wrap app with CSRFMiddleware, embed scope['csrftoken']() in POST forms or x-csrftoken headers—rejects invalid POSTs with 403.
Embed CSRF Tokens in Forms for Double Submit Protection
Wrap your ASGI app with CSRFMiddleware(app, signing_secret="your-secret") to implement OWASP's Double Submit Cookie pattern. The middleware sets a csrftoken cookie (configurable via cookie_name) if missing and exposes it via scope["csrftoken"]()—a callable function. Use it to populate hidden form fields: <input type="hidden" name="csrftoken" value="{{ request.scope['csrftoken']() }}">. For JS fetches, send x-csrftoken header matching the cookie. On POST, middleware validates token in form data or header, rejecting mismatches with 403. Set signing_secret explicitly or via ASGI_CSRF_SECRET env var to avoid invalidation on restarts—random secrets persist only per server run. Adds Vary: Cookie header if setting cookie to bust caches.
Configure Cookies and Auto-Set Behavior
Control cookie with options: cookie_path="/" (default), cookie_domain=None, cookie_secure=True (HTTPS-only), cookie_samesite="Lax" (default; options: Strict, Lax, None). Use always_set_cookie=True to set csrftoken on every request lacking it, not just when scope["csrftoken"]() called. Skips protection if no cookies (unauthenticated) or Authorization: Bearer ... header present (safe from cross-site due to browser CORS). Protect login forms always via always_protect=["/login/"] to block login CSRF.
Skip APIs and Customize Failures
Opt out for web APIs with skip_if_scope callback returning True, e.g., lambda scope: scope["path"].startswith("/api/"). Override 403 defaults with send_csrf_failed function taking scope, send, and message_id from asgi_csrf.Errors enum for custom responses per error type.