Exercise 3: Why JSON Doesn't Bypass CSRF — Possible Solution ==================================================================== WHY CSRF STILL APPLIES ------------------------------ Django's CSRF protection is tied to the request being a same-origin, session-authenticated browser request making an unsafe method call (POST, PUT, DELETE, etc.) - it has nothing to do with whether the request body happens to be form-encoded data or JSON. Switching the scan flow from a template form submission to a fetch() call against a DRF endpoint changes how the request is constructed and sent, but it's still the same browser, still using the same session-based authentication, still making the same kind of unsafe request - none of the actual conditions that CSRF protection cares about have changed. WHAT HAPPENS IF THE CSRF TOKEN IS LEFT OUT OF THE fetch() CALL ------------------------------ The request gets rejected with the same 403 Forbidden response Chapter 6 already covered for a missing {% csrf_token %} in a template form - Django's CSRF middleware doesn't distinguish between a rejected template form submission and a rejected fetch() call; it applies the identical check regardless of which one sent the request. The token needs to be read (commonly from a cookie or a hidden value) and explicitly included in the fetch() call's own headers for the request to succeed. WHY THIS WORKS AS AN ANSWER ------------------------------ It correctly explains that CSRF protection depends on the nature of the request (same-origin, session-authenticated, unsafe method) rather than its content-type or transport mechanism, and correctly describes the resulting 403 rejection if the token is omitted from the fetch() call, exactly mirroring Chapter 6's own template-form gotcha.