Alejandro Veintimilla
Alejandro Veintimilla

Reputation: 11573

How to connect Django Rest Framework with contrib.auth views

I am using DRF with JWT (JSON Web Token) authentication. I want to use django's built-in reset password functionality. So, I have included the urls:

 url('^', include('django.contrib.auth.urls')),

But, of course, under an API, calling https://.../password_reset/ results on a csrf token missing error. I am wondering which aproach should I take to solve this. Should I change the built in reset_password view and remove csrf protection? Is it a better idea to create a DRF endpoint that accepts the email (reset_password view post parameter) and then somehow generate a csrf token and send it to the view with redirect(reverse("reset_password"), email=email) ... but then, redirect will not send a post request to the reset_password view. Maybe saving the email to session? Any advice will help.

Upvotes: 2

Views: 724

Answers (1)

Peter Malmgren
Peter Malmgren

Reputation: 565

I think in the case of a password reset endpoint it is safe to remove CSRF protection. CSRF protection is for authenticated endpoints to prevent other websites from using a user's stored credentials to gain unauthorized access. Since the PasswordResetForm used by Django doesn't do anything other than send an e-mail, an attacker can't really do much other than annoy a user by spamming them with password reset emails.

You could use a third party for this, but if all you're doing is adding a password reset endpoint, you just need a few lines of code.

views.py

import json

from django.contrib.auth.forms import PasswordResetForm
from django.http.response import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods


@csrf_exempt
@require_http_methods(['POST'])
def email_password_reset(request):
    # the POST body should be in the format {'email': '[email protected]'}
    try:
        # you could also uncomment the following line if you wanted this view to be anonymous only
        # assert not request.user.is_authenticated()
        assert request.META.get('CONTENT_TYPE', '') == 'application/json'
        body = json.loads(request.body)
    except (AssertionError, TypeError):
        pass
    else:
        form = PasswordResetForm(body)

        if form.is_valid():
            form.save()
    finally:
        return HttpResponse(status=200)

urls.py

urlpatterns = patterns(...
    url(r'^/api/password_reset/$', 'email_password_reset', name='email-password-reset')
...)

Upvotes: 3

Related Questions