Opened 14 months ago
Closed 11 days ago
#36300 closed Bug (fixed)
request.META["HTTP_" + self.header] in RemoteUserMiddleware __acall__ does not sound correct
| Reported by: | Jan Pazdziora | Owned by: | Jacob Walls |
|---|---|---|---|
| Component: | contrib.auth | Version: | 5.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Jon Janzen, Carlton Gibson | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I've been investigating why https://github.com/adelton/django-identity-external no longer works with Django 5.2. The https://docs.djangoproject.com/en/5.2/releases/5.2/#django-contrib-auth talks about new async auth functions. I have no idea if the async functions are part of the problem I try to solve but it made me look at the code changes.
The PR https://github.com/django/django/pull/18036 for https://code.djangoproject.com/ticket/35303 added __acall__ with code
+ try: + username = request.META["HTTP_" + self.header] + except KeyError: + # If specified header doesn't exist then remove any existing + # authenticated remote-user, or return (leaving request.user set to + # AnonymousUser by the AuthenticationMiddleware).
among others.
However, the code in __call__ (previously process_request) has code
try:
username = request.META[self.header]
except KeyError:
# If specified header doesn't exist then remove any existing
# authenticated remote-user, or return (leaving request.user set to
# AnonymousUser by the AuthenticationMiddleware).
if self.force_logout_if_no_header and request.user.is_authenticated:
Since they implement the same logic, the discrepancy is worrying. I believe the "HTTP_" prefix is wrong -- if the user (admin) wants to consume some HTTP header, let them configure the value with the HTTP_ prefix already.
This also shows that there don't seem tests covering the RemoteUserMiddleware, or the problem would have been caught.
Change History (6)
comment:1 by , 14 months ago
| Cc: | added |
|---|---|
| Resolution: | → needsinfo |
| Status: | new → closed |
comment:2 by , 14 months ago
I think the difference here is that WSGI servers generally set REMOTE_USER in the environment, where the ASGI scope is parsed as headers (so get the HTTP_ prefix).
needsinfo: Yes. A clearer demonstration of why Django is at fault would be needed here.
Unless django-identity-external is using the new __acall__ methods, it's not clear why it should be affected. (I didn't see a tracking issue on its repo.) Perhaps you're using it with an async app, and you're hitting the new pathway? Maybe the `CustomHeaderRemoteUserMiddleware` example in the docs would be what you need, as a workaround?
comment:3 by , 2 weeks ago
| Resolution: | needsinfo |
|---|---|
| Status: | closed → new |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → Bug |
Replying to Jan Pazdziora:
This also shows that there don't seem tests covering the
RemoteUserMiddleware, or the problem would have been caught.
As developed in ticket:37025#comment:19, this is essentially right -- we had tests, but they were written incorrectly.
It's a regression in 50f89ae850f6b4e35819fe725a08c7e579bfd099 with respect to custom headers. (The effort to support the default header under ASGI changed the semantic for custom headers.)
I repurposed #37025 to clean up the tests, which should show the problem more clearly. I'll put up a fix.
comment:4 by , 2 weeks ago
| Has patch: | set |
|---|---|
| Owner: | set to |
| Status: | new → assigned |
PR -- this branch contains some other related fixes, so we might hold this branch until the other work is reviewed.
comment:5 by , 11 days ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
There are tests such as
tests.auth_tests.test_remote_user.RemoteUserTest.test_known_user_asyncIf the HTTP prefix is removed, the tests fail.
You will need to demonstrate an issue that we can replicate so that we can better understand the request here.
I think really this is a discussion around that WSGI adds a
HTTP_prefix but ASGI does not (seeHttpHeaders.to_wsgi_namevsHttpHeaders.to_asgi_name)I will cc some other folks to the ticket in case they have thoughts to add