summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/contrib/auth/tokens.py2
-rw-r--r--django/contrib/auth/views.py29
2 files changed, 26 insertions, 5 deletions
diff --git a/django/contrib/auth/tokens.py b/django/contrib/auth/tokens.py
index 46b8467476..6cf694cebb 100644
--- a/django/contrib/auth/tokens.py
+++ b/django/contrib/auth/tokens.py
@@ -24,6 +24,8 @@ class PasswordResetTokenGenerator(object):
"""
Check that a password reset token is correct for a given user.
"""
+ if not (user and token):
+ return False
# Parse the token
try:
ts_b36, hash = token.split("-")
diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
index 8edf02a7d1..be156286c6 100644
--- a/django/contrib/auth/views.py
+++ b/django/contrib/auth/views.py
@@ -425,6 +425,10 @@ class PasswordResetView(PasswordContextMixin, FormView):
return super(PasswordResetView, self).form_valid(form)
+INTERNAL_RESET_URL_TOKEN = 'set-password'
+INTERNAL_RESET_SESSION_TOKEN = '_password_reset_token'
+
+
class PasswordResetDoneView(PasswordContextMixin, TemplateView):
template_name = 'registration/password_reset_done.html'
title = _('Password reset sent')
@@ -446,12 +450,26 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
self.validlink = False
self.user = self.get_user(kwargs['uidb64'])
- if self.user is not None and self.token_generator.check_token(self.user, kwargs['token']):
- self.validlink = True
- else:
- return self.render_to_response(self.get_context_data())
+ if self.user is not None:
+ token = kwargs['token']
+ if token == INTERNAL_RESET_URL_TOKEN:
+ session_token = self.request.session.get(INTERNAL_RESET_SESSION_TOKEN)
+ if self.token_generator.check_token(self.user, session_token):
+ # If the token is valid, display the password reset form.
+ self.validlink = True
+ return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
+ else:
+ if self.token_generator.check_token(self.user, token):
+ # Store the token in the session and redirect to the
+ # password reset form at a URL without the token. That
+ # avoids the possibility of leaking the token in the
+ # HTTP Referer header.
+ self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token
+ redirect_url = self.request.path.replace(token, INTERNAL_RESET_URL_TOKEN)
+ return HttpResponseRedirect(redirect_url)
- return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
+ # Display the "Password reset unsuccessful" page.
+ return self.render_to_response(self.get_context_data())
def get_user(self, uidb64):
try:
@@ -471,6 +489,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
user = form.save()
if self.post_reset_login:
auth_login(self.request, user)
+ del self.request.session[INTERNAL_RESET_SESSION_TOKEN]
return super(PasswordResetConfirmView, self).form_valid(form)
def get_context_data(self, **kwargs):