Opened 3 months ago
Closed 3 months ago
#36540 closed Bug (fixed)
alogout does not clear the request.auser attribute
| Reported by: | Xdynix | Owned by: | Xdynix |
|---|---|---|---|
| Component: | contrib.auth | Version: | 5.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Jon Janzen | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | yes | UI/UX: | no |
Description
The request.auser method caches the user in _acached_user, which is not cleared during alogout. Therefore, the following view code will behave unexpectedly.
def delete_session(request: HttpRequest) -> None:
logger.info("Current user:", user=request.user.username) # user="user"
logout(request)
logger.info("Current user:", user=request.user.username) # user=""
return None
async def delete_session(request: HttpRequest) -> None:
logger.info("Current user:", user=(await request.auser()).username) # user="user"
await alogout(request)
logger.info("Current user:", user=(await request.auser()).username) # user="user"
return None
It should be able to be fixed by adding the following to alogout.
if hasattr(request, "_acached_user"):
delattr(request, "_acached_user")
Change History (9)
comment:1 by , 3 months ago
| Resolution: | → worksforme |
|---|---|
| Status: | new → closed |
comment:2 by , 3 months ago
The problematic code is within django/contrib/auth/middleware.py.
Add the following test case to auth_tests.test_middleware.TestAuthenticationMiddleware and you can reproduce it:
async def test_auser_logout(self):
from django.contrib.auth import alogout
from django.contrib.auth.models import AnonymousUser
self.middleware(self.request)
auser = await self.request.auser()
self.assertEqual(auser, self.user)
await alogout(self.request)
auser_second = await self.request.auser()
self.assertIsInstance(auser_second, AnonymousUser)
comment:3 by , 3 months ago
| Resolution: | worksforme |
|---|---|
| Status: | closed → new |
comment:4 by , 3 months ago
| Cc: | added |
|---|---|
| Summary: | `alogout` is not cleaning user cache correctly → alogout does not clear the request.auser attribute |
| Triage Stage: | Unreviewed → Accepted |
Thank you for the clarification and the test
Apologies, it makes sense we are refering to auser, rather than user, in the async case.
Confirmed that this bug has been present since alogout was implemented in 5e98959d9242c57a55c65847758781f82d386fa4 (5.0)
Here is a possible fix:
-
django/contrib/auth/__init__.py
a b async def alogout(request): 269 269 user = None 270 270 await user_logged_out.asend(sender=user.__class__, request=request, user=user) 271 271 await request.session.aflush() 272 if hasattr(request, " user"):272 if hasattr(request, "auser"): 273 273 from django.contrib.auth.models import AnonymousUser 274 async def auser(): 275 return AnonymousUser() 274 276 275 request. user = AnonymousUser()277 request.auser = auser 276 278 277 279 278 280 def get_user_model():
Would you like to prepare a PR? This would include your test
comment:5 by , 3 months ago
| Has patch: | set |
|---|---|
| Owner: | set to |
| Status: | new → assigned |
Sure, I will submit a PR for it.
comment:7 by , 3 months ago
| Patch needs improvement: | set |
|---|
comment:8 by , 3 months ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
I can't replicate. The behavior also matches the sync behavior
tests/async/test_async_auth.py