[React] Axios interceptor를 사용한 토큰 관리

오형상·2023년 4월 6일
0

CoinToZ

목록 보기
7/9
post-thumbnail

Axios interceptor

axios에 포함된 기능으로, 요청이나 응답 전에 무엇인가를 수행해주거나, 오류 발생시에 수행할 것들을 미리 정의해 놓을 수 있는 기능

interceptor 도입 이유

  1. 매번 인증이 필요한 api 호출 시 헤더에 토큰을 담는게 번거로움.
  2. 중간에 코드 변경 시 전부 변경해줘야 하는 등 유지보수 어려움.

axios 생성

// src/components/pages/util/customApi.js
import axios from "axios";
import { refresh, refreshErrorHandle } from "./client";

const Api = axios.create({
  timeout: 10000,
  params: {},
});

Api.interceptors.request.use(refresh, refreshErrorHandle);

export default Api;

axios request, response 처리

✔️ moment를 이용하여 로그인 해서 받아온 accessToken의 만료 시간과 현재 시간의 차이를 통해 토큰이 만료되었는지 체크

✔️ 헤더에 refreshToken, accessToken, email 담은 후 GET /api/v1/users/reissuance 요청 보내 토큰 재발급

✔️ 재발급 받은 토큰을 쿠키로 재설정 및 헤더에 재발급 받은 accessToken 저장 후 리턴

⚠️ 토큰이 만료되지 않았다면 헤더에 기존 토큰을 담아 요청 보냄

// src/components/pages/util/client.js

import axios from "axios";
import moment from "moment";
import { setCookie, getCookie, removeCookie } from "./cookie";
import jwt_decode from "jwt-decode";

const refresh = async (config) => {
  const refreshToken = getCookie("refresh");
  const accessToken = getCookie("access");
  const decodePayload = jwt_decode(accessToken, { payload: true });
  const expireAt = new Date(decodePayload.exp) * 1000;

  // 토큰이 만료되었다면
  if (moment(expireAt).diff(moment()) < 0 && refreshToken) {
    console.log("토큰을 재발급합니다!");
    const expires =  moment().add('3','days').toDate();
    const paths = '/';

    //재발급 요청
    const res = await axios.get("/api/v1/users/reissuance", {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Authorization-refresh": `Bearer ${refreshToken}`,
        email: localStorage.getItem("email")
      }
    });
    console.log("재발급 성공");
    setCookie("access", res.headers.get("Authorization"),{paths, expires});
    setCookie("refresh", res.headers.get("Authorization-refresh"),{paths, expires});

    config.headers["Authorization"] = `Bearer ${getCookie("access")}`; // 토큰 교체

  }
  else {
    config.headers["Authorization"] = `Bearer ${accessToken}`;
  }

  return config;
};

const refreshErrorHandle = () => {
  removeCookie("refresh");
};

export { refresh, refreshErrorHandle };

사용 법

customApi.js 에서 Api를 불러와 기존 axios 처럼 사용하면 된다.

import * as React from 'react';
import { Button } from 'react-bootstrap';
import Api from './customApi';

export default function Test() {

  const getInfo = async () => {
    await Api.get("/api/v1/users")
    .then(function (response) {
      alert(response.data)
    })
    .catch(function (err) {
      console.log(err);
      alert("유저 정보 조회 실패")
    });
  }

  return (
    <>
      <Button
      variant="primary"
      onClick={getInfo}
      type="submit"
      sx={{ mt: 3, mb: 2 }}
      >
        조회 테스트
      </Button>
    </>
    
  );

}

참고자료

[React] Refresh Token 을 이용한 토큰 자동 갱신

0개의 댓글