JWT 로그인 방식 서버에 로그인을 하면 토큰을 발급해주어 사용자가 서비스를 이용할때 이 토큰을 요청에 포함시켜 사용자를 인증한다. 근데 이 토큰엔 만료시간이 있다 이 프로젝트에서는 이 토큰의 만료시간이 15분이다 그래서 토큰이 만료되면 리프레시 토큰으로 다시 새로운 access_token
을 발급 받아야 한다
오잉…..
access_token
이 만료되면.. 리프레시 토큰으로 새롭게 발급 받으라고!?
일단 로그인할때 response
받은 access_token
과 refresh_token
을 저장하자
시나리오 1.
로그인 할 때 발급 받은 access_token은 리덕스에, refresh_token은 쿠키에 저장한다
hoc를 이용해 access_token이 만료되면 새롭게 발급받고 토큰이 필요한 컴포넌트에 props로 넘겨준다
react-cookie라는 라이브러리를 통해 쿠키에 쉽게 저장 할 수 있었다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import { Cookies } from "react-cookie" ;const cookies = new Cookies ();export const setRefreshToken = (refreshToken ) => { const today = new Date (); const expireDate = today.setDate (today.getDate () + 7 ); return cookies.set ("refresh_token" , refreshToken, { sameSite : "strict" , path : "/" , expires : new Date (expireDate), }); }; export const getCookieToken = ( ) => { return cookies.get ("refresh_token" ); }; export const removeCookieToken = ( ) => { return cookies.remove ("refresh_token" , { sameSite : "strict" , path : "/" }); };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import React , { useEffect, useCallback } from "react" ;import { useSelector, useDispatch } from "react-redux" ;import { getCookieToken } from "@util/settingSessions" ;import { refreshTokenFunc } from "@api/loginApi" ;import { setAccessTokenAction } from "@redux/user/userSlice" ;const AccessToken = (SpecificComponent ) => { const AccessToken = (props ) => { const accessToken = useSelector ((state ) => state.user .accessToken ); const userLogin = useSelector ((state ) => state.user .userLogin ); const dispatch = useDispatch (); const getCookie = useCallback (async () => { const refresh = await getCookieToken (); const access_token = await refreshTokenFunc (refresh); await dispatch (setAccessTokenAction (access_token)); }, [userLogin]); useEffect (() => { if (userLogin) { getCookie (); } }, []); return ( <SpecificComponent {...props } accessToken ={accessToken} userLogin ={userLogin} /> ); }; return AccessToken ; }; export default AccessToken ;
조건문 작성이 좀 이상하긴 했다.. 유저가 로그인 되어있으면 리프레시 토큰을 호출했으니 그리고 또 다른 문제가 호출이 너무 많이 된다는 거다.. 중간에 조건문 작성을 좀 바꿨었는데 안되서 다른 방식을 택했다…
시나리오 2.
axios interceptor
를 이용해서 토큰이 만료되면 리프레시토큰으로 다시 호출 해온다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 clientServer.interceptors .response .use ( async (response) => { return response; }, async (error) => { const { config, response : { status }, } = error; if (status === 401 ) { if ( error.response .data .msg === "Token has expired" || error.response .data .msg === "Missing Authorization Header" ) { const originalRequest = config; const refreshToken = await getCookieToken (); const access_token = await refreshTokenFunc (refreshToken); clientServer.defaults .headers .common .Authorization = `Bearer ${access_token} ` ; originalRequest.headers .Authorization = `Bearer ${access_token} ` ; return axios (originalRequest); } } return Promise .reject (error); } );
interceptor
를 이용한 refresh 토큰을 검색해보니 여러 정보가 떴다 보면서 작성하긴 했는데 이게 제대로 되는지 사실 애매했다. 어떨때는 잘 불러오는데 어떨때는 …. 새로고침을 해줘야 토큰을 다시 불러 올 때도 있었다. 이 axios interceptor
에 대해서 좀 더 공부해 볼 필요가 있다