3
votes

I'm using Django Rest Framework and django-rest-framework-simplejwt for authentication. The data being sent is being consumed by react.

So far I've been able to subclass the TokenObtainPairSerializer to return both the username and ID when logging in / getting a new token.

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        data = super(MyTokenObtainPairSerializer, self).validate(attrs)

        data.update({'user': self.user.username})
        data.update({'id': self.user.id})

        return data

I'm trying to have a users username and id returned when the token is refreshed as well. This, however, does not work:

class MyTokenRefreshSerializer(TokenRefreshSerializer):

    def validate(self, attrs):
        data = super(MyTokenRefreshSerializer, self).validate(attrs)
        user = self.context['request'].user
        data.update({'user': user.username})
        data.update({'id': user.id})

        return data  

Here, the username is always returned as an empty string and the ID is always returned as null.

I've tried many different ways, including trying to update this information in the view itself, but can't seem to get it to work. I've noticed that TokenRefreshSerializer subclasses serializers.Serializer while TokenObtainPairSerializer subclasses TokenObtainSerializer which itself authenticates a user using Django authentication. This appears to require a password (like when a user logs in) but obviously that wouldn't be provided when simply refreshing a token.

My question is, how can I return the username and id (or any arbitrary information) about the current user when the token is refreshed?

The follow-on question would be, is it more practical to simply save that information to localStorage on the front end when the user first logs in and have the state re-populate that data on each subsequent visit (until the user logs out, or the refresh token is no longer valid)?

Please Note: This is not a repost of similar questions such as this one, because I am targeting the REFRESHING of tokens. The initial TokenObtainPairView was straightforward to subclass and implement.

1
As in the post you'd referred, override the to_representation() method of MyTokenRefreshSerializer classJPG
@ArakkalAbu in the linked post it says that answer is out of date and we need to override the validate method. Is that incorrect? Just curious because I stayed away from that if it’s out of date.Hanzy
@ArakkalAbu I don't think that will work when looking through the source code and from the errors I've been seeing. Specifically because there won't be a self.user on MyTokenRefreshSerializer. Trying to access it will cause an error. Assigning it simply returns an empty string (if using the request.user to assign the value).Hanzy
To get around this, I’m just creating a custom token claim with the info I need and decoding it in the browser. But there should probably be a way to simply send the data in the response directly?Hanzy
As the refresh token endpoint does not set authenticated permission all you are left with to get user info is the refresh token. So i dont think there is any other way except to decode that token and get the data. You could probably do the decoding in the backend, which automatically answers your follow up question(yes you should) whether you should save user info on localstorage and refresh it with subsequent hit to a protected api that uses access token as the request.user field would now be set and you could fetch user data and refresh your localstorage in case some user update happened.dipen bhatt

1 Answers

2
votes

As the refresh token endpoint does not set authenticated permission all you are left with to get user info is the refresh token. So i dont think there is any other way except to decode that token and get the data. You could probably do the decoding in the backend, which automatically answers your follow up question(yes you should) whether you should save user info on localstorage and refresh it with subsequent hit to a protected api that uses access token as the request.user field would now be set and you could fetch user data and refresh your localstorage in case some user update happened.