Skip to content

Commit

Permalink
refactor: auth refreshtoken (#100)
Browse files Browse the repository at this point in the history
* feat: refresh Token

* refactor: refresh token
  • Loading branch information
boomchanotai authored May 17, 2024
1 parent ad7897b commit b190007
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 70 deletions.
71 changes: 68 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { StrictMode, Suspense } from "react";
import {
QueryCache,
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import { StrictMode, Suspense, useState } from "react";
import { RouterProvider } from "react-router-dom";
import { refreshToken as getRefreshToken } from "./api/auth/refreshToken";
import { router } from "./routes";
import useAuthStore from "./store/authStore";
import { calculateExpiryTime } from "./utils/calculateExpiryTime";

function AppRoot() {
return (
Expand All @@ -18,7 +25,65 @@ function AppRoot() {
}

function App() {
const queryClient = new QueryClient();
const accessToken = useAuthStore((state) => state.accessToken);
const refreshToken = useAuthStore((state) => state.refreshToken);
const setAuth = useAuthStore((state) => state.setAuth);
const clearAuth = useAuthStore((state) => state.clearAuth);
const [isRefreshingToken, setIsRefreshingToken] = useState(false);

const refreshAuthToken = async (
accessToken: string,
refreshToken: string
) => {
if (isRefreshingToken) return;
if (accessToken == null || refreshToken == null) return;

try {
const response = await getRefreshToken(refreshToken);

const expriedAt = calculateExpiryTime(response.expires_in);
setAuth(response.access_token, response.refresh_token, expriedAt);
} catch (error) {
clearAuth();
router.navigate("/admin");
} finally {
setIsRefreshingToken(false);
}
};

const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: 30000, // 30 seconds
retry: (failureCount, error) => {
// Don't retry for certain error responses
if (
error.message.includes("400") ||
error.message.includes("401")
) {
return false;
}

// Retry others just once
return failureCount <= 1;
},
},
},
queryCache: new QueryCache({
onError: (error) => {
if (
error.message.includes("400") ||
error.message.includes("401")
) {
if (accessToken == null || refreshToken == null) return;
refreshAuthToken(accessToken, refreshToken);
}
},
}),
})
);

return (
<StrictMode>
Expand Down
8 changes: 0 additions & 8 deletions src/api/auth/refreshToken.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import useAuthStore from "@/store/authStore";
import axios from "axios";

interface RefreshTokenResponse {
Expand All @@ -14,17 +13,10 @@ interface RefreshTokenCredentials {
const refreshToken = async (
refresh_token: string
): Promise<RefreshTokenResponse> => {
const { accessToken } = useAuthStore.getState();

const response = await axios.post<RefreshTokenResponse>(
`${import.meta.env.VITE_API_URL}/auth/refreshToken`,
{
refresh_token,
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
);

Expand Down
43 changes: 0 additions & 43 deletions src/hooks/auth/useRefreshToken.ts

This file was deleted.

17 changes: 1 addition & 16 deletions src/layouts/AdminLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
import background from "@/assets/background/background.png";
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import useRefreshToken from "@/hooks/auth/useRefreshToken";
import useAuthStore from "@/store/authStore";
import { useEffect } from "react";
import { Toaster } from "react-hot-toast";
import { useNavigate } from "react-router-dom";

type MainLayoutProps = {
children: React.ReactNode;
};

const AdminLayout = ({ children }: MainLayoutProps) => {
const navigate = useNavigate();
const { isLoggedIn, refreshToken, validateSession } = useAuthStore();
const { mutate } = useRefreshToken();

useEffect(() => {
if (isLoggedIn == false) {
navigate("/admin");
}

if (isLoggedIn && refreshToken && validateSession()) {
mutate({ refresh_token: refreshToken });
}
}, [isLoggedIn]);
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);

return (
<>
Expand Down

0 comments on commit b190007

Please sign in to comment.