I am implementing an API that works either with an API key, or with a CSRF token. The goal is for it to be usable either by a web app (protected by CSRF) or by a third party app
I've been accessing the CsrfViewMiddleware
like Aldarund has shown but more needs to be said about this kind of solution:
If you are performing the test in a view, then you can return reason
directly. According to how Django middleware works, when process_view
returns something else than None
, then it must be a HttpResponse
object so it can just be returned by the view.
There may be cases where you do not want to return reason
directly, but if there is no reason not to do so, I'd rather return it, for consistency with how the site behaves in other cases.
If you use the test in a run-of-the-mill view, and you already use CsrfViewMiddleware
site-wide, it is usually the case that request
will already have passed once through CsrfViewMiddleware
. (Yes, it can happen. I have a case where a request I receive is modified and retested through CsrfViewMiddleWare
after it has already been tested by CsrfViewMiddleware
due to the site-wide configuration.) However, the middleware sets csrf_processing_done
on request
after it tests it and won't retest it if it is called again, because of this flag. So csrf_processing_done
has to be reset to False
to perform a second test.
Here's an illustration of the above:
from django.middleware.csrf import CsrfViewMiddleware
def view(request):
request.csrf_processing_done = False
reason = CsrfViewMiddleware().process_view(request, None, (), {})
if reason is not None:
return reason # Failed the test, stop here.
# process the request...