KassyLog

Refresh Token 본문

react

Refresh Token

Kassy_kim 2022. 12. 15. 20:46


JWT 토큰 인증 방식은 제 3자에게 토큰이 탈취되는 경우 보안에 취약하다는 단점이 있어 토큰에 유효기간을 부여하여 보안을 강화하게 되는데, 유효기간이 짧으면 사용자는 계속 로그인을 다시 해야하기 때문에 불편해 진다. 여기서 사용할 수 있는 것이 Refresh Token을 활용한 토큰 리프레시다.


다른 블로그를 참고해서 가져온 사진은 이와 같다.

 

 

 

 

 

 

 

 

 

 

 

 

 

여기서 내가 나만의 언어로 생각해본 리프레시 토큰의 인터셉터 작동과정을 대화체로 설명해보겠다!

서버: 너 토큰 만료 됐으니까 리프레시토큰으로 너인거 증명해~
클라이언트: 앗! 나 리프레시토큰 챙겨왔어! 얼렁 통과시켜줘
서버: 음~ 알겠어. 다음에 또 챙겨와~

 

alert은 sweetalert2 라이러리를 활용해서 구현했으며 내가 실제로 구현한 코드는 아래와 같다

//Api.js

import axios from "axios";
import Swal from "sweetalert2";
import { useState } from "react";

export const api = axios.create({
  baseURL: process.env.REACT_APP_BASE_URL,
  headers: {
    "content-type": "application/json;charset=UTF-8",
    accept: "application/json",
  },
});

//요청 api에 토큰을 실어줌
api.interceptors.request.use((config) => {
  // console.log("----------------> request", config);
  const token = sessionStorage.getItem("accessToken");
  // console.log("액세스토큰나오니?", token);
  config.headers.common["Authorization"] = `${token}`;
  return config;
});

// response interceptors
api.interceptors.response.use(
  (response) => {
    // console.log("--------------> response", response);
    return response;
  },
  async (error) => {
    const { config } = error;
    const originalRequest = config;

    // 401 에러 발생시 액세스토큰 만료되었을 때, 리프레시토큰 보내기
    if (error.response.data.message === "Access token is not valid") {
      // console.log("1. 액세스토큰 만료됐으니 리프레시를 보내거라");
      const refreshToken = sessionStorage.getItem("refreshToken");
      // console.log("2. 리프레시 나오니?", refreshToken);
      // token refresh 요청
      return await axios
        .post(process.env.REACT_APP_BASE_URL + "/auth/token", {
          reAuthorization: `${refreshToken}`,
        })
        .then((res) => {
          // console.log("3. 액세스", res);
          //토큰 리프레시 후 액세스토큰을 서버에서 준다면? 어디에 담아두는 지 찾아서 조건문에 넣어두기
          if (res.data.access_token) {
            // console.log("4. 재발급 토큰", res.data.access_token);
            // access token이 재발급 된 상태,
            sessionStorage.setItem("accessToken", res.data.access_token);
            originalRequest.headers.Authorization = `${res.data.access_token}`;
            // console.log('original : ', originalRequest)
            return axios(originalRequest);
          }
        })
        .catch((err) => {
          const [alertModal, setAlertModal] = useState(false);
          const [alertData, setAlertData] = useState("");

          // console.log("3. 리프레시만료", err);
          //리프레시 토큰이 만료됐다면?
          if (err.response.data.message === "Refresh token is not valid") {
            sessionStorage.removeItem("userName");
            sessionStorage.removeItem("userId");
            sessionStorage.removeItem("email");
            sessionStorage.removeItem("refreshToken");
            sessionStorage.removeItem("accessToken");

            Swal.fire({
              title: "재로그인이 필요합니다.",
              text: "로그인 시간이 만료되었습니다.",
              icon: "warning",
              confirmButtonColor: "#616AC5",
              confirmButtonText: "재로그인하기",
            }).then((result) => {
              if (result.isConfirmed) {
                window.location.href = process.env.REACT_APP_FRONT_URL + `/login`;
              }
            });
          }
        });
    }
  }
);

 

로직파일에서 import해서 활용한 코드는 아래와 같다.

import { api } from "#utils/Api";
...
const api호출함수 = () => {
    api
      .method(`url`)
      .then((res) => {
        // console.log("성공응답?: ", res.data);
      })
      .catch((err) => {
        // console.log('실패응답:', err)
      });
  };

 

보통 리프레시 토큰으로 토큰 리프레시 작동 방법에는 2가지가 있다.

1. 매번 access token과 refresh token 을 같이 보낸다.

2. access token으로 api를 호출하고 토큰 만료 오류가 온다면 그때 refresh token을 보낸다.

나는 이 두가지 방법 중 2번을 채택하여 활용한 방법이고 요즘은 불필요한 api 호출을 줄이기 위해 1번을 더 많이 사용한다고 한다.

'react' 카테고리의 다른 글

리코일  (0) 2023.03.27
리액트 쿼리  (0) 2023.03.27
emotion과 styled-components  (0) 2023.03.26
craco란?  (0) 2022.12.16
사진 다운로드 기능  (0) 2022.12.13