Search code examples
vue.jsdjango-rest-frameworkvuex

Vuex initial state lost after token answer


I try to get value of an username field inside of a JWT from DRF response using VueJs, I set my initial state inside a vuex module:

function initialState() {
  return {
    accessKey: null,
    refreshKey: null,
    username: '',
    alertMessage: null,

  }
}
export const mutations = {
  setUserKey(state, payload) {
    state.accessKey = payload.accessKey;
    state.refreshKey = payload.refreshKey;
    state.username = payload.username;
    state.expiration = Date.now() + 1
  },
};
export const actions = {
  async loginUser(context, payload) {
    try {
      const response = await DjangoAPI.login(payload);
      context.commit('setUserKey',{
        accessKey: response.data.access,
        refreshKey: response.data.refresh,
        username: response.data.username
      });
      return Promise.resolve(response);
    } catch(err) {
      console.log('err in user.actions/loginUser', err)
      return Promise.reject(err);
    }
  },
};

export default {
  namespaced: true,
  state: initialState,
  getters,
  actions,
  mutations
}

when I check vuex initial values in localStorage i can see username field:

user: {accessKey: null, refreshKey: null, expiration: 0, username: ""}
accessKey: null
alertMessage: null
expiration: 0
refreshKey: null
username: ""

But after login, I can get other values but username field is lost:

user: {,…}
accessKey: "eyJ0eXAi...PmQU_I"
alertMessage: null
expiration: 1590318917105
refreshKey: "eyJ0eXA...GdCgI"

if I check JWT values, I can see username in my payload:

{
 "token_type": "access",
 "exp": 1590319633,
 "jti": "1556edbab9dd47349138fd98a1f8babc",
 "user_id": 1,
 "username": "ytsejam",
 "bio": "",
 "iat": 1590316033
}

Why does username field is removed after response?

Thanks

edit1:

console.log(response):

{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
config: {url: "/api/obtain/token/", method: "post", data: "{"username":"ytsejam","password":"ne12veryt.."}", headers: {…}, baseURL: "http://localhost:8000/", …}
data:
access: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwMzIyMzc5LCJqdGkiOiIyNDJjNTA3YzM0MWU0N2Y3OTE0MGU0YmNjNGQ5NWQ1MSIsInVzZXJfaWQiOjEsInVzZXJuYW1lIjoieXRzZWphbSIsImJpbyI6IiJ9.--7cLjVFAvYG8G0TCGh5_6J2foE2h0lEa9K8okUYN4U"
refresh: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU5MTUzMTY3OSwianRpIjoiMjQ0Y2UxMTgzNDk5NDFiZDk4YjlmYTk1MGRkMjdkZTEiLCJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Inl0c2VqYW0iLCJiaW8iOiIifQ.b_ONU8yR4LculKQOyw_6aNZnvGdOWbruV48_OhNKYhU"
__proto__: Object
headers: {access-control-allow-credentials: "true", access-control-allow-origin: "http://localhost:8000", allow: "POST, OPTIONS", content-language: "tr", content-length: "518", …}
request: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}
status: 200
statusText: "OK"
__proto__: Object

DRF view using SimpleJWT package:

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):

    @classmethod
    def get_token(cls, user):
        token = super(MyTokenObtainPairSerializer, cls).get_token(user)

        # Add custom claims
        token['username'] = user.username
        token['bio'] = user.bio
        return token

class ObtainTokenPairWithColorView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

Solution

  • The recommended approach to add custom fields to JWT response is to rewrite the validate() method instead of get_token():

    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
        def validate(self, attrs):
            data = super().validate(attrs)
            refresh = self.get_token(self.user)
            data['refresh'] = str(refresh)
            data['access'] = str(refresh.access_token)
    
            # Add custom claims
            data['username'] = self.user.username
            data['bio'] = self.user.bio
            return data
    

    Then you will have 'username' and 'bio' fields in response.data, along with 'access' and 'refresh'.