Skip to content

5. Implementasi Refresh Token

Kenapa harus menggunakan Refresh Token

Alt text

Alt text

Api Refresh Token

Alt text

endpoint refresh token
http://localhost:5002/auth/refresh-token?
header endpoint refresh token
Authorization:Bearer XXX
id: X
response endpoint refresh token
{
    "status": "Success",
    "message": "Success",
    "data": {
        "id": 1,
        "nama": "ihsan santana w",
        "email": "ihsanabuhanifah@gmail.com",
        "password": "$2b$12$otdHLxtVDZq05dQAVccfpOH20OTJ57cg7kuAuzWkh3gWuaQrbA4YG",
        "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtYSI6Imloc2FuIHNhbnRhbmEgdyIsImVtYWlsIjoiaWhzYW5hYnVoYW5pZmFoQGdtYWlsLmNvbSIsImlhdCI6MTY5NTYwNDQwMCwiZXhwIjoxNjk2MjA5MjAwfQ.q4lzXbvXDTt-WmOru1MXDipDGsAkfELLNQC3BQLOo4U",
        "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtYSI6Imloc2FuIHNhbnRhbmEgdyIsImVtYWlsIjoiaWhzYW5hYnVoYW5pZmFoQGdtYWlsLmNvbSIsImlhdCI6MTY5NTYwNDQwMCwiZXhwIjoxNjk1NjA0NDMwfQ.BuDhbSEIwc8zc_WUZCE2cgfwBjcRD0RfvzdxuzQ3oZY"
    }
}

Membuat axiosClientRefresh

lib/axiosClient
import axios, { AxiosInstance } from "axios";

export const axiosClient: AxiosInstance = axios.create({
  baseURL: "http://localhost:5002",
  headers: { "Content-Type": "application/json" },
});


export const axiosClientRefresh: AxiosInstance = axios.create({
  baseURL: "http://localhost:5002",
  headers: { "Content-Type": "application/json" },
});

export interface BaseResponseSuccess {
  status: string;
  message: string;
  data: any[] | any;
}

export interface BaseResponsePagination {
  status: string;
  message: string;
  data: any[];
  pagination: {
    page: number;
    total_page: number;
    pageSize: number;
    total: number;
  };
}

export interface BasePayloadPagination {
  page: number;
  pageSize: number;
}

Membuat hook useRefreshToken

hook/useRefeshToken.ts
import { axiosClientRefresh } from "@/lib/axiosClient";
import { signOut, useSession } from "next-auth/react";
import { Session } from "next-auth";
import { useEffect } from "react";
import { useToast } from ".";

interface SessionUser {
  id: number;
  refreshToken: string;
  accessToken: string;
  name: string;
  email: string;
}

export const useRefreshToken = () => {
  const { data: session, update } = useSession();
  const { toastWarning } = useToast();

  useEffect(() => {
    const requestIntercept = axiosClientRefresh.interceptors.request.use(
      (config: any) => {
        config.headers[
          "Authorization"
        ] = `Bearer ${session?.user?.refreshToken}`;
        config.headers.id = session?.user?.id;

        return config;
      },
      (error: any) => Promise.reject(error)
    );

    const responseIntercept = axiosClientRefresh.interceptors.response.use(
      async (response: any) => response,
      async (error: any) => {
        toastWarning(error.response.message);
        // signOut();
        // window.location.replace("/auth/login");
      }
    );

    return () => {
      axiosClientRefresh.interceptors.request.eject(requestIntercept);
      axiosClientRefresh.interceptors.response.eject(responseIntercept);
    };
  }, [session, toastWarning]);

  const refreshToken = async () => {
    if (!session) return;

    try {
      const { user } = session as Session & { user: SessionUser };

      const res = await axiosClientRefresh.get("/auth/refresh-token");

      console.log('res', res.data)
      await update({
        ...session,
        user: {
          ...user,
          accessToken: res.data.data.access_token,
          refreshToken: res.data.data.refresh_token,
        },
      });

      return true;
    } catch {
      return false;
    }
  };

  return { refreshToken };
};

Implementasi pada useAxiosAuth

hook/useAxiosAuth.ts
import { axiosClient } from "@/lib/axiosClient";
import { useSession, signOut } from "next-auth/react";
import { useEffect } from "react";
import { useRefreshToken } from "./useRefeshToken";

const useAxiosAuth = () => {
  const { data: session } = useSession();
  const { refreshToken } = useRefreshToken();

  useEffect(() => {
    const requestIntercept = axiosClient.interceptors.request.use(
      (config: any) => {
        config.headers[
          "Authorization"
        ] = `Bearer ${session?.user?.accessToken}`;

        return config;
      },
      (error: any) => Promise.reject(error)
    );

    const responseIntercept = axiosClient.interceptors.response.use(
      async (response: any) => response,
      async (error: any) => {
        const prevRequest = error?.config;

        if (401 === error?.response?.status && !prevRequest?.sent) {
          prevRequest.sent = true;
          try {
            await refreshToken();

            prevRequest.headers[
              "Authorization"
            ] = `Bearer ${session?.user?.accessToken}`;
            return axiosClient(prevRequest);
          } catch (err) {
            signOut();
            window.location.replace("/auth/login");
          }
        } else {
          return Promise.reject(error);
        }
      }
    );

    return () => {
      axiosClient.interceptors.request.eject(requestIntercept);
      axiosClient.interceptors.response.eject(responseIntercept);
    };
  }, [session, refreshToken]);

  return axiosClient;
};

export default useAxiosAuth;

Jalankan pada Browser

Alt text