From f06e63dcc73eb439f01c9d38657f8bddaef959b6 Mon Sep 17 00:00:00 2001 From: moonseonghui Date: Wed, 17 Jul 2024 22:27:44 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20logout=20axios=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/logout/logoutAxios.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/apis/logout/logoutAxios.ts diff --git a/src/apis/logout/logoutAxios.ts b/src/apis/logout/logoutAxios.ts new file mode 100644 index 00000000..e76fb710 --- /dev/null +++ b/src/apis/logout/logoutAxios.ts @@ -0,0 +1,20 @@ +import { isAxiosError } from 'axios'; + +import { privateInstance } from '@/apis/instance'; +import MESSAGES from '@/apis/messages'; + +const AUTH_URL = { + LOGOUT: '/api/auth/logout', +}; + +const userLogout = async () => { + try { + const response = await privateInstance.delete(AUTH_URL.LOGOUT); + return response.data; + } catch (error) { + if (isAxiosError(error)) throw error; + else throw new Error(MESSAGES.UNKNOWN_ERROR); + } +}; + +export default userLogout; From b8abf7e5899c0b521eec79f33c1ecbb9c33262e2 Mon Sep 17 00:00:00 2001 From: moonseonghui Date: Wed, 17 Jul 2024 23:14:31 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20logout=20api=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=97=90=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SettingPage/LogOutBtn.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/SettingPage/LogOutBtn.tsx b/src/components/SettingPage/LogOutBtn.tsx index 38505d1e..f0a97059 100644 --- a/src/components/SettingPage/LogOutBtn.tsx +++ b/src/components/SettingPage/LogOutBtn.tsx @@ -1,7 +1,23 @@ import styled from '@emotion/styled'; +import { useNavigate } from 'react-router-dom'; + +import userLogout from '@/apis/logout/logoutAxios'; function LogOutBtn() { - return 로그아웃; + const navigator = useNavigate(); + + const handleLogoutButton = async () => { + try { + await userLogout(); + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); + navigator('/'); + } catch (error) { + console.error(error); + } + }; + + return 로그아웃; } export default LogOutBtn; From 14e0e0b6e471d59848a05aed3f3c0552d1fc1ecf Mon Sep 17 00:00:00 2001 From: moonseonghui Date: Wed, 17 Jul 2024 23:54:09 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20re-issue=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20redirect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/instance.ts | 60 +++++++++++++----------- src/components/SettingPage/LogOutBtn.tsx | 4 +- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/apis/instance.ts b/src/apis/instance.ts index 8f61c2f4..c23e83dd 100644 --- a/src/apis/instance.ts +++ b/src/apis/instance.ts @@ -1,4 +1,4 @@ -import axios from 'axios'; +import axios, { isAxiosError } from 'axios'; import { LoginResponse } from '@/apis/login/loginInterface'; import MESSAGES from '@/apis/messages'; @@ -24,17 +24,22 @@ export const privateInstance = axios.create({ // refresh token api export async function postRefreshToken() { - const response = await axios.post( - `${API_URL}/api/auth/re-issue`, - {}, - { - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${localStorage.getItem('refreshToken')}`, - }, - } - ); - return response; + try { + const response = await axios.post( + `${API_URL}/api/auth/re-issue`, + {}, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${localStorage.getItem('refreshToken')}`, + }, + } + ); + return response; + } catch (error) { + if (isAxiosError(error)) throw error; + else throw new Error(MESSAGES.UNKNOWN_ERROR); + } } privateInstance.interceptors.response.use( @@ -49,23 +54,24 @@ privateInstance.interceptors.response.use( // 토큰이 만료되을 때 if (status === 401) { const originRequest = config; - const response = await postRefreshToken(); - - // 리프레시 토큰 요청이 성공할 때 - if (response.status === 200) { - const newAccessToken = response.data.data.accessToken; - localStorage.setItem('accessToken', newAccessToken); - localStorage.setItem('refreshToken', response.data.data.refreshToken); - axios.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`; - // 진행중이던 요청 이어서하기 - originRequest.headers.Authorization = `Bearer ${newAccessToken}`; - return axios(originRequest); - } - if (response.status === 401) { + try { + const response = await postRefreshToken(); + // 리프레시 토큰 요청이 성공할 때 + if (response.status === 200) { + const newAccessToken = response.data.data.accessToken; + localStorage.setItem('accessToken', newAccessToken); + localStorage.setItem('refreshToken', response.data.data.refreshToken); + axios.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`; + // 진행중이던 요청 이어서하기 + originRequest.headers.Authorization = `Bearer ${newAccessToken}`; + return await axios(originRequest); + } + } catch (err) { + // 리프레시 토큰 요청이 실패할 때 + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); alert(MESSAGES.LOGIN.EXPIRED); window.location.replace('/'); - } else { - alert(MESSAGES.UNKNOWN_ERROR); } } return Promise.reject(error); diff --git a/src/components/SettingPage/LogOutBtn.tsx b/src/components/SettingPage/LogOutBtn.tsx index f0a97059..c76a64c3 100644 --- a/src/components/SettingPage/LogOutBtn.tsx +++ b/src/components/SettingPage/LogOutBtn.tsx @@ -4,14 +4,14 @@ import { useNavigate } from 'react-router-dom'; import userLogout from '@/apis/logout/logoutAxios'; function LogOutBtn() { - const navigator = useNavigate(); + const navigate = useNavigate(); const handleLogoutButton = async () => { try { await userLogout(); localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); - navigator('/'); + navigate('/'); } catch (error) { console.error(error); }