If you do a GET request before POSTing to the password reset view, you get the CSRF token in a cookie, which you can then send in your POST request.
If you insist on exempting the view: I think the problem lies in the way the CSRF protection is applied to the password_reset
view. It is explicitly decorated by csrf_protect
.
To have a closer look at the problem, lets assume original_password_reset_view
is password_reset
without the csrf_protect
. Basically, you are doing this:
csrf_exempt(csrf_protect(original_password_reset_view))
# ^^ your code
# ^^ the decorator in django.contrib.auth.views
And adding in the effect of the CsrfViewMiddleware
, we get the equivalent of
csrf_protect(csrf_exempt(csrf_protect(original_password_reset_view)))
csrf_protect
is just a middleware-turned-decorator from CsrfViewMiddleware
. csrf_exempt
on the other hand simply sets csrf_exempt=True
on its argument. So the middleware, represented by the outer csrf_protect
, sees the csrf_exempt=True
value on the view and disables its CSRF projection. It negates the outer csrf_protect
. So we have:
csrf_protect(original_password_reset_view)
The view is still protected. Basically, there is no sane way around. (An insane way: write a middleware that sets request.csrf_processing_done = True
for that specific URL. Don't do that...)