pythonpython-3.xdjangodjango-rest-frameworkdjango-rest-framework-jwt

Changing the default user while using REST framework JWT


I have a proxied user model:

class TheDude(User):
    class Meta:
        proxy = True

And I'm using the Django REST framework JWT to do JWT auth in the REST API.

I'd like to get the user object from the request but currently it's a User object. Because it's proxied I can't use AUTH_USER_MODEL. I've tried doing a middleware component to override the user in the request but it's not set at that stage. I've also tried using JWT_RESPONSE_PAYLOAD_HANDLER however my function isn't called so I can't set it there either.

If I want to be able to get TheDude object when I call request.user instead of User in my views, how would I do this while authing using the REST framework JWT Auth library?

EDIT

I've added

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        ...
        'myapp.authentication.MyCustomJWTAuthentication',
    )
    ...
}

to my settings.py and my

class MyCustomJWTAuthentication(JWTAuthentication):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.user_model = TheDude

Which is called correctly however when I get the user from request in my serialiser, it's still of type User and not TheDude

class TestSerializer(serializers.ModelSerializer):

    user_test = serializers.SerializerMethodField('get_user_test')

    def get_user_test(self, obj):
        print(type(self.context['request'].user))

Solution

  • It should be possible to use the proxy model by overriding the JWTAuthentication authentication class and setting your proxy user model as the user_model like so:

    from rest_framework_simplejwt.authentication import JWTAuthentication
    
    
    class MyCustomJWTAuthentication(JWTAuthentication):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.user_model = TheDude
    

    Say you add this class on myapp/authentication.py, you can then apply this custom authentication class as one of the default authentication classes in your REST_FRAMEWORK settings:

    REST_FRAMEWORK = {
        ...
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'myapp.authentication.MyCustomJWTAuthentication',
            ...
            
        )
        ...
    }
    

    Or just apply it to certain views you want:

    from myapp.authentication import MyCustomJWTAuthentication
    
    
    class CertainAPIViewThatNeedsTheDude(APIView):
        authentication_classes = (MyCustomJWTAuthentication, )
    

    This should in turn give you a request.user that is a TheDude instance.