current workaround for async auth backend

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:

  1. You’re in an async view or middleware.
  2. You’re calling into authenticate or get_user, which calls into the synchronous backend.
  3. 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)(...)
1 Like

I agree with Ryan, but just to add context the async backends will be released with Django 5.2

1 Like