| 124 | return False |
| 125 | |
| 126 | async def dispatch(self, request: Request, call_next: Callable) -> Response: |
| 127 | # Only check state-changing methods |
| 128 | if request.method not in STATE_CHANGING_METHODS: |
| 129 | return await call_next(request) |
| 130 | |
| 131 | # Skip CSRF for requests using explicit auth (not cookie-based) |
| 132 | if self._is_csrf_exempt(request): |
| 133 | return await call_next(request) |
| 134 | |
| 135 | # Get origin and referer headers |
| 136 | origin = request.headers.get("origin") |
| 137 | referer = request.headers.get("referer") |
| 138 | |
| 139 | # Validate origin |
| 140 | if not self.is_allowed_origin(origin, referer): |
| 141 | return JSONResponse( |
| 142 | status_code=403, |
| 143 | content={ |
| 144 | "detail": "CSRF validation failed: Origin not allowed" |
| 145 | } |
| 146 | ) |
| 147 | |
| 148 | return await call_next(request) |