Opened 18 months ago

Closed 2 weeks ago

#35971 closed New feature (fixed)

RemoteUserMiddleware needs a get_username method

Reported by: Adrien Kunysz Owned by: Jacob Walls
Component: contrib.auth Version: 5.0
Severity: Normal Keywords:
Cc: Adrien Kunysz 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 (last modified by Adrien Kunysz)

As currently implemented, the only way to customise how RemoteUserMiddleware gets the username is through the "header" variable. This is then used in call and acall methods like this:

            username = request.META[self.header]

It would be convenient to move that logic into a separate method that could be overridden. For example:

get_username(self, request, header_name):
    return request.META[header_name]    

Specific use case: the proxy I have in front of Django always sets two specific headers (say "X-Username" and "X-Authenticated"). The value of "X-Username" is only valid if "X-Authenticated" is "true", otherwise it should be ignored (typically it ends up being a single space character). I use PersistentRemoteMiddleware to use X-Username but the only way I found to ignore it when X-Authenticated is not true is to override call / acall , which seems rather fragile while a small change to RemoteUserMiddleware would make for a much more robust, flexible and maintainable solution.

With the proposed change, in my child class I could just say

def get_username(self, request, header_name):
    if request.META["X-Authenticated"].lower() != "true":
        raise KeyError
    return request.META[header_name]

I am happy to propose a patch if we can agree this change is desirable.

The analysis above is for the latest version on github. I have marked this feature request as 5.0 because that's the version I currently use and backporting the proposed change seems easy enough.

Change History (11)

comment:1 by Adrien Kunysz, 18 months ago

Type: UncategorizedNew feature

comment:2 by Adrien Kunysz, 18 months ago

Version: dev5.0

comment:3 by Adrien Kunysz, 18 months ago

Description: modified (diff)

comment:4 by Adrien Kunysz, 18 months ago

Description: modified (diff)

comment:5 by Sarah Boyce, 18 months ago

Resolution: wontfix
Status: newclosed

I think given that it's probably not too difficult to achieve this by overriding the call method, I'm not sure it's worth adding a hook
(below is untested)

class MyRemoteUserMiddleware(RemoteUserMiddleware):
    def __call__(self, request):
        if request.META.get(self.header) and request.META["X-Authenticated"].lower() != "true":
            if self.force_logout_if_no_header and request.user.is_authenticated:
                self._remove_invalid_user(request)
            return self.get_response(request)
        return super().__call__(request)

If you want it to be added, you can propose and discuss the idea on the Django Forum, where you'll reach a broader audience and receive additional feedback.

I'll close the ticket for now, but if the community agrees with the proposal, please return to this ticket and reference the forum discussion so we can re-open it. For more information, please refer to the documented guidelines for requesting features.

comment:6 by Adrien Kunysz, 18 months ago

Thank you. I don't think your proposal resolves my problem but it gave me another idea. I can just delete the entry from request.META before calling the parent call. In case anyone else runs into this issue, this is what I am doing (5.0 has process_request instead of call):

def process_request(self, request):
    authenticated = request.META.get("X-Authenticated", "false").lower() == "true"
    if not authenticated and self.header in request.META:
        del request.META[self.header]
    return super().process_request(request)

comment:7 by Jacob Walls, 3 weeks ago

Resolution: wontfix
Status: closednew
Triage Stage: UnreviewedAccepted

Ended up needing this anyway for #37079.

comment:8 by Jacob Walls, 3 weeks ago

Has patch: set
Owner: set to Jacob Walls
Status: newassigned

comment:9 by Jacob Walls, 3 weeks ago

comment:10 by Jacob Walls, 2 weeks ago

Triage Stage: AcceptedReady for checkin

Marking RFC after two approvals on GitHub (this could have easily just been a Refs # cleanup on a closed ticket.)

comment:11 by Jacob Walls <jacobtylerwalls@…>, 2 weeks ago

Resolution: fixed
Status: assignedclosed

In c9b65e2:

Fixed #35971 -- Added RemoteUserMiddleware.get_username() helper.

This alleviates sync/async duplication.

Note: See TracTickets for help on using tickets.
Back to Top