[Django] #34565: Exception will be raised when settings.PASSWORD_HASHERS changes and the check_password() method is called in an asynchronous context.

9 views
Skip to first unread message

Django

unread,
May 14, 2023, 3:23:27 PM5/14/23
to django-...@googlegroups.com
#34565: Exception will be raised when settings.PASSWORD_HASHERS changes and the
check_password() method is called in an asynchronous context.
-------------------------------------+-------------------------------------
Reporter: Dingning | Owner: nobody
Type: Bug | Status: assigned
Component: | Version: 4.2
contrib.auth | Keywords: async auth
Severity: Normal | check_password
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
When `settings.PASSWORD_HASHERS` is changed and `user.check_password()` is
called in an async context, a `SynchronousOnlyOperation` exception may
occur.

The reason is that the check_password function will call the synchronous
setter function to update the password field of the user table when the
`settings.PASSWORD_HASHERS` is changed.


== To reproduce the process:
1. Start Django and create a user. Suppose the user's password is 123456.
2. Close the server, modify `settings.PASSWORD_HASHERS`, for example,
exchange the order of the first two Hashers. You can refer to
`django.conf.global_settings.PASSWORD_HASHERS`.
3. Start the server and call `user.check_password('123456')` in the
asynchronous view.
4. `SynchronousOnlyOperation` is raiesd.


== Reference Code:

{{{
#!python
from django.http import HttpResponse
from django.contrib.auth import get_user_model


async def test_check_password(request):
user = await get_user_model().objects.aget(id=1)
is_correct = user.check_password('123456')

return HttpResponse(is_correct)
}}}


== Significance:
1. When `settings.PASSWORD_HASHERS` changes, `check_password` and related
functions can be called normally in an asynchronous environment.
2. Lay the foundation for the future `django.contrib.auth` module to
support native asynchrony.


== Solution:
Add `acheck_password` method, this method will call the async setter
function to update the password field of the user table when the
`settings.PASSWORD_HASHERS` is changed.


== Demo
I simply implemented the solution mentioned above and put it here for
reference.
https://github.com/HappyDingning/django/tree/acheck_password


== Related discussions:
https://forum.djangoproject.com/t/add-async-support-for-abstractbaseuser-
check-password/20364

Thanks to bigfootjon, carltongibson and UriahKingsley

--
Ticket URL: <https://code.djangoproject.com/ticket/34565>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
May 14, 2023, 3:25:39 PM5/14/23
to django-...@googlegroups.com
#34565: Exception will be raised when settings.PASSWORD_HASHERS changes and the
check_password() method is called in an asynchronous context.
-------------------------------------+-------------------------------------
Reporter: Dingning | Owner: nobody
Type: Bug | Status: assigned
Component: contrib.auth | Version: 4.2
Severity: Normal | Resolution:
Keywords: async auth | Triage Stage:
check_password | Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Dingning:

Old description:

New description:


== Reference Code:

return HttpResponse(is_correct)
}}}

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34565#comment:1>

Django

unread,
May 14, 2023, 3:26:11 PM5/14/23
to django-...@googlegroups.com

Old description:

New description:


== Reference Code:

return HttpResponse(is_correct)
}}}

support native async.


== Solution:
Add `acheck_password` method, this method will call the async setter
function to update the password field of the user table when the
`settings.PASSWORD_HASHERS` is changed.


== Demo:
I simply implemented the solution mentioned above and put it here for
reference.
https://github.com/HappyDingning/django/tree/acheck_password

Thanks to bigfootjon, carltongibson and UriahKingsley

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34565#comment:2>

Django

unread,
May 14, 2023, 3:27:32 PM5/14/23
to django-...@googlegroups.com

Old description:

> support native async.
>

> == Solution:
> Add `acheck_password` method, this method will call the async setter
> function to update the password field of the user table when the
> `settings.PASSWORD_HASHERS` is changed.
>

> == Demo:
> I simply implemented the solution mentioned above and put it here for
> reference.
> https://github.com/HappyDingning/django/tree/acheck_password
>

> == Related discussions:
> https://forum.djangoproject.com/t/add-async-support-for-abstractbaseuser-
> check-password/20364
>
> Thanks to bigfootjon, carltongibson and UriahKingsley

New description:

When `settings.PASSWORD_HASHERS` is changed and `user.check_password()` is
called in an async context, a `SynchronousOnlyOperation` exception may
occur.

The reason is that the check_password function will call the synchronous
setter function to update the password field of the user table when the
`settings.PASSWORD_HASHERS` is changed.


== To Reproduce The Process:


== Reference Code:

return HttpResponse(is_correct)
}}}


== Related Discussions:
https://forum.djangoproject.com/t/add-async-support-for-abstractbaseuser-
check-password/20364

Thanks to bigfootjon, carltongibson and UriahKingsley

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34565#comment:3>

Reply all
Reply to author
Forward
0 new messages