From 8498ef1e8625df79f561a10aae35c27486e7a6fb Mon Sep 17 00:00:00 2001 From: MOON Date: Tue, 6 Aug 2024 13:52:00 +0900 Subject: [PATCH 1/4] =?UTF-8?q?:sparkles:=20=EC=8A=A4=ED=82=A4=EB=A7=88=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리프레시토큰 요청,응답 스키마 --- src/schema/auth.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/schema/auth.ts b/src/schema/auth.ts index c5a4ee7e..c5154033 100644 --- a/src/schema/auth.ts +++ b/src/schema/auth.ts @@ -41,9 +41,20 @@ export const PostAuthResponse = z.object({ user: User, }); +export const PostRefreshTokenRequest = z.object({ + refreshToken: z.string(), +}); + +export const PostRefreshTokenResponse = z.object({ + accessToken: z.string(), +}); + // NOTE: 회원가입 타입 export type PostSignUpRequestType = z.infer; export type PostSignUpResponseType = z.infer; // NOTE: 로그인 타입 export type PostSigninRequestType = z.infer; export type PostSigninResponseType = z.infer; +// NOTE: 리프레시 토큰 +export type PostRefreshTokenRequestType = z.infer; +export type PostRefreshTokenResponseType = z.infer; From 919ab42a3238572293a4b17ba5007384e7a6110b Mon Sep 17 00:00:00 2001 From: MOON Date: Tue, 6 Aug 2024 13:52:39 +0900 Subject: [PATCH 2/4] =?UTF-8?q?:sparkles:=20=EB=A6=AC=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=8B=9C=20=ED=86=A0=ED=81=B0=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/auth.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/apis/auth.ts b/src/apis/auth.ts index e13efb7d..a0c8c36b 100644 --- a/src/apis/auth.ts +++ b/src/apis/auth.ts @@ -1,4 +1,4 @@ -import type { PostSigninRequestType, PostSigninResponseType, PostSignUpRequestType, PostSignUpResponseType } from '@/schema/auth'; +import type { PostRefreshTokenRequestType, PostRefreshTokenResponseType, PostSigninRequestType, PostSigninResponseType, PostSignUpRequestType, PostSignUpResponseType } from '@/schema/auth'; import httpClient from '.'; export const postSignin = async (request: PostSigninRequestType): Promise => { @@ -10,3 +10,8 @@ export const postSignup = async (request: PostSignUpRequestType): Promise => { + const response = await httpClient.post('/auth/refresh-token', request); + return response.data; +}; From b39ad83fd0136bc0ff3d338a913a44ecbf0086c5 Mon Sep 17 00:00:00 2001 From: MOON Date: Tue, 6 Aug 2024 13:53:05 +0900 Subject: [PATCH 3/4] =?UTF-8?q?:sparkles:=20=EB=A6=AC=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=ED=9B=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useRefreshToken.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/hooks/useRefreshToken.ts diff --git a/src/hooks/useRefreshToken.ts b/src/hooks/useRefreshToken.ts new file mode 100644 index 00000000..a4377665 --- /dev/null +++ b/src/hooks/useRefreshToken.ts @@ -0,0 +1,16 @@ +import { useMutation } from '@tanstack/react-query'; +import { postRefreshToken } from '@/apis/auth'; +import { PostRefreshTokenRequestType, PostRefreshTokenResponseType } from '@/schema/auth'; + +const useRefreshToken = () => + useMutation({ + mutationFn: postRefreshToken, + onSuccess: (data) => { + localStorage.setItem('accessToken', data.accessToken); + }, + onError: () => { + localStorage.removeItem('refreshToken'); + }, + }); + +export default useRefreshToken; From a29dcb957a350835a4d0839b0cb1188bca00851e Mon Sep 17 00:00:00 2001 From: MOON Date: Tue, 6 Aug 2024 13:53:25 +0900 Subject: [PATCH 4/4] =?UTF-8?q?:sparkles:=20=EB=A6=AC=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=8B=9C=20=ED=9B=85=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/auth/SignIn.tsx | 10 +++++++--- src/pages/auth/SignUp.tsx | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/pages/auth/SignIn.tsx b/src/pages/auth/SignIn.tsx index 7c297ab6..7e4af11c 100644 --- a/src/pages/auth/SignIn.tsx +++ b/src/pages/auth/SignIn.tsx @@ -9,17 +9,21 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form'; import { PostSigninRequest, PostSigninRequestType } from '@/schema/auth'; import useSigninMutation from '@/hooks/useSignInMutation'; +import useRefreshToken from '@/hooks/useRefreshToken'; export default function SignIn() { const mutationSignin = useSigninMutation(); + const { mutate: refreshAccessToken } = useRefreshToken(); const router = useRouter(); useEffect(() => { - const accessToken = localStorage.getItem('accessToken'); - if (accessToken) { + const refreshToken = typeof window !== 'undefined' ? localStorage.getItem('refreshToken') : null; + + if (refreshToken) { + refreshAccessToken({ refreshToken }); router.push('/epigrams'); } - }, [router]); + }, [refreshAccessToken]); // 폼 정의 const form = useForm({ diff --git a/src/pages/auth/SignUp.tsx b/src/pages/auth/SignUp.tsx index bd21425c..37a829fa 100644 --- a/src/pages/auth/SignUp.tsx +++ b/src/pages/auth/SignUp.tsx @@ -9,17 +9,21 @@ import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import useRegisterMutation from '@/hooks/useRegisterMutation'; +import useRefreshToken from '@/hooks/useRefreshToken'; export default function SignUp() { const [focusedField, setFocusedField] = useState(null); + const { mutate: refreshAccessToken } = useRefreshToken(); const router = useRouter(); useEffect(() => { - const accessToken = localStorage.getItem('accessToken'); - if (accessToken) { + const refreshToken = typeof window !== 'undefined' ? localStorage.getItem('refreshToken') : null; + + if (refreshToken) { + refreshAccessToken({ refreshToken }); router.push('/epigrams'); } - }, [router]); + }, [refreshAccessToken]); const form = useForm({ resolver: zodResolver(PostSignUpRequest),