본문 바로가기

STUDY/React

React | JWT 안전하게 저장하기 (localStorage 사용 X) (3)

지난글까지 완료한 상태라면, 다른 탭에서 로그아웃을 하더라도 모든 탭이 동시에 로그아웃이 되지만..
다른 탭을 생성하면 또 로그인을 해야한다. 이번 글에서는 이 문제를 해결한다!

Refresh Token을 Cookie에 저장!

최초 로그인 시 함께 발급되는 refresh_token을 쿠키에 저장한다.

우선, 리액트에서 쿠키를 편하게 사용하려면 다른 라이브러리를 추가해야 한다.
아니면 documtn.cookie로 생성하고, 삭제하고 해야 하는데 굉장히 번거로운 작업이다.. 물론 직접 해도 된다.

universal-cookie를 사용할 것이다. react-cookie를 사용해도 되긴 하지만, 자바스크립트 내에서만 사용할 것이므로..

npm install universal-cookie

auth.js 수정

우선 universal-cookie를 import해주고, 생성자를 이용해 쿠키사용을 위한 선언을 한다.

import Cookies from 'universal-cookie';
const cookies = new Cookies();

 

쿠키는 key, value의 쌍 형식으로 저장되기 때문에 cookies.set()메서드도 동일하게 키와 값, 그리고 옵션을 설정해 저장한다.
옵션에는 sameSite설정을 추가해주었다.

export function setRefreshTokenToCookie(refresh_token) {
  cookies.set('refresh_token', refresh_token, { sameSite: 'strict' });
}

 

그리고 로그아웃 하면 cookie도 삭제한다.

export function logout() {
  console.log('localStorage set logout!');
  window.localStorage.setItem('logout', Date.now());
  cookies.remove('refresh_token');
}

App.js 수정

로그인에 성공하면, 발급받은 refresh_tokencookie에 저장한다!
handleLogin()메서드를 수정한다.

  function handleLogin(id, password) {
    let token = auth.login(id, password);

    if (token) {
      console.log('로그인 성공!');
      dispatch({
        type: 'SET_TOKEN',
        token: token,
        result: true,
      });
      auth.setRefreshTokenToCookie(token.refresh_token);    // cookie에 refresh_token 저장
    } else {
      console.log('로그인 실패');
      dispatch({
        type: 'SET_TOKEN',
        token: null,
        result: false,
      });
    }
  }

 

이제 로그인에 성공하면 쿠키에 refresh_token이 저장된다.
refresh_tokenaccess_token이 만료되었을 경우에 access_token을 발급받기 위한 토큰이다.

Refresh Token으로 로그인 유지하기

쿠키에 저장된 refresh_token값으로 access_token을 발급받고, 로그인을 유지시킨다.

auth.js 수정

getAccessToken()이라는 메서드를 만들었다.
쿠키에 저장된 리프레시 토큰을 꺼내서 (원래는 리프레시 토큰이 유효한지도 확인해야 함) 새로운 토큰을 발급하도록..

export function getAccessToken() {
  const refresh_token = cookies.get('refresh_token');
  if (refresh_token) {
    return {
      access_token: 'dj7H8Jduyf,bw&%dkhdkszd',
      refresh_token: 'djKJ/dio2jk*4KJHydhen,wlLlmddjk',
    };
  } else {
    return undefined;
  }
}

App.js 수정

useEffect()를 통해 새로운 탭이 열렸거나, 인증 여부가 달라질 경우 refresh_token으로 새롭게 access_token을 발급받는다.

  useEffect(() => {
    const token = auth.getAccessToken();
    if (token) {
      dispatch({
        type: 'SET_TOKEN',
        token: token,
        result: true,
      });
      auth.setRefreshTokenToCookie(token.refresh_token);
    } else {
      dispatch({
        type: 'DELETE_TOKEN',
      });
    }
  }, [authenticated]);

 

다른 탭에서도 로그인이 되어있는 상태

 

코드는.. 일단 JWT를 localStorage에 저장하지 않는 방법에 대해 이해한 것에 의의를 둔다...!!