Axios 인터셉터를 활용한 JWT 갱신

devPomme·2023년 5월 22일
0
post-thumbnail

Axios 인터셉터

then 또는 catch로 처리되기 전에 요청과 응답을 가로챌수 있다. 공식문서

인터셉터를 활용해 JWT 갱신하기

  • /api/login POST 호출 및 성공시 accessToken과 refreshToken 을 응답으로 받는다.

  • /api/reissue POST 호출 시 accessToken 과 refreshToken을 body 에 담아 POST 요청해야하고, 성공 시 accessToken과 갱신된 refreshToken 을 응답으로 받는다.

  • /api/profile get 호출 시 axios 에서 제공하는 인터셉터 기능을 활용해 토큰 갱신 및 권한 처리를 실행해야한다.

    • axios Interceptor에서는 Local Storage의 토큰과 Response body의 토큰을 비교한 후 변경이 된 경우 Local Storage에 토큰 정보를 업데이트 처리한다.
  • 나는 주로 커스텀 인스턴스를 생성해서 API 모듈화를 함으로 인스턴스에 인터셉터를 추가해주겠다.

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

const authAxios: AxiosInstance = axios.create({
  baseURL: `${process.env.BASE_URL}/api/auth`,
  withCredentials: true,
});

// 토큰을 Local Storage에 저장하는 함수
const saveTokenToLocalStorage = (accessToken: string, refreshToken: string) => {
  localStorage.setItem('accessToken', accessToken);
  localStorage.setItem('refreshToken', refreshToken);
};

// 토큰을 Local Storage에서 가져오는 함수
const getTokenFromLocalStorage = (): {
  accessToken: string | null;
  refreshToken: string | null;
} => {
  const accessToken = localStorage.getItem('accessToken');
  const refreshToken = localStorage.getItem('refreshToken');
  return { accessToken, refreshToken };
};

// axios 인스턴스에 인터셉터 추가
authAxios.interceptors.request.use(async (config: AxiosRequestConfig) => {
  const { accessToken, refreshToken } = getTokenFromLocalStorage();

  if (accessToken) {
    config.headers.Authorization = `Bearer ${accessToken}`;
  }

  return config;
});

authAxios.interceptors.response.use(
  async (response: AxiosResponse) => {
    const { accessToken, refreshToken } = getTokenFromLocalStorage();
    const { url, data } = response.config;

    if (url === '/api/login') {
      // '/api/login' 요청에 대한 처리
      const { accessToken: newAccessToken, refreshToken: newRefreshToken } =
        response.data;
      saveTokenToLocalStorage(newAccessToken, newRefreshToken);
    } else if (url === '/api/reissue') {
      // '/api/reissue' 요청에 대한 처리
      const { accessToken: newAccessToken } = response.data;
      saveTokenToLocalStorage(newAccessToken, refreshToken as string);
    } else if (url === '/api/profile' && data) {
      // '/api/profile' 요청에 대한 처리
      const { accessToken: newAccessToken } = data;
      if (newAccessToken && newAccessToken !== accessToken) {
        saveTokenToLocalStorage(newAccessToken, refreshToken as string);
      }
    }

    return response;
  },
  async (error) => {
    // 에러 처리
    // ...

    return Promise.reject(error);
  },
);

export default authAxios;

authAxios.interceptors.request.use는 요청을 보내기 전에 실행되며, 헤더에 접근 토큰(accessToken)을 추가한다.

authAxios.interceptors.response.use는 응답을 받은 후 실행되며, 응답을 확인하고 필요한 경우 토큰을 업데이트한다.

profile
헌신하고 확장하는 삶

0개의 댓글