diff --git a/src/api/index.tsx b/src/api/index.tsx
index 4b01cc1a..c5a6ca4c 100644
--- a/src/api/index.tsx
+++ b/src/api/index.tsx
@@ -1,96 +1,71 @@
import axios from 'axios';
import { HTTP_STATUS_CODE } from '../constants/api';
import { getCookie, removeCookie, setCookie } from '@hooks/sign-in/useSignIn';
+import { REFRESH_API } from './refresh';
import { message } from 'antd';
-import { TextBox } from '@components/text-box';
import { ROUTES } from '@/constants/routes';
-import { REFRESH_API } from './refresh';
+import { isAccessTokenExpired } from '@/utils/refresh';
export const instance = axios.create({
// baseURL: '',
baseURL: process.env.REACT_APP_SERVER_URL,
+ timeout: 5000,
headers: {
'Content-Type': 'application/json',
- timeout: 5000,
},
});
+const handleUnauthorized = () => {
+ removeCookie('accessToken');
+ removeCookie('refreshToken');
+ localStorage.clear();
+ message.error('로그인 만료 입니다.');
+ window.location.replace('/signin');
+};
+
instance.interceptors.request.use(
- (config) => {
+ async (config) => {
const accessToken = getCookie('accessToken');
if (accessToken) {
- config.headers['Authorization'] = `Bearer ${accessToken}`;
+ const isTokenExpired = isAccessTokenExpired(accessToken);
+ if (isTokenExpired) {
+ try {
+ const res = await REFRESH_API.postRefresh({
+ accessToken: accessToken,
+ refreshToken: getCookie('refreshToken') as string,
+ });
+ config.headers['Authorization'] = `Bearer ${res.data.accessToken}`;
+ setCookie('accessToken', res.data.accessToken);
+ setCookie('refreshToken', res.data.refreshToken);
+ } catch (refreshError) {
+ console.log('재발급 실패');
+ }
+ } else {
+ config.headers['Authorization'] = `Bearer ${accessToken}`;
+ }
}
return config;
},
(error) => {
+ // 여기 뺐습니다.
return Promise.reject(error);
},
);
instance.interceptors.response.use(
- (response) => {
- return response;
- },
- async (error) => {
- const accessToken = getCookie('accessToken');
- const refreshToken = getCookie('refreshToken');
- if (error.response.status === HTTP_STATUS_CODE.NOTFOUND) {
- console.log('404페이지로 이동');
- } else if (
+ (response) => response,
+ (error) => {
+ if (
+ error.response?.status === HTTP_STATUS_CODE.UNAUTHORIZED &&
window.location.pathname !== ROUTES.SIGNIN &&
- window.location.pathname !== ROUTES.SIGNUP &&
window.location.pathname !== ROUTES.SIGNIN_AGREEMENT &&
- window.location.pathname !== ROUTES.SIGNUP_SUCCESS &&
- error.response.status === HTTP_STATUS_CODE.UNAUTHORIZED &&
- accessToken
- ) {
- try {
- const response = await REFRESH_API.postRefresh({
- accessToken: accessToken,
- refreshToken: refreshToken as string,
- });
- removeCookie('accessToken');
- removeCookie('refreshToken');
- removeCookie('accommodationId');
- const newAccessToken = response.data.data.accessToken;
- const newRefreshToken = response.data.data.refreshToken;
- setCookie('accessToken', newAccessToken);
- setCookie('refreshToken', newRefreshToken);
- } catch (error) {
- removeCookie('accessToken');
- removeCookie('refreshToken');
- removeCookie('accommodationId');
- message.error({
- content: (
-
- 로그인 만료입니다.
-
- ),
- duration: 2,
- });
- setTimeout(() => {
- window.location.href = ROUTES.SIGNIN;
- }, 1000);
- }
- return axios(error.config);
- } else if (
- !accessToken &&
- window.location.pathname !== ROUTES.SIGNIN &&
window.location.pathname !== ROUTES.SIGNUP &&
- window.location.pathname !== ROUTES.SIGNIN_AGREEMENT &&
window.location.pathname !== ROUTES.SIGNUP_SUCCESS
) {
- removeCookie('accessToken');
- removeCookie('refreshToken');
- removeCookie('accommodationId');
- localStorage.clear();
- setTimeout(() => {
- window.location.href = ROUTES.SIGNIN;
- }, 1000);
+ handleUnauthorized();
+ } else if (error.response?.status === HTTP_STATUS_CODE.NOTFOUND) {
+ console.log('여기 404에러 핸들링 필요해요~');
}
return Promise.reject(error);
},
);
-
-export default instance;
diff --git a/src/api/refresh/index.ts b/src/api/refresh/index.ts
index 19cc30c4..3e0f084a 100644
--- a/src/api/refresh/index.ts
+++ b/src/api/refresh/index.ts
@@ -1,8 +1,7 @@
import { instance } from '..';
import { PostRefreshData, RefreshData } from './type';
-import { Response } from '@/types/api';
export const REFRESH_API = {
postRefresh: (data: RefreshData) =>
- instance.post>('/api/auth/refresh', data),
+ instance.post('/api/auth/refresh', data),
};
diff --git a/src/api/sign-up/index.ts b/src/api/sign-up/index.ts
index 0c3045a8..5152b61e 100644
--- a/src/api/sign-up/index.ts
+++ b/src/api/sign-up/index.ts
@@ -7,18 +7,17 @@ import {
VerificationData,
} from './type';
import { instance } from '..';
-import { Response } from '@/types/api';
export const SIGN_UP_API = {
postSignUp: (data: SignUpData) =>
- instance.post>('/api/auth/owners/signup', data),
+ instance.post('/api/auth/owners/signup', data),
postAuthentication: (data: AuthenticationData) =>
- instance.post>(
+ instance.post(
'/api/auth/owners/request-email',
data,
),
getVerify: (data: VerificationData) =>
- instance.get>('/api/auth/owners/verify', {
+ instance.get('/api/auth/owners/verify', {
params: {
email: data.email,
'verification-code': data.verificationCode,
diff --git a/src/assets/data/signInData.json b/src/assets/data/signInData.json
index 7fedf1f3..9ab4b30d 100644
--- a/src/assets/data/signInData.json
+++ b/src/assets/data/signInData.json
@@ -1,12 +1,9 @@
{
- "message": "성공적으로 로그인 했습니다.",
- "data": {
- "accessToken": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MTIzNDVAbmF2ZXIuY29tIiwiaWF0IjoxNzAxMzMwOTE0LCJleHAiOjE3MDE0MTczMTR9._G-tEQZpJdCgT_Uo4ipDByBwjP-0HclSq35G3MLvNvIiPILbT0Y9MZR19gTWDbzLuU0Gp1phFMbSGNYuAD1cSg",
- "refreshToken": "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE3MDEzMzA5MTQsImV4cCI6MTcwMTkzNTcxNH0.8BZt06CkTEWx7FyT4OH4c7ZNNplz9un2TCmyxf-nM5aCJe-MXJVdJAYnHW00j3ZytR_aYWp-R78tBSSF3pfAkw",
- "memberResponse": {
- "id": 1,
- "email": "test123@mail.com",
- "name": "홍길동"
- }
+ "accessToken": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MTIzNDVAbmF2ZXIuY29tIiwiaWF0IjoxNzAxMzMwOTE0LCJleHAiOjE3MDE0MTczMTR9._G-tEQZpJdCgT_Uo4ipDByBwjP-0HclSq35G3MLvNvIiPILbT0Y9MZR19gTWDbzLuU0Gp1phFMbSGNYuAD1cSg",
+ "refreshToken": "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE3MDEzMzA5MTQsImV4cCI6MTcwMTkzNTcxNH0.8BZt06CkTEWx7FyT4OH4c7ZNNplz9un2TCmyxf-nM5aCJe-MXJVdJAYnHW00j3ZytR_aYWp-R78tBSSF3pfAkw",
+ "memberResponse": {
+ "id": 1,
+ "email": "test123@mail.com",
+ "name": "홍길동"
}
}
diff --git a/src/components/layout/side-bar/signout-btn/index.tsx b/src/components/layout/side-bar/signout-btn/index.tsx
index 326c600b..fa452d3b 100644
--- a/src/components/layout/side-bar/signout-btn/index.tsx
+++ b/src/components/layout/side-bar/signout-btn/index.tsx
@@ -1,12 +1,23 @@
+import { ROUTES } from '@/constants/routes';
import { LogoutOutlined } from '@ant-design/icons';
import { TextBox } from '@components/text-box';
+import { removeCookie } from '@hooks/sign-in/useSignIn';
import styled from 'styled-components';
export const SignOutBtn = () => {
+ const handleSignOut = () => {
+ // 여기에 로그아웃 api 연결할 예정
+ // 밑에는 onSuccess 시 할 일
+ removeCookie('accessToken');
+ removeCookie('refreshToken');
+ localStorage.clear();
+ window.location.href = ROUTES.SIGNIN;
+ // 여기 밑에는 onError 시 할 일 추가할 예정
+ };
return (
-
+
로그아웃
diff --git a/src/hooks/sign-in/useSignIn.ts b/src/hooks/sign-in/useSignIn.ts
index d2e85a93..121ed2e3 100644
--- a/src/hooks/sign-in/useSignIn.ts
+++ b/src/hooks/sign-in/useSignIn.ts
@@ -1,7 +1,7 @@
export const setCookie = (name: string, value: string | number) => {
try {
if (name === 'accessToken') {
- document.cookie = `${name}=${value};max-age=7200;path=/;`;
+ document.cookie = `${name}=${value};max-age=3600;path=/;`;
} else if (name === 'refreshToken') {
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 7);
diff --git a/src/pages/sign-in/index.tsx b/src/pages/sign-in/index.tsx
index 8be5ce5c..6afb50b2 100644
--- a/src/pages/sign-in/index.tsx
+++ b/src/pages/sign-in/index.tsx
@@ -24,6 +24,8 @@ export const SignIn = () => {
setCookie('accessToken', response.data.accessToken);
setCookie('refreshToken', response.data.refreshToken);
const memberResponse = response.data.memberResponse;
+ setCookie('accessToken', response.data.accessToken);
+ setCookie('refreshToken', response.data.refreshToken);
const memberData = JSON.stringify(memberResponse);
localStorage.setItem('member', memberData);
if (accommodationListData?.accommodations[0]?.id) {
@@ -32,74 +34,35 @@ export const SignIn = () => {
accommodationListData?.accommodations[0]?.id,
);
}
- try {
- const res = isAccomodationList();
- if (res === true) {
- const accomodationId = getCookie('accomodationId');
- setTimeout(() => {
- handleChangeUrl(`/${accomodationId}/main`);
- }, 1000);
- } else {
- setTimeout(() => {
- handleChangeUrl('/init');
- }, 1000);
- }
- } catch (e) {
- message.error({
- content: (
-
- 요청에 실패했습니다. 잠시 후 다시 시도해 주세요.
-
- ),
- duration: 2,
- style: {
- width: '346px',
- height: '41px',
- },
- });
+ const res = isAccommodationList();
+ if (res === true) {
+ const accommodationId = getCookie('accommodationId');
+ setTimeout(() => {
+ handleChangeUrl(`/${accommodationId}/main`);
+ }, 1000);
+ } else {
+ setTimeout(() => {
+ handleChangeUrl('/init');
+ }, 1000);
}
},
- onError(error) {
- if (error instanceof AxiosError && error.response) {
- if (error.response.status === HTTP_STATUS_CODE.BAD_GATEWAY) {
- message.error({
- content: (
-
- 요청에 실패했습니다. 잠시 후 다시 시도해 주세요.
-
- ),
- duration: 2,
- style: {
- width: '346px',
- height: '41px',
- },
- });
- } else {
- message.error({
- content: (
-
- 이메일과 비밀번호를 확인해 주세요.
-
- ),
- duration: 2,
- style: {
- width: '346px',
- height: '41px',
- },
- });
- }
- }
+ onError() {
+ message.error({
+ content: (
+
+ 이메일과 비밀번호를 확인해 주세요.
+
+ ),
+ duration: 2,
+ });
},
});
- const isAccomodationList = () => {
- if (
+
+ const isAccommodationList = () => {
+ return (
accommodationListData?.accommodations &&
accommodationListData.accommodations.length > 0
- ) {
- return true;
- } else {
- return false;
- }
+ );
};
const handleOnclick = () => {
@@ -123,6 +86,7 @@ export const SignIn = () => {
});
}
};
+
const formik = useFormik({
initialValues: {
email: '',
@@ -130,11 +94,43 @@ export const SignIn = () => {
},
validationSchema: ValidateSchema,
onSubmit: async (values) => {
- const signInData: SignInData = {
- email: values.email,
- password: values.password,
- };
- mutate(signInData);
+ try {
+ const signInData: SignInData = {
+ email: values.email,
+ password: values.password,
+ };
+ await mutate(signInData);
+ } catch (e) {
+ if (e instanceof AxiosError && e.response) {
+ if (e.response.status === HTTP_STATUS_CODE.BAD_GATEWAY) {
+ message.error({
+ content: (
+
+ 요청에 실패했습니다. 잠시 후 다시 시도해 주세요.
+
+ ),
+ duration: 2,
+ style: {
+ width: '346px',
+ height: '41px',
+ },
+ });
+ } else {
+ message.error({
+ content: (
+
+ 이메일과 비밀번호를 확인해 주세요.
+
+ ),
+ duration: 2,
+ style: {
+ width: '346px',
+ height: '41px',
+ },
+ });
+ }
+ }
+ }
},
});
@@ -155,7 +151,7 @@ export const SignIn = () => {
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
- >
+ />
{touched.email && errors.email && (
{errors.email}
@@ -171,7 +167,7 @@ export const SignIn = () => {
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
- >
+ />
{touched.password && errors.password && (
{errors.password}
diff --git a/src/queries/sign-up/index.ts b/src/queries/sign-up/index.ts
index cc7b67dd..6ec44124 100644
--- a/src/queries/sign-up/index.ts
+++ b/src/queries/sign-up/index.ts
@@ -6,34 +6,32 @@ import {
PostSignUpResData,
SignUpData,
} from '@api/sign-up/type';
-import { Response } from '@/types/api';
import { SIGN_UP_API } from '@api/sign-up';
export const usePostSignUp = (
options?: UseMutationOptions<
- AxiosResponse>,
+ AxiosResponse,
AxiosError,
SignUpData
>,
) => {
- return useMutation<
- AxiosResponse>,
- AxiosError,
- SignUpData
- >((data: SignUpData) => SIGN_UP_API.postSignUp(data), {
- ...options,
- });
+ return useMutation, AxiosError, SignUpData>(
+ (data: SignUpData) => SIGN_UP_API.postSignUp(data),
+ {
+ ...options,
+ },
+ );
};
export const usePostAuthentication = (
options?: UseMutationOptions<
- AxiosResponse>,
+ AxiosResponse,
AxiosError,
AuthenticationData
>,
) => {
return useMutation<
- AxiosResponse>,
+ AxiosResponse,
AxiosError,
AuthenticationData
>((data: AuthenticationData) => SIGN_UP_API.postAuthentication(data), {
diff --git a/src/utils/refresh/index.ts b/src/utils/refresh/index.ts
new file mode 100644
index 00000000..f4ca32ea
--- /dev/null
+++ b/src/utils/refresh/index.ts
@@ -0,0 +1,18 @@
+export function isAccessTokenExpired(accessToken: string) {
+ if (!accessToken) {
+ return true;
+ }
+
+ const decodedToken = decodeAccessToken(accessToken);
+ const currentTime = Math.floor(Date.now() / 1000);
+
+ return decodedToken.exp < currentTime;
+}
+
+function decodeAccessToken(accessToken: string) {
+ const tokenParts = accessToken.split('.');
+ const encodedPayload = tokenParts[1];
+ const decodedPayload = atob(encodedPayload);
+
+ return JSON.parse(decodedPayload);
+}