Opened 7 weeks ago

Closed 6 weeks 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 Sarah Boyce, 7 weeks ago

Resolution: worksforme
Status: newclosed

I can't replicate. The behavior also matches the sync behavior

  • tests/async/test_async_auth.py

    a b class AsyncAuthTest(TestCase):  
    127127        await self.client.alogin(username="testuser", password="testpw")
    128128        request = HttpRequest()
    129129        request.session = await self.client.asession()
     130        request.user = self.test_user
    130131        await alogout(request)
     132        self.assertNotEqual(request.user, self.test_user)
     133        self.assertIsInstance(request.user, AnonymousUser)
    131134        user = await aget_user(request)
    132135        self.assertIsInstance(user, AnonymousUser)

comment:2 by Xdynix, 7 weeks 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 Xdynix, 7 weeks ago

Resolution: worksforme
Status: closednew

comment:4 by Sarah Boyce, 7 weeks ago

Cc: Jon Janzen added
Summary: `alogout` is not cleaning user cache correctlyalogout does not clear the request.auser attribute
Triage Stage: UnreviewedAccepted

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):  
    269269        user = None
    270270    await user_logged_out.asend(sender=user.__class__, request=request, user=user)
    271271    await request.session.aflush()
    272     if hasattr(request, "user"):
     272    if hasattr(request, "auser"):
    273273        from django.contrib.auth.models import AnonymousUser
     274        async def auser():
     275            return AnonymousUser()
    274276
    275         request.user = AnonymousUser()
     277        request.auser = auser
    276278
    277279
    278280def get_user_model():

Would you like to prepare a PR? This would include your test

comment:5 by Xdynix, 7 weeks ago

Has patch: set
Owner: set to Xdynix
Status: newassigned

Sure, I will submit a PR for it.

comment:7 by Sarah Boyce, 7 weeks ago

Patch needs improvement: set

comment:8 by Sarah Boyce, 6 weeks ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:9 by Sarah Boyce <42296566+sarahboyce@…>, 6 weeks ago

Resolution: fixed
Status: assignedclosed

In 31a43c5:

Fixed #36540 -- Updated request.auser() in contrib.auth.alogin() and contrib.auth.alogout().

Note: See TracTickets for help on using tickets.
Back to Top