ibz ibz - 20 days ago 6
Python Question

Django user impersonation by admin

I have a Django app. When logged in as an admin user, I want to be able to pass a secret parameter in the URL and have the whole site behave as if I were another user.

Let's say I have the URL

/my-profile/
which shows the currently logged in user's profile. I want to be able to do something like
/my-profile/?__user_id=123
and have the underlying view believe that I am actually the user with ID 123 (thus render that user's profile).

Why do I want that?

Simply because it's much easier to reproduce certain bugs that only appear in a single user's account.

My questions:


  1. What would be the easiest way to implement something like this?

  2. Is there any security concern I should have in mind when doing this? Note that I (obviously) only want to have this feature for admin users, and our admin users have full access to the source code, database, etc. anyway, so it's not really a "backdoor"; it just makes it easier to access a user's account.


ibz ibz
Answer

I solved this with a simple middleware. It also handles redirects (that is, the GET parameter is preserved during a redirect). Here it is:

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.user = models.User.objects.get(id=int(request.GET["__impersonate"]))

    def process_response(self, request, response):
        if request.user.is_superuser and "__impersonate" in request.GET:
            if isinstance(response, http.HttpResponseRedirect):
                location = response["Location"]
                if "?" in location:
                    location += "&"
                else:
                    location += "?"
                location += "__impersonate=%s" % request.GET["__impersonate"]
                response["Location"] = location
        return response