Is there any way to edit the request user in django middleware?
Asked Answered
S

1

7

I am creating a way for Superusers to assume control of another user's account, but allow logging to show that all actions performed in this time are done by the superuser.

The idea I have currently is to process the request in middleware and look for a specific header. If that header exists I will replace the current request.user with the user specified in the header. Currently the middleware looks like this:

class ControlledUserMiddleware(MiddlewareMixin):

def process_request(self, request):
    controlled_user = request.META.get('HTTP_CONTROLLED_USER', None)
    if controlled_user:
        request.user = User.objects.get(uuid=controlled_user)

I have found that - despite the fact I have placed this after the auth middleware in my settings file - the user in the request is always 'anonymous user' when it reaches this function.

This method is not working currently and I was wondering if it was possible at all to edit the request.user before it reaches view logic.

Edit as requested in comments, here are the REST_FRAMEWORK settings:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.MultiPartParser',
        'rest_framework.parsers.FormParser',
    ]
}
Sixty answered 4/3, 2019 at 16:17 Comment(7)
I think the idea is not good. Because it will become a headache since you can't distinguish between the logs of normal user and superuser.Leclair
So, What I suggest is, provide access/permission to the superuser to such operations.Leclair
I have added an extra column in the logs, so all logs will look normal except for those that contain the added 'controlled user', which will show who the user was acting as while they performed a request. That aside though - purely for science - is it possible to override the request.user?Sixty
I didn't try yet. What about your status? Is your snippet working?\Leclair
Yeah the snippet works but acts as if the user has never been changed, which makes me think the user is being set again after this has finished. I have put this as the last thing in my middleware list but still no luckSixty
Please share your REST_FRAMEWORK settings. DRF's DEFAULT_AUTHENTICATION_CLASSES (if you have defined any) should provide some hints.Glyceryl
Edited post with DRF settingsSixty
S
7

Found it, yes it is possible. It turns out that as mehamasum correctly pointed out in the comment above, the TokenAuthentication in my DEFAULT_AUTHENTICATION_CLASSES was overwriting the request.user from the token in the request. This can be overwritten by adding _force_auth_user and force_auth_token to the middleware function like so:

class ControlledUserMiddleware(MiddlewareMixin):

def process_request(self, request):
    controlled_user_uuid = request.META.get('HTTP_CONTROLLED_USER', None)
    if controlled_user_uuid:
        controlled_user = User.objects.get(uuid=controlled_user_uuid)
        request._force_auth_user = controlled_user
        request._force_auth_token = Token.objects.get(user=controlled_user)
Sixty answered 5/3, 2019 at 12:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.