Reputation: 11573
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
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