I wrote a code to reset user password. I just want to ask if it is a good and secure way to do this? Can I make any improvements here?
I use send_password_resetting_message
function to send an email with a link to reset password and when I go on this page I use there set_new_password
to set new password using uidb64, token and new password.
I am using DRF.
(it is for situation when you forget your password and you want to reset it)
views.py
from .utils import password_reset_token
@api_view(['POST'])
def send_password_resetting_message(request):
try:
email = request.data['email']
if User.objects.filter(email=email).exists():
user = User.objects.get(email=email)
email_subject = "..."
email_body = render_to_string('password_resetting/index.html', {
'user': user,
'domain': settings.FRONTEND_APP_ADDRESS,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': password_reset_token.make_token(user)
})
email=EmailMessage(subject=email_subject, body=email_body, from_email=settings.EMAIL_FROM_USER, to=[email])
email.content_subtype='html'
email.send()
return Response(status=status.HTTP_200_OK)
except:
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['POST'])
def set_new_password(request, uidb64, token):
try:
uid = force_text(urlsafe_b64decode(uidb64))
user = User.object.get(pk=uid)
except Exception as e:
user=None
if user and password_reset_token.check_token(user, token):
user.set_password(request.data['password'])
user.save()
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_403_FORBIDDEN)
utils.py
from django.contrib.auth.tokens import PasswordResetTokenGenerator
import six
class PasswordResetTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.password))
password_reset_token = PasswordResetTokenGenerator()
set_new_password
, please tell me that the codeuser.set_password(request.data['password']) user.save()
does NOT mean that you are saving into the database the raw text password that the user typed ! That would be a HUGE security vulnerability that should NEVER happen - instead the value the user typed should be hashed, salted, and peppered. Eg, see bcrypt which incorporates all three (though there are probably more advanced algorithms around now) \$\endgroup\$set_password
set a hashed password into database ;) \$\endgroup\$