[Answered ]-AxiosInstance raise error ->( Invalid token specified) -> after update -> user profile information ? why ? please solve it

1๐Ÿ‘

โœ…

I should change userInfo.access to userInfo.token:

Consider axiosInstance.js:

import jwt_decode from 'jwt-decode';
import dayjs from 'dayjs';
import axios from 'axios';
import { AxiosRequestConfig } from 'axios';
import {updateAccessToken} from '../actions/userActions';
import {USER_DETAILS_RESET} from "../constants/userConstants";
const baseURL = 'http://127.0.0.1:8000';

export const axiosInstance = (userInfo , dispatch) => {

    const instance = axios.create({

        baseURL : baseURL,
        headers :  {
            'Content-Type': 'application/json',
            Authorization:`Bearer ${userInfo.access}`,
        }
    });


    instance.interceptors.request.use(async (req)=> {

            const user = jwt_decode(userInfo.token);
            const isExpired = dayjs.unix(user.exp).diff(dayjs()) < 5000;
            if (!(isExpired)) {

                return req
            }

            const response = await axios.post(
                '/api/v1/users/token/refresh/' , {refresh:userInfo.refresh},
            );


            dispatch(updateAccessToken(response.data))
            req.headers.Authorization = `Bearer ${response.data.access}`;
            return req;

    });
    return instance
}

In fact , I have Authorization:'Bearer ${userInfo.access}', whom it changing to empty sting after first request to server (backend) that implementing by django and django-rest-framework and django-rest-frame-work-simplejwt in this web application and jwt_decode() module only accept a validate jwt-token and for an empty string comeback same common error (Invalid token specified) because , here token is empty and not validate so jwt_decode() module can not parse it well , and raise this error.

Fortunately i have good implementing in django backend in serializers.py for this problem โ€“ Consider:

section 1:

class UserSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField(read_only=True)
    family = serializers.SerializerMethodField(read_only=True)
    _id = serializers.SerializerMethodField(read_only=True)
    isAdmin = serializers.SerializerMethodField(read_only=True)
    sex = serializers.SerializerMethodField(read_only=True)
    userPicture = serializers.SerializerMethodField(read_only=True)
    userIp = serializers.SerializerMethodField(read_only=True)
    userInfo = serializers.SerializerMethodField(read_only=True)
    userActive = serializers.SerializerMethodField(read_only=True)



    class Meta:
        model = get_user_model()
        # fields = "__all__"
        fields = ['_id', 'name', "family", 'email', 'sex', 'userIp', 'userInfo', 'userActive', 'userPicture', 'isAdmin' , 'password']
        extra_kwargs = {
            'password': {"write_only": True, },
            # "email": {"validators": (clean_email,), },

        }

    # def validate_email(self, value):
    #     if not User.objects.filter(email__iexact=value).exists():
    #         raise serializers.ValidationError("email is not correct !")
    #     return value
    #
    # def validate_password(self, value):
    #     if not User.objects.filter(password__iexact=value).exists():
    #         raise serializers.ValidationError("password is not correct !")
    #     return value
    def get_name(self, obj):
        name = obj.first_name
        return name

    def get_sex(self, obj):
        sex = obj.gender
        return sex

    def get_userIp(self, obj):
        userIp = obj.user_ip
        return userIp

    def get_userPicture(self, obj):
        # userPicture = obj.profile_image
        # return userPicture

        if obj.profile_image and hasattr(obj.profile_image, 'url'):
            print(obj.profile_image.url)

            userPicture = obj.profile_image.url
            return userPicture

    def get_family(self, obj):
        family = obj.last_name
        return family

    def get__id(self, obj):
        _id = obj.id
        return _id

    def get_isAdmin(self, obj):
        isAdmin = obj.is_staff

        return isAdmin
    def get_userActive(self , obj):
        userActive = obj.is_active
        return userActive
    def get_userInfo(self, obj):

        try:
            response = requests.get('https://api64.ipify.org?format=json', timeout=1000).json()
        except:
            response = None
        if response is None:
            user_ip = None
        else:
            user_ip = response['ip']

        try:
            userInfo = requests.get(f'https://ipapi.co/{user_ip}/json/', timeout=1000).json()
        except:
            userInfo = None
        # obj.user_info = userInfo
        # obj.save()
        # userInfo = obj.user_info
        if userInfo is None:
            userInfo = {}

        return userInfo

