I’ve seen in django code base that BaseBackend
already has aauthenticate
and aget_user
methods, but right now for the latest django 5.1.4 they are not available. What should I do if I need to load users from external sources asynchronously? I can’t just slam one of the methods of custom auth backend asgiref.async_to_sync
coz it will throw “You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.” Of course I can write a sync call to that external source, but it doesn’t look good…
in the end alongside custom async auth backend as a workaround I wrote simplified versions (hardcoded for backend) of aget_user
, aauthenticate
, custom AuthenticationMiddleware
(that uses new aget_user
), and then fixed reference to new aauthenticate
inside login view.
everything works smoothly, but i’m not really happy with extra 50 lines of code, tho…
Let me see if I’ve got a good picture of what you’re doing:
- You’re in an async view or middleware.
- You’re calling into
authenticate
orget_user
, which calls into the synchronous backend. - Inside the backend, you’re needing to make an async call.
If that’s seems right, I think this error is appropriate, but it’s not quite helping you to see where it got messed up. You need the authenticate
or get_user
call to be sync_to_async
, so that it won’t stall the async loop. It does that by starting that synchronous function in a different thread (that doesn’t have an event loop already), which will make it so that async_to_sync
can do what you expect it to do.
So, for example to call authenticate
from an async view you might be able to do:
async def my_view(request):
await sync_to_async(authenticate)(...)
I agree with Ryan, but just to add context the async backends will be released with Django 5.2