django-rest-auth icon indicating copy to clipboard operation
django-rest-auth copied to clipboard

Can't get password reset to work by following example

Open Shelagh-Lewins opened this issue 6 years ago • 8 comments

Hi, I can't get password reset to work. I've copied urls.py directly from the demo on GitHub:

# api/urls.py
from django.urls import include, path
from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic import TemplateView, RedirectView

from django.contrib.auth.views import PasswordResetView, \
    PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView

urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
    url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
        name='signup'),
    url(r'^email-verification/$',
        TemplateView.as_view(template_name="email_verification.html"),
        name='email-verification'),
    url(r'^login/$', TemplateView.as_view(template_name="login.html"),
        name='login'),
    url(r'^logout/$', TemplateView.as_view(template_name="logout.html"),
        name='logout'),
    url(r'^password-reset/$',
        TemplateView.as_view(template_name="password_reset.html"),
        name='password-reset'),
    url(r'^password-reset/confirm/$',
        TemplateView.as_view(template_name="password_reset_confirm.html"),
        name='password-reset-confirm'),

    url(r'^user-details/$',
        TemplateView.as_view(template_name="user_details.html"),
        name='user-details'),
    url(r'^password-change/$',
        TemplateView.as_view(template_name="password_change.html"),
        name='password-change'),


    # this url is used to generate email content
    url(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        TemplateView.as_view(template_name="password_reset_confirm.html"),
        name='password_reset_confirm'),

    url(r'^rest-auth/', include('rest_auth.urls')),
    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
    url(r'^account/', include('allauth.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect')
]

I've copied the Templates folder from the demo into my django project folder.

This is from my settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'rest_auth.registration',
    'api',
    'users',
]

AUTH_USER_MODEL = 'users.CustomUser'

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 
SITE_ID = 1

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

When I browse to the endpoint http://127.0.0.1:8000/api/v1/rest-auth/password/reset/ I see a form with this information and an input to type an email:

GET /api/v1/rest-auth/password/reset/
HTTP 405 Method Not Allowed
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "detail": "Method \"GET\" not allowed."
}

If I enter an email address and click "Post" the page changes to show

{
    "detail": "Password reset e-mail has been sent."
}

However no email text appears in the console.

Here's the request that was sent, copied from the Network tab of the browser as cURL:

curl 'http://127.0.0.1:8000/api/v1/rest-auth/password/reset/' -H 'Cookie: tabstyle=html-tab; sessionid=n2nddatqzw71xiskvrn4kaynf2w6eq3x; csrftoken=ON4EIciQ7TawRpWH4g3qfh030tzHBnvQJFUZBxCMfQHn6xEgInj3ip5QCXX9r1HK' -H 'Origin: http://127.0.0.1:8000' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygXpeN1siqg1pdzU8' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' -H 'Cache-Control: max-age=0' -H 'Referer: http://127.0.0.1:8000/api/v1/rest-auth/password/reset/' -H 'Connection: keep-alive' --data-binary $'------WebKitFormBoundarygXpeN1siqg1pdzU8\r\nContent-Disposition: form-data; name="csrfmiddlewaretoken"\r\n\r\nGFZOPWrxqc3lpAyBaycV8IFtAuxp3jfbBxP9IhLty9AcEIgaOFsybQKgcYVRTXr5\r\n------WebKitFormBoundarygXpeN1siqg1pdzU8\r\nContent-Disposition: form-data; name="email"\r\n\r\[email protected]\r\n------WebKitFormBoundarygXpeN1siqg1pdzU8--\r\n' --compressed

If I paste that into a terminal, I get back the html for the password reset page.

Please, can you explain what I am missing to get this basic feature working?

Thank you.

Shelagh-Lewins avatar Dec 30 '18 10:12 Shelagh-Lewins

Check if your user exists ([email protected]), is active and has a usable password:

>>> from django.contrib.auth.models import User
>>> User.objects.get(email='[email protected]', is_active=True).has_usable_password()
True

s-sebastian avatar Jan 17 '19 09:01 s-sebastian

That code gives me an error, I guess because I have a custom user? AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.CustomUser'

The user does definitely exist; I can log in on the site as that user, using their email address and password. And I can see the user in the admin interface.

Shelagh-Lewins avatar Jan 17 '19 13:01 Shelagh-Lewins

Yes, use your custom user model.

Check the actual email backend:

$ python manage.py diffsettings --all | grep "EMAIL_BACKEND"
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

You can also test it in the console:

>>> from django.core.mail import send_mail
>>> from django.conf import settings
>>> send_mail('Testing', 'This is a test message.', settings.DEFAULT_FROM_EMAIL, ['[email protected]'], fail_silently=False)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Testing
From: webmaster@localhost
To: [email protected]
Date: Thu, 17 Jan 2019 14:41:22 -0000
Message-ID: <[email protected]>

This is a test message.
-------------------------------------------------------------------------------
1

s-sebastian avatar Jan 17 '19 14:01 s-sebastian

Thank you for your reply. I've got it working in in the end by changing a lot of things, so I can't really retest this. But I wonder if the demo code is out of date? Maybe rest-framework has changed?

Shelagh-Lewins avatar Jan 17 '19 18:01 Shelagh-Lewins

Thank you for your reply. I've got it working in in the end by changing a lot of things, so I can't really retest this. But I wonder if the demo code is out of date? Maybe rest-framework has chan

Very good, help me out with how you made it work, I'll await your reply

devgreek avatar Sep 10 '19 05:09 devgreek

Thank you for your reply. I've got it working in in the end by changing a lot of things, so I can't really retest this. But I wonder if the demo code is out of date? Maybe rest-framework has changed?

What have you changed to make it work ?

CavalcanteLucas avatar Apr 23 '20 00:04 CavalcanteLucas

I am having the same issue, how did u make work?

KimBitrus26 avatar Jul 14 '20 23:07 KimBitrus26

IIRC, I gave up on using Django Rest Framework for this bit and customised the standard Django templates.

shelagh-lewins-ucl avatar Jul 15 '20 09:07 shelagh-lewins-ucl