[React] 리액트에서 JWT(JSON Web Token)으로 로그인 구현하기

2022. 9. 4. 23:23Front-end/React

이번에 백엔드 개발자와 협업한 프로젝트에서 JWT 방식 로그인을 사용했는데, 간단하게 정리해볼까 한다.

JWT 토큰 방식 로그인의 순서는 다음과 같다.

  1. 클라이언트에서 서버에 로그인 요청을 보낸다.
  2. 요청 데이터에 문제가 없다면 서버는 새로운 토큰을 발급한다.
  3. 발급한 토큰을 응답 헤더에 담아 클라이언트로 보낸다.
  4. 클라이언트는 응답 헤더에서 토큰을 꺼내 웹 스토리지에 저장한다.

이후 사용자 인증이 필요한 요청 시 요청 헤더에 저장한 토큰을 담아서 요청하면 된다.

 

다음은 코드와 함께 JWT 인증 방식에 대해 알아보자.

 

로그인 요청

const handleLogin = async (data) => {
    return await axios.post("http://서버URL/users/logins", {
      email: data.email,
      password: data.password,
    });
  };

로그인 요청을 받은 서버는 토큰을 발급해 응답 헤더에 담아 클라이언트로 보낸다.

 

웹 스토리지에 토큰 저장

localStorage.setItem("accessToken", data.headers["authorization"]);
localStorage.setItem("refreshToken", data.headers["refresh-token"]);
navigate("/");

클라이언트는 응답 헤더에 있는 토큰을 웹 스토리지에 저장하고 메인 페이지로 이동한다.

 

그리고 요청할 때 토큰을 서버로 보내는 부분은 사용자 인증이 필요한 요청에 사용할 axios 객체를 만들고 interceptors를 사용했다. axios 인터셉터는 요청이나 응답을 가로채 원하는 작업을 수행할 수 있게 해 준다.

// 사용자 인증 axios 객체 생성
export const auth = axios.create({
  baseURL: process.env.REACT_APP_SERVER,
});

// 웹 스토리지에 저장된 토큰을 서버로 전송
auth.interceptors.request.use((config) => {
  config.headers["authorization"] = localStorage.getItem("accessToken");
  config.headers["refresh-token"] = localStorage.getItem("refreshToken");
  return config;
});

 

여기서 refresh token은 access token이 만료됐을 때 access token을 새로 발급해주기 위한 토큰이다. 클라이언트는 토큰의 만료 여부를 알 수 없다.

 

그래서 요청 헤더에 토큰을 담아 서버로 보냈을 때 서버가 토큰의 만료 여부를 확인하고 refresh 토큰이 유효하다면 서버는 새로운 access 토큰을 발급해 클라이언트로 보내준다.

 

그럼 클라이언트는 응답 헤더에 access 토큰이 있는 걸 확인하고 기존 토큰이 만료됐다는 사실을 알게 된다. 그다음 클라이언트는 기존 토큰을 삭제하고 리프레시된 토큰을 다시 저장하는 것이다.

 

그렇다면 클라이언트는 어떻게 매번 응답 헤더에 리프레시된 토큰이 있는지 확인할까?

 

이 또한 axios의 interceptors를 이용하면 간단하게 구현할 수 있다.

instance.interceptors.response.use((response) => {
  // 응답 헤더에 토큰이 있으면 true
  if (response.headers["authorization"]) {
    // 만료된 access 토큰 삭제
    localStorage.removeItem("accessToken");
    // 새로운 access 토큰 저장
    localStorage.setItem("accessToken", response.headers["authorization"]);
  } else if (response.data.error === "INVALID_TOKEN") { // refresh 토큰 만료
    localStorage.removeItem("accessToken"); // access 토큰 삭제
    localStorage.removeItem("refreshToken"); // refresh 토큰 삭제 
    alert("토큰이 만료되었습니다. 다시 로그인해주세요.");
  }
  return response;
});

두 번째 조건에 해당하는 구문은 주석으로 표기한 바와 같이 리프레시 토큰이 만료됐을 때 실행되는 구문이다.

 

참고로 토큰 유효기간은 access 토큰은 탈취될 가능성이 높으므로 보통 30분에서 2시간 정도로, refresh 토큰은 아예 유효기간을 두지 않거나 한 달에서 3개월까지 두는 곳도 있다고 한다.

 

 

JSON 웹 토큰 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. JSON 웹 토큰상태인터넷 표준최초 출판일2010년 12월 28일 (2010-12-28)마지막 버전RFC 75192015년 5월조직IETF약어JWT JSON 웹 토큰(JSON Web Token, JWT, "jot”[1])은 선택적 서명

ko.wikipedia.org

 

반응형