Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invalid link in reset_password

Tags:

django

I wanna to write a custom user in Django but I have a problem with the reset password. I use the URLs below for urls.py

url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z_\-\']+)-(?P<token>[0-9A-Za-z\-\']+)/$', PasswordResetConfirmView.as_view() , name='reset_password_confirm'),
url(r'^reset_password', ResetPasswordRequestView.as_view())

and this is my view for reset password and confirm it

class ResetPasswordRequestView(FormView):
        # User = get_user_model()
        template_name = "test_template.html"    #code for template is given below the view's code
        success_url = 'reset_password'
        form_class = PasswordResetRequestForm

        @staticmethod
        def validate_email_address(email):
            try:
                validate_email(email)
                return True
            except ValidationError:
                return False

        def post(self, request, *args, **kwargs):
            form = self.form_class(request.POST)
            if form.is_valid():
                data= form.cleaned_data["email_or_username"]
            if self.validate_email_address(data) is True:                 #uses the method written above
                '''
                If the input is an valid email address, then the following code will lookup for users associated with that email address. If found then an email will be sent to the address, else an error message will be printed on the screen.
                '''
                associated_users= User.objects.filter(Q(email=data)|Q(username=data))
                if associated_users.exists():
                    for user in associated_users:
                            c = {
                                'email': user.email,
                                'domain': request.META['HTTP_HOST'],
                                'site_name': 'your site',
                                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                                'user': user,
                                'token': default_token_generator.make_token(user),
                                'protocol': 'http',
                                    }
                            subject_template_name='password_reset_subject.txt' 
                            # copied from django/contrib/admin/templates/registration/password_reset_subject.txt to templates directory
                            email_template_name='password_reset_email.html'    
                            # copied from django/contrib/admin/templates/registration/password_reset_email.html to templates directory
                            subject = loader.render_to_string(subject_template_name, c)
                            # Email subject *must not* contain newlines
                            subject = ''.join(subject.splitlines())
                            email = loader.render_to_string(email_template_name, c)
                            send_mail(subject, email, DEFAULT_FROM_EMAIL , [user.email], fail_silently=False)
                    result = self.form_valid(form)
                    messages.success(request, 'An email has been sent to ' + data +". Please check its inbox to continue reseting password.")
                    return result
                result = self.form_invalid(form)
                messages.error(request, 'No user is associated with this email address')
                return result
            else:
                '''
                If the input is an username, then the following code will lookup for users associated with that user. If found then an email will be sent to the user's address, else an error message will be printed on the screen.
                '''
                associated_users= User.objects.filter(username=data)
                if associated_users.exists():
                    for user in associated_users:
                        c = {
                            'email': user.email,
                            'domain': 'example.com', #or your domain
                            'site_name': 'example',
                            'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                            'user': user,
                            'token': default_token_generator.make_token(user),
                            'protocol': 'http',
                            }
                        subject_template_name='password_reset_subject.txt'
                        email_template_name='password_reset_email.html'
                        subject = loader.render_to_string(subject_template_name, c)
                        # Email subject *must not* contain newlines
                        subject = ''.join(subject.splitlines())
                        email = loader.render_to_string(email_template_name, c)
                        send_mail(subject, email, DEFAULT_FROM_EMAIL , [user.email], fail_silently=False)
                    result = self.form_valid(form)
                    messages.success(request, 'Email has been sent to ' + data +"'s email address. Please check its inbox to continue reseting password.")
                    return result
                result = self.form_invalid(form)
                messages.error(request, 'This username does not exist in the system.')
                return result
            messages.error(request, 'Invalid Input')
            return self.form_invalid(form)  

class PasswordResetConfirmView(FormView):
    template_name = "password_reset_confirm.html"
    success_url = 'admin'
    form_class = SetPasswordForm

    def post(self, request, uidb64=None, token=None, *arg, **kwargs):
        """
        View that checks the hash in a password reset link and presents a
        form for entering a new password.
        """
        UserModel = get_user_model()
        form = self.form_class(request.POST)
        assert uidb64 is not None and token is not None  # checked by URLconf
        try:
            uid = urlsafe_base64_decode(uidb64)
            user = UserModel._default_manager.get(pk=uid)
        except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
            user = None

        if user is not None and default_token_generator.check_token(user, token):
            if form.is_valid():
                new_password= form.cleaned_data['new_password2']
                user.set_password(new_password)
                user.save()
                messages.success(request, 'Password has been reset.')
                return self.form_valid(form)
            else:
                messages.error(request, 'Password reset has not been unsuccessful.')
                return self.form_invalid(form)
        else:
            messages.error(request,'The reset password link is no longer valid.')
            return self.form_invalid(form) 

it sends an email include an invalid link such HTTP://127.0.0.1:8000/reset_password_confirm/b'MjM'-4y1-68809e63d52242805bd7/

when I clicked on it so I receive this message that shows it is an invalid The password reset link was invalid, possibly because it has already been used. Please request a new password reset.

I searched a lot and didn't any solution. can anybody help me, please? thanks a lot

like image 963
parimah ziayi Avatar asked Nov 22 '25 13:11

parimah ziayi


1 Answers

If you are using CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True your url must be in https.

You have 2 options. Rewrite reset.html template, create a file in rootproject\templates\registration\password_reset_email.html

The content you can force https, the template is:

{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you 
requested a password reset for your user account at
{{ site_name }}.{% endblocktrans %}

{% trans "Please go to the following page and choose a 
new password:" %}
{% block reset_link %}
https://{{ domain }}{% url 'password_reset_confirm' 
uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} 
{{ user.get_username }}

{% trans "Thanks for using our site!" %}

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

{% endautoescape %}

Option 2: You must ensure that your server is runing over https, the template email search request.schema if is http or https and is filled with schema used. I have my nginx server over https as a proxy, but my django server was running over http, thus my email template was gerated with only http.

like image 118
Egalicia Avatar answered Nov 24 '25 02:11

Egalicia