RobinReborn
RobinReborn

Reputation: 451

CSRF Exempt Django Auth Password Reset View for Cross Domain request

I have a separate front end and backend site and I am trying to enable users on the front end to reset their password. I have created an endpoint for them to do so which works when accessed via the backend site. But when I try to access the endpoint via Insomnia I get:

Forbidden (403)

CSRF verification failed. Request aborted.

I have added my front end domain to the CORS_ORIGIN_WHITELIST.

class PasswordResetView(auth_views.PasswordResetView):
    template_name = 'users/reset_password.html'

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

Is there some other method that I must also make csrf_exempt?

Upvotes: 3

Views: 658

Answers (1)

aaron
aaron

Reputation: 43083

django.contrib.auth.views.PasswordResetView decorates its dispatch method with csrf_protect, where csrf_protect = decorator_from_middleware(CsrfViewMiddleware).

Wrapping with your csrf_exempt and the actual CsrfViewMiddleware, we have csrf_protect(csrf_exempt(csrf_protect(<bound method PasswordResetView.dispatch ...>))), where <bound method PasswordResetView.dispatch ...> is super().dispatch.

That can be reduced to csrf_protect(<bound method PasswordResetView.dispatch ...>).

We can trick CsrfViewMiddleware by setting request.csrf_processing_done = True:

class PasswordResetView(auth_views.PasswordResetView):
    template_name = 'users/reset_password.html'

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        request.csrf_processing_done = True
        return super().dispatch(request, *args, **kwargs)

Alternatively, you can set super().dispatch.__wrapped__.csrf_exempt = True but this has the side effect of also affecting other view classes that inherit auth_views.PasswordResetView, since super().dispatch.__wrapped__ is just <function PasswordResetView.dispatch ...>.

Upvotes: 2

Related Questions