[React17]React에서 JWT 인증 라우터 구현하기

JIN

June 24, 2022

JWT 인증

React에서 JWT 인증 방법은 아래 링크에서 확인할 수 있다.
https://5xjin.github.io/blog/install_hugo/

해당 링크에 이어서 인증 라우터를 구현할 예정이다.

JWT 인증 라우터 구현

JWT 인증 라우터를 구현함으로써 인증된 사용자는 로그인 페이지로 이동하지 못하게, 인증되지 못한 사용자는 인증 페이지로 이동하지 못하게 할 예정이다.
인증되었을 때와 인증되지 못하였을 때 총 2가지 조건이 있으므로 만들 라우터는 아래와 같다.

JWT 체크 컴포넌트

JWT 인증 여부, 즉 JWT 발급 여부 를 확인하는 컴포넌트이다.
이전 게시글에서 JWT를 웹 브라우저의 쿠키redux에 저장해 놓았으므로 이를 이용하여 검증하고, 해당 검증 값을 반환할 예정이다.

나는 해당 컴포넌트를 만들기 위해 CheckToken.js 파일을 만들었다.

CheckToken Component

./auth/CheckToken.js

export function CheckToken(key) {
    const [isAuth, setIsAuth] = useState('Loaded');
    const { authenticated, expireTime } = useSelector(state => state.token);
    const refreshToken = getCookieToken();
    const dispatch = useDispatch();

    useEffect(()=> {
        const checkAuthToken = async () => {
            if (refreshToken===undefined) {
                dispatch(DELETE_TOKEN());
                setIsAuth('Failed');
            } else {
                if (authenticated && new Date().getTime() < expireTime){
                    setIsAuth('Success');
                } else {
                    const response = await requestToken(refreshToken);

                    if (response.status) {
                        const token = response.json.access_token;
                        dispatch(SET_TOKEN(token));
                        setIsAuth('Success');
                    } else {
                        dispatch(DELETE_TOKEN());
                        removeCookieToken();
                        setIsAuth('Failed');
                    }
                }
            }
        };
        checkAuthToken();
    }, [refreshToken, dispatch, key]);

    return {
        isAuth
    };
}
  1. 웹 브라우저의 쿠키 에 토큰이 저장되어 있는지 확인한다. 만일 존재하지 않는다면 Failed 를 반환한다.
  2. 쿠키에 refresh 토큰이 저장되어 있다면 redux 내에도 저장되었는지 확인한다.
  3. 만일 리덕스 내에 저장되어 있지 않거나, 저장되었더라도 토큰이 만료되었다면 새로운 access 토큰을 요청한다.
  4. 새로운 access 토큰을 정상적으로 발급 받았거나 만료되지 않은 access 토큰이 리덕스에 존재한다면 Success를 반환한다.
  5. access 토큰에 요청에 대한 응답이 올바르지 않다면 Failed를 반환한다.

PrivateRouter

위에서 기술한 CheckToken 컴포넌트의 응답값을 이용하여 JWT 인증 라우터를 아래와 같이 구현한다.

./routes/PrivateRoute.js

export default function PrivateRoute() {
    const location = useLocation();
    const { isAuth } = CheckToken(location.key);

    if (isAuth === 'Failed') {
        return (
            <Navigate to="/user/login" />
        )
    } else if (isAuth==='Loading') {
        return <LoadingModal />
    }

    return <Outlet />
}

App.js

function App() {
  return (
      <Router>
        <Routes>
            <Route element={<PrivateRoute />}>
                <Route path="/" element={<Home />} />
                <Route path="/logout" element={<Logout />} />
            </Route>

            <Route path="/user/login" element={ <Login /> } />
        </Routes>

      </Router>
  );
}

PublicRouter

PrivateRoute 결과 값을 반대로 이용하여 똑같이 작성하면 되지만 Route로 감싸는 방법이 아닌 살짝 다른 방법을 사용해 보기로 했다.

./routes/PublicRoute.js

export default function PublicRoute({ children }) {
    const location = useLocation();
    const { isAuth } = CheckToken(location.key);

    if (isAuth === 'Success') {
        return (
            <Navigate to="/" />
        )
    } else if (isAuth==='Loading') {
        return <LoadingModal />
    }

    return children
}

App.js

function App() {
    return (
        <Router>
            <Routes>
                <Route element={<PrivateRoute />}>
                    <Route path="/" element={<Home />} />
                    <Route path="/logout" element={<Logout />} />
                </Route>

                <Route path="/user/login"
                       element={
                           <PublicRoute>
                               <Login />
                           </PublicRoute>} />
            </Routes>
        </Router>
    );
}

Git Repository

https://github.com/5xJIN/react-pactice