skip to Main Content

In my scenario, to avoid the expiration of token I decide to call the refresh token for every API calls (Adding it in the Interceptor axiosInstance.ts). I don’t know whether the approach is correct or not. If it’s correct where do I add it in my React Typescript application

Need to call the refresh token for all API calls expect some url’s.

3

Answers


  1. Well refresh tokens are used to check whether the token is needed to again issued or not for all the authorized routes where it uses the token to actually validate the user and then authorize the request. So personally i think that its better to only pass it the end points where this kind of authorization is needed and check for it like get values which uses the authorization or post etc. But in some scenarios like whereas you want to logout the user depending on some values its better to just pass it in always and then check whether the token is expired or not. This is just my personal approach.

    Login or Signup to reply.
  2. No this approach is not efficient i have did in this below steps

    1. login request after successful receive authentication token and refresh token store in global place

    2. when i request data from api using authentication token some time api return 401 because token has expired then renew auth token using refresh token

    Login or Signup to reply.
  3. You should only call the refresh endpoint only when the token is expired or you have gotten 401 response, you can check this using axios interceptors.

    if it is a jwt token you can check if the token is expired using this function

    // Function to check if a token is expired
    export const isTokenExpired = (token: string | null) => {
      try {
        if (!token) {
          return true; // Token is considered expired if it's null or undefined
        }
        // Decode the token
        const decodedToken = jwt.decode(token) as DecodedToken | null;
    
        // Check if the token has an expiration claim and if it has expired
        return !!(
          decodedToken &&
          decodedToken?.exp &&
          decodedToken.exp * 1000 < Date.now()
        );
    
      } catch (error) {
        console.error("Error decoding JWT:", error);
        return true; // Assume the token is expired if there is an error decoding it
      }
    };
    

    Your can call that function inside another function that returns an access token

      const getAccessToken = async () => {
        
        if (!accessToken) {
          
          const accessT = await refreshToken();
          
          return accessT;
        }
    
        if (isTokenExpired(accessToken)) {
          console.log("Access token expired, refreshing...");
          const accessT = await refreshToken();
          if (accessT) return accessT;
          console.log("Failed TO Refresh");
        }
    
        return accessToken;
    
      };
    

    You can call this function inside axios interceptor to check if the response is 401 , i use a react hook to accomplish that, but you can use it any other way

    import { BASE_URL } from "@/lib/constants";
    import axios from "axios";
    import { useEffect } from "react";
    import { useAuth } from "../context/auth.context";
    
    
    export const axiosAuth = axios.create({
        baseURL: BASE_URL,
        headers: {"Content-Type": "application/json"},
    });
    
    const useAxiosAuth = () => {
        const { getAccessToken, logout} = useAuth();
    
    
        useEffect(() => {
            const requestIntercept = axiosAuth.interceptors.request.use(
                async (config) => {
                    if (!config.headers["Authorization"]) {
    //the getAccessToken() function checks whether the token is expired or not then refreshes the token and get a new one if it is expired
                        const token = await getAccessToken();
                        config.headers["Authorization"] = `Bearer ${token}`;
    
                    }
                    return config;
                },
                (error) => Promise.reject(error)
            );
    
            const responseIntercept = axiosAuth.interceptors.response.use(
                (response) => response,
                async (error) => {
                    const prevRequest = error?.config;
                    if (error?.response?.status === 401 && !prevRequest?.sent) {
                        prevRequest.sent = true;
                        //inside the getacess token refresh is called
                        const token = await getAccessToken();
                        prevRequest.headers["Authorization"] = `Bearer ${token}`;
                        return axiosAuth(prevRequest);
    
                    }
                    logout();
                    return Promise.reject(error);
                }
            );
    
            return () => {
                axiosAuth.interceptors.request.eject(requestIntercept);
                axiosAuth.interceptors.response.eject(responseIntercept);
            };
        }, [accessToken, getAccessToken, logout, refreshToken]);
    
        return axiosAuth;
    };
    
    export default useAxiosAuth;
    

    so i create the axios instance in one place and import it every where to use it like

    const axiosAuth = useAxiosAuth()
    const response = await axiosAuth.get(`${url}?${params}`)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search