Difference in REMOTE_USER source between sync and async code (Django 5.2)

Hi,

I’m running into an issue where my django app is using Windows NTLM authentication and receiving the REMOTE_USER variable from IIS. In Django 5.2, async code for the RemoteUserBackend and RemoteUserMiddleware have been added, but the async code uses a different value than the sync code.

Sync code uses request.META[“REMOTE_USER”], which has been the standard since forever, I think. See django/django/contrib/auth/middleware.py at 8914f4703cf03e2a01683c4ba00f5ae7d3fa449d · django/django · GitHub

The async variant, however, uses request.META[“HTTP_REMOTE_USER”](see same file, line 203)

There is no note on this discrepancy in the code, and I can’t really find anything about it online, other than the discussion at REMOTE_USER support · Issue #127 · django/asgiref · GitHub , which doesn’t make it clear if something has changed.

Is this a bug, or am I missing something?

It’s because the expectation is that remote user (if used) will be set as a header under ASGI.

Hi Carlton, thanks for the prompt reply. Would it be an good addition to the docs at How to authenticate using REMOTE_USER to highlight this detail? Something along the lines of:

Please note: in a synchronous context (e.g. WSGI), the REMOTE_USERvalue is usually passed as an environment value from the web server to the application, and can thus be found at request.META[“REMOTE_USER”].

Due to the fact that ASGI doesn’t support passing environment variables, the RemoteUserMiddleware expects the REMOTE_USER value in an async context to be passed as a regular HTTP header: its value should be available at request.headers[“REMOTE_USER”] or request.META[“HTTP_REMOTE_USER”].

I think to do it properly the section would need a bit more of a rewrite than that. The ASGI approach is essentially equivalent to the custom header approach mentioned towards the end of the discussion there, and all the caveats apply.