in section 1 i programming class -> class UserSerializer(serializers.ModelSerializer): as active user of this web application but this system in simplejwt (for django) once generate jwt_token in login and after first login access and refresh token do not generate jwt so i programming section 2 that it is a class -> UserSerializerWithToken(UserSerializer):
whom this class inheritance parent class in section 1 and has special method -> def get_token(self, obj): โ€“ Consider:

 def get_token(self, obj):
            token = RefreshToken.for_user(obj)
    
            return str(token.access_token)

this method generate access token in every request so Authorization:'Bearer ${userInfo.token}', is not empty and jwt_decode() parsing it well and right.

section 2:

# validating by validators in #### https://www.django-rest-framework.org/api-guide/serializers/#validation ####

class UserSerializerWithToken(UserSerializer):
    token = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = get_user_model()
        fields = ['_id', 'name', 'family', 'email', 'sex', 'userPicture', 'userActive', 'userIp', 'userInfo', 'isAdmin', 'token' , 'password']
        # fields = "__all__"

    def get_token(self, obj):
        token = RefreshToken.for_user(obj)

        return str(token.access_token)

more information -> i have bugs in my code because in method -> def get_token(self, obj): i get access token only , but i should get refresh token , too -> so:
Consider:

 def get_token(self, obj):
            token = RefreshToken.for_user(obj)
    
            return str(token.access_token)

instead to:

def get_token(self, obj):
           token = RefreshToken.for_user(obj)
           return str(token.access_token)

def get_refreshToken(self,obj)
           token = RefreshToken.for_user(obj)
           return str(token)

and add refreshToken = serializers.SerializerMethodField(read_only=True) to class UserSerializerWithToken(UserSerializer): to complete this part of code , too,

and i should compatible my app with this refershToken and token instead refresh and access that simplejwt generate once after login user and send it to redux of react in FRONTEND -> solve it => i should change userInfo.access to userInfo.token and change userInfo.refresh to userInfo.refreshToken in axiosInstance.js.

Consider axiosInstance.js (changed):

import jwt_decode from 'jwt-decode';
import dayjs from 'dayjs';
import axios from 'axios';
import { AxiosRequestConfig } from 'axios';
import {updateAccessToken} from '../actions/userActions';
 
 
export const axiosInstance = (userInfo , dispatch) => {
    const baseURL = 'http://127.0.0.1:8000';


    const instance = axios.create({

        baseURL : baseURL,
        headers :  {
            'Content-Type': 'application/json',
            Authorization:`Bearer ${userInfo?.token}`,
        }
    });


    instance.interceptors.request.use(async (req)=> {

            const user = jwt_decode(userInfo.token);
            const isExpired = dayjs.unix(user.exp).diff(dayjs()) < 5000;
            if (!(isExpired)) {

                return req
            }

            const response = await axios.post(
                'http://127.0.0.1:8000/api/v1/users/token/refresh/' , {refresh:**userInfo.refreshToken**},
            );


            dispatch(updateAccessToken(response.data))
            req.headers.Authorization = `Bearer ${response.data.access}`;
            return req;

    });
    return instance
}

so in updateAccessToken() that is imported and dispatched by dispatch() (method of react-redux) on axiosInstance.js i assigned userInfo.access to userInfo.token and userInfo.refresh to userInfo.refreshToken , because access and refresh generate once after request 'http://127.0.0.1:8000/api/v1/users/token/refresh/' and next time remove from redux but token and refreshToken that handle by coder whom these tokens are not removed after request and i use it and never raise error -> (Invalid token specified) .

userActions.js โ€“ updateAccessToken (arrow function โ€“ action (react-redux)):

export const updateAccessToken = (obj) => (dispatch , getState) => {
    const {userLogin:{userInfo}} = getState();
    userInfo.token = obj.access;
    userInfo.refreshToken = obj.refresh;



    dispatch({type: USER_LOGIN_SUCCESS , payload: userInfo});

    localStorage.setItem('userInfo' ,JSON.stringify(userInfo));


     
๐Ÿ‘คsaman barjawand

Leave a comment