diff --git a/apps/client/src/pages/onBoarding/GoogleCallback.tsx b/apps/client/src/pages/onBoarding/GoogleCallback.tsx index 1c4c8f1e..0a872de4 100644 --- a/apps/client/src/pages/onBoarding/GoogleCallback.tsx +++ b/apps/client/src/pages/onBoarding/GoogleCallback.tsx @@ -3,6 +3,16 @@ import LoadingChippi from '@shared/components/loadingChippi/LoadingChippi'; import { useEffect } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; +const sendTokenToExtension = (token: string) => { + window.postMessage( + { + type: 'SET_TOKEN', + token, + }, + window.location.origin + ); +}; + const GoogleCallback = () => { const navigate = useNavigate(); const [searchParams] = useSearchParams(); @@ -21,24 +31,20 @@ const GoogleCallback = () => { const handleUserLogin = ( isUser: boolean, - accessToken: string | undefined, + accessToken: string | null, + refreshToken: string | null, hasJob?: boolean ) => { if (isUser) { if (accessToken) { localStorage.setItem('token', accessToken); - - const sendTokenToExtension = (token: string) => { - window.postMessage( - { - type: 'SET_TOKEN', - token, - }, - window.location.origin - ); - }; sendTokenToExtension(accessToken); } + + if (refreshToken) { + localStorage.setItem('refreshToken', refreshToken); + } + if (typeof hasJob === 'boolean') { localStorage.setItem('hasJob', String(hasJob)); } @@ -54,16 +60,24 @@ const GoogleCallback = () => { const loginWithCode = async (code: string) => { try { - const res = await apiRequest.post('/api/v3/auth/google', { - code, - uri: redirectUri, - }); - const { isUser, userId, email, accessToken, hasJob } = res.data.data; + const res = await apiRequest.post( + '/api/v3/auth/google', + { + code, + uri: redirectUri, + }, + { + withCredentials: true, + } + ); + + const { isUser, userId, email, accessToken, refreshToken, hasJob } = + res.data.data; localStorage.setItem('email', email); localStorage.setItem('userId', userId); - handleUserLogin(isUser, accessToken, hasJob); + handleUserLogin(isUser, accessToken, refreshToken, hasJob); } catch (error) { console.error('로그인 오류:', error); navigate('/onboarding?step=SOCIAL_LOGIN'); diff --git a/apps/client/src/shared/apis/setting/axiosInstance.ts b/apps/client/src/shared/apis/setting/axiosInstance.ts index a23bedf4..b79cabb4 100644 --- a/apps/client/src/shared/apis/setting/axiosInstance.ts +++ b/apps/client/src/shared/apis/setting/axiosInstance.ts @@ -28,7 +28,8 @@ apiRequest.interceptors.response.use( const noAuthNeeded = [ '/api/v1/auth/token', '/api/v3/auth/signup', - '/api/v2/auth/google', + '/api/v3/auth/google', + '/api/v3/auth/reissue', ]; const isNoAuth = noAuthNeeded.some((url) => @@ -46,10 +47,34 @@ apiRequest.interceptors.response.use( ) { originalRequest._retry = true; - // localStorage.removeItem('token'); - window.location.href = '/onboarding?step=SOCIAL_LOGIN'; + try { + const res = await axios.post( + `${import.meta.env.VITE_BASE_URL}/api/v3/auth/reissue`, + {}, + { + withCredentials: true, + } + ); - return Promise.reject(error); + const newAccessToken = res.data.data.token; + localStorage.setItem('token', newAccessToken); + + window.postMessage( + { type: 'SET_TOKEN', token: newAccessToken }, + window.location.origin + ); + + originalRequest.headers.Authorization = `Bearer ${newAccessToken}`; + return apiRequest(originalRequest); + } catch (reissueError) { + console.error('토큰 재발급 실패. 다시 로그인해주세요.', reissueError); + + localStorage.removeItem('token'); + localStorage.removeItem('refreshToken'); + window.location.href = '/onboarding?step=SOCIAL_LOGIN'; + + return Promise.reject(reissueError); + } } return Promise.reject(error);