﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37042	alogin() does not invalidate _acached_user, causing stale AnonymousUser after async login	Dong Huynh		"When alogin() is called after request.auser() in the same request, subsequent calls to request.auser() return a stale AnonymousUser because alogin() does not update request._acached_user.

The sync path does not have this problem. login() sets request.user = user, which replaces the SimpleLazyObject entirely, so all subsequent request.user access returns the correct user. But in the async path, request.auser() is a separate callable (partial(auser, request)) that caches its result in request._acached_user. alogin() updates request.user but never touches _acached_user.

Reproduction:

{{{
class MyAuthMiddleware:
    async def __acall__(self, request):
        # Step 1: check if already authenticated
        user = await request.auser()  # caches AnonymousUser in _acached_user

        if not user.is_authenticated:
            db_user = await User.objects.aget(email=""existing@example.com"")
            await alogin(request, db_user)  # updates request.user, NOT _acached_user

        response = await self.get_response(request)  # view runs
        return response

# In the view:
async def my_view(request):
    user = await request.auser()  # returns stale AnonymousUser
    assert user.is_authenticated  # FAILS
}}}

Fixed in: Django 6.x, which replaces request.auser with a closure after login:

{{{
if hasattr(request, ""auser""):
    async def auser():
        return user
    request.auser = auser
}}}

Workaround for 5.x, after await alogin(request, user):

{{{
request._acached_user = user  # Fixed in Django 6.x (alogin replaces request.auser)
}}}
"	Bug	closed	contrib.auth	5.2	Normal	duplicate	alogin, async, auser		Unreviewed	0	0	0	0	1	0
