Skip to content

Instantly share code, notes, and snippets.

@squio
Created June 8, 2021 08:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save squio/28aadec528bea9302c168744fd0af3b6 to your computer and use it in GitHub Desktop.
Save squio/28aadec528bea9302c168744fd0af3b6 to your computer and use it in GitHub Desktop.
Use url with uid and token generated by dj-rest-auth for actual password reset routine from django allauth
urlpatterns = [
# this path is used to generate email content for password reset request
# from dj-rest-auth API; format is same as used by default django auth so
# the generated URL must be translated to be used with allauth
path('accounts/password/reset/key/api/<uidb64>/<token>/',
user.ApiPasswordResetView.as_view(),
name='password_reset_confirm'),
]
from allauth.account.forms import \
default_token_generator as allauth_token_generator
from django.contrib.auth.tokens import default_token_generator
from django.utils.encoding import force_str
from django.utils.http import int_to_base36, urlsafe_base64_decode
from django.contrib.auth.models import User
class ApiPasswordResetView(View):
""" Wrapper to change the uid encoding and token
used by dj_rest_auth to the method used by allauth
"""
def get(self, *args, **kwargs):
uidb36 = None
token = kwargs.get('token')
try:
uid = force_str(urlsafe_base64_decode(kwargs.get('uidb64')))
user = User.objects.get(pk=uid)
uidb36 = int_to_base36(int(uid))
# validate default token
if default_token_generator.check_token(user, token):
# generate allauth token
token = allauth_token_generator.make_token(user)
else:
token = None
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
return Http404()
# redirect to Allauth password reset link
return HttpResponseRedirect(
reverse_lazy('account_reset_password_from_key', args=[uidb36, token])
)
@femiir
Copy link

femiir commented Jul 3, 2021

how do I really implement this I am a super noob to the world of Django and have spent a whole day trying to fix this

my urls.py looks like this


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('posts.urls')),
    path('api-auth/', include('rest_framework.urls')),
    path('api/v1/users/', include('dj_rest_auth.urls')),
    path('api/v1/users/register/', include('dj_rest_auth.registration.urls')),
    path('api/v1/users/register/verify-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),
    path('api/v1/users/register/verify-email/<str:key>/', ConfirmEmailView.as_view(), name='account_confirm_email'),
    path('api/v1/users/password/reset/confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    # path('password-reset/confirm/<uidb64>/<token>/', TemplateView.as_view(), name='password_reset_confirm')
  
   

    # path('accounts/', include('allauth.urls')),
    
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

everything works but I keep getting

{
    "token": [
        "Invalid value"
    ]
}

@femiir
Copy link

femiir commented Jul 3, 2021

I was able to make it work using your gist but now it goes to allauth and starts all the redirecting which I don't want...but it still generates the same uid and token so why does it not work in drf

@squio
Copy link
Author

squio commented Jul 4, 2021

@femiir so the good news is you got is working, but what do you mean withe all the redirecting?

The behavior I'm getting is:

  • first link (the one which is sent by email) opens the custom view, which generates an allauth compatible token
  • the web view is automatically redirected to the allauth token verification endpoint
  • the new compatible token checks out valid and redirect to the actual 'change password' view from allauth

So: two redirects in total and the change password page should be opened (unless the token is invalid of course).

Do you get anything else?

@femiir
Copy link

femiir commented Jul 4, 2021

@femiir so the good news is you got is working, but what do you mean withe all the redirecting?

The behavior I'm getting is:

  • first link (the one which is sent by email) opens the custom view, which generates an allauth compatible token
  • the web view is automatically redirected to the allauth token verification endpoint
  • the new compatible token checks out valid and redirect to the actual 'change password' view from allauth

So: two redirects in total and the change password page should be opened (unless the token is invalid of course).

Do you get anything else?

when I click the confirm it works and tries to automatically redirect to account/login which is not in my routes.

my goal is to write a backend and then have a front end person utilise this

@squio
Copy link
Author

squio commented Jul 5, 2021

Just one step back: these two snippets are specifically meant to convert between the password reset request from package dj-rest-auth to the routine from django-allauth.

From your question I get the impression that you want to implement something else, am I correct?

For a more generic authentication system you really should look into - for instance - Django Allauth which provides authentication services in a very flexible way.

@femiir
Copy link

femiir commented Jul 5, 2021

thank you so much for your response...

well what I was doing was having endpoints for a blog that a frontend will connect to so using dj-rest-auth
I had routes like
localhost:8000/api/v1/users/register
localhost:8000/api/v1/users/login # this was generated by dj-rest-auth for me
localhost:8000/api/v1/users/logout # this was generated by dj-rest-auth for me
localhost:8000/api/v1/users/register/verify-email/
localhost:8000/api/v1/users/register/verify-email/str:key/
localhost:8000/api/v1/users/password/reset/confirm/// # so this was the link that did not work till I used your snippets

and then had this in my route but on clicking the mail link it generates a template that was what I was referring to.

I am newbie so I guess my interpretation is not good forgive my naiveness
path('api/v1/users/password/reset/key/api///', views.ApiPasswordResetView.as_view(), name='password_reset_confirm'),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment