Skip to content

Commit

Permalink
Update Axios interceptor to handle token expiration and refresh logic
Browse files Browse the repository at this point in the history
  • Loading branch information
xet-a committed Aug 25, 2024
1 parent 1054244 commit fbecc95
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 42 deletions.
78 changes: 42 additions & 36 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,42 +52,6 @@ if (import.meta.env.PROD) {

const router = createBrowserRouter(routes);

axios.interceptors.response.use(
res => {
console.log("inspector test: " + res.data.json);
return res;
},
async error => {
const state = store.getState();
const dispatch = useDispatch();
const originalRequest = error.config;

if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;

const refreshToken = state.auth.refreshToken;
const response = await axios.post('/auth/refresh', { refreshToken });

if (response.status === 200) {
const newAccessToken = response.data.accessToken;
dispatch(setAccessToken(newAccessToken));

axios.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;

return axios(originalRequest);
} else {
dispatch(setAccessToken(null));
dispatch(setRefreshToken(null));
dispatch(setUserData(null));
}
}

return Promise.reject(error);
}
);


axios.defaults.baseURL = import.meta.env.VITE_API_ADDR;

function SettingLoader() {
Expand All @@ -97,6 +61,7 @@ function SettingLoader() {

function App() {
const config = useSelector(selectConfig);
const dispatch = useDispatch();
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const theme = useMemo(() => {
const defaultMode = prefersDarkMode ? "dark" : "light";
Expand Down Expand Up @@ -134,6 +99,47 @@ function App() {
});
}, [handleError]);

useEffect(() => {
const handleRefreshTokenExpiration = () => {
dispatch(setAccessToken(null));
dispatch(setRefreshToken(null));
dispatch(setUserData(null));
// axios.defaults.headers.common["Authorization"] = "";
};

const interceptor = axios.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
if (error.config.url === "/auth/refresh") {
handleRefreshTokenExpiration();
return Promise.reject(error);
} else if (!error.config._retry) {
error.config._retry = true;
const refreshToken = store.getState().auth.refreshToken;
try {
const response = await axios.post("/auth/refresh", { refreshToken });
const newAccessToken = response.data.accessToken;
dispatch(setAccessToken(newAccessToken));
axios.defaults.headers.common["Authorization"] =
`Bearer ${newAccessToken}`;
error.config.headers["Authorization"] = `Bearer ${newAccessToken}`;
return axios(error.config);
} catch (refreshError) {
handleRefreshTokenExpiration();
return Promise.reject(refreshError);
}
}
}
return Promise.reject(error);
}
);

return () => {
axios.interceptors.response.eject(interceptor);
};
}, [dispatch]);

return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
Expand Down
1 change: 0 additions & 1 deletion frontend/src/pages/auth/callback/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ function CallbackIndex() {

dispatch(setAccessToken(accessToken));
dispatch(setRefreshToken(refreshToken));

}, [dispatch, navigate, searchParams]);

return <Box></Box>;
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/store/authSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { RootState } from "./store";

export interface AuthState {
accessToken: string | null;
refreshToken: string | null;
refreshToken: string | null;
}

const initialState: AuthState = {
accessToken: null,
refreshToken: null,
refreshToken: null,
};

export const authSlice = createSlice({
Expand All @@ -19,9 +19,9 @@ export const authSlice = createSlice({
setAccessToken: (state, action: PayloadAction<string | null>) => {
state.accessToken = action.payload;
},
setRefreshToken(state, action: PayloadAction<string | null>) {
state.refreshToken = action.payload;
},
setRefreshToken(state, action: PayloadAction<string | null>) {
state.refreshToken = action.payload;
},
},
});

Expand Down

0 comments on commit fbecc95

Please sign in to comment.