1 | diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
|
---|
2 | index b84fae8..00e7447 100644
|
---|
3 | --- a/django/contrib/auth/views.py
|
---|
4 | +++ b/django/contrib/auth/views.py
|
---|
5 | @@ -303,6 +303,8 @@ def password_reset_done(request,
|
---|
6 | return TemplateResponse(request, template_name, context)
|
---|
7 |
|
---|
8 |
|
---|
9 | +SECURE_PASSWORD_RESET = True
|
---|
10 | +
|
---|
11 | # Doesn't need csrf_protect since no-one can guess the URL
|
---|
12 | @sensitive_post_parameters()
|
---|
13 | @never_cache
|
---|
14 | @@ -333,6 +335,10 @@ def password_reset_confirm(request, uidb64=None, token=None,
|
---|
15 | except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
|
---|
16 | user = None
|
---|
17 |
|
---|
18 | + internal_token = request.session.get('internal-reset-token')
|
---|
19 | + if internal_token:
|
---|
20 | + token = internal_token
|
---|
21 | +
|
---|
22 | if user is not None and token_generator.check_token(user, token):
|
---|
23 | validlink = True
|
---|
24 | title = _('Enter new password')
|
---|
25 | @@ -342,11 +348,19 @@ def password_reset_confirm(request, uidb64=None, token=None,
|
---|
26 | form.save()
|
---|
27 | return HttpResponseRedirect(post_reset_redirect)
|
---|
28 | else:
|
---|
29 | + if SECURE_PASSWORD_RESET and not request.session.get('internal-reset-token'):
|
---|
30 | + import uuid
|
---|
31 | + # Saving a dummy password to invalidate user token.
|
---|
32 | + user.set_password(str(uuid.uuid4()))
|
---|
33 | + user.save()
|
---|
34 | + request.session['internal-reset-token'] = token_generator.make_token(user)
|
---|
35 | form = set_password_form(user)
|
---|
36 | else:
|
---|
37 | validlink = False
|
---|
38 | form = None
|
---|
39 | title = _('Password reset unsuccessful')
|
---|
40 | + if request.session.get('internal-reset-token'):
|
---|
41 | + del request.session['internal-reset-token']
|
---|
42 | context = {
|
---|
43 | 'form': form,
|
---|
44 | 'title': title,
|
---|