sessionStorage에 token 저장하기
useEffect(() => {
// auth.onAuthStateChanged(async (user) => {
auth.onIdTokenChanged(async (user) => {
if (user) {
const token = await user.getIdToken();
const userId = user.uid;
dispatch(getUser(userId));
sessionStorage.setItem("accessToken",token);
setIsLogin(true);
} else {
dispatch(getUser(null));
setIsLogin(false);
}
});
}, []);
const checkTokenExpiration = async () => {
const token = sessionStorage.getItem("accessToken");
if (token) {
try {
const expirationTime = jwtDecode(token).exp;
const currentTime = Math.floor(Date.now() / 1000);
if (expirationTime < currentTime) {
sessionStorage.removeItem("accessToken");
alert("토큰이 만료되어 로그아웃 되었습니다");
await signOut(auth);
}
} catch (error) {
console.error(error);
}
}
};
setInterval(checkTokenExpiration, 60000);
const logOut = async () => {
await signOut(auth);
dispatch(getUser(null));
sessionStorage.removeItem("accessToken")
};
auth는 getAuth()로 가져온 유저 정보를 뜻한다.
onAuthStateChanged는 로그인 정보가 변경될 때마다 콜백함수를 호출된다.
onIdTokenChanged는 id token이 변경될 때마다 콜백함수를 호출한다.
그러므로 토큰 정보를 가져와서 활용하기 위해서는 onIdTokenChanged 함수를 사용해야 한다.
토큰이 존재할 때 세션스토리지에 setItem으로 토큰을 저장한다.세션스토리지는 브라우저 세션이 만료되면 사라지고,로컬스토리지는 브라우저가 종료되어도 남아있다.그래서 세션이 만료되면 토큰 정보가 사라질 수 있도록 세션스토리지에 저장했다.
checkTokenExpiration라는 함수를 만들어서 setInterval로 1분마다 토큰의 만료시간을 체크하도록 했다.(firebase에서 생성되는 토큰은 기본적으로 1시간이다.)
토큰은HEADER.PAYLOAD.VERIFY SIGNATURE 세 가지 부분으로 나누어진다.만료시간인 exp는 payload에 담겨있다.
토큰을 디코딩 하기위해 jwt-decode 패키지를 설치하고 사용했다.
yarn add jwt-decode
import jwtDecode from "jwt-decode";
해당 패키지를 이용해서 디코딩을 하면 객체로 확인 됐던 것 같다.
그래서 디코딩된 객체에 .exp를 하면 필요한 정보인 토큰 만료시간만 얻을 수 있다.
해결하지 못한 점
토큰이 만료되고
alert로 토큰이 만료되었다는 안내 문구와 함께 강제 로그아웃을 하고자 했으나
alert창이 확인되지는 않았다..ㅠㅠㅠ
하지만 시간이 만료되면 로그아웃은 되기 때문에.. 오늘은 이정도로 만족한다..!
조건부 Router 렌더링하기
토큰이 있다는 것은 로그인 된 유저가 있다는 것으로
로그인 상태에서는 접근하지 못하는 페이지를 구분했다.
이미 로그인된 상태라면 로그인과 회원가입 페이지는 접근하지 못하도록
{!token && ~~~} 으로 조건부 렌더링을 표현했다.
그리고 접근하지 못하는 링크를 입력했을 경우를 위해
<Route path='*' element={<NotFoundPage />} />
이 줄을 추가해줬다.
내가 지정하지 않아 접근할 수 없는 모든 페이지는 NotFoundPage로 넘어가게 된다!
const Router = () => {
const token = sessionStorage.getItem("accessToken");
return (
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path='/detail/:id' element={<Detail />} />
{!token && <Route path='/login' element={<Login />} />}
{!token && <Route path='/signup' element={<SignUp />} />}
<Route path='*' element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
);
};