JS소스모듈

토큰 만료 갱신

JoyYellow 2022. 11. 21. 17:14
import axios from 'axios';

let isRefreshing = false;
let pendingQueue = [];

const processQueue = (error, token = null) => {
	pendingQueue.forEach(prom => {
		if (error) {
			prom.reject(error)
		} else {
			prom.resolve(token)
		}
	})
	pendingQueue = []
}


const axiosJwt = axios.create({
	baseURL: process.env.NODE_ENV === 'development' ? process.env.APP_AXIOS_URL : config.BASE_URL;
})

axiosJwt.interceptors.request.use(
	(response) => response,
    (error), refreshToken(error, axiosJwt)
)

function refreshToken(error, axiosObj) {
	const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
    	is (isRefreshing) {
        	return new Promise((resolve, reject) => {
            	pendingQueue.push({ resolve, reject })
            }).then(() => {
                originalRequest.headers.Authorization = 'Bearer ' + store.getters.getJwt
            }).catch((err) => {
            	return Promise.reject(err)
            })
        }
        originalRequest._retry = true
        isRefreshing = true
        const token = store.getters.getRefreshToken
        return new Promise(function (resolve, reject) {
        	axios.post(url, {
            	jwt: store.getters.getJwt,
                refresh_token: token,
            }).then((res) => {
            	if (res.status === 200) {
                	if (res.data.jwt && res.data.access_token && res.data.refresh_token) {
                    	store.commit('setJwt', res.data.jwt);
                        store.scommit('setAccessToken', res.data.access_token);
                        sotre.commit('setRefreshToken', res.data.refres_token);
                        originalRequest.headers.Authorization = 'Bearer ' + res.data.jwt;
                        axiosObj.defaults.headers.Authorization = 'Bearer'
                        resolve(axiosObj(originalRequest))
                    }
                }
            }).catch((err) => {
            	console.log('refreshToken err: ', err);
                window.localStorage.removeItem('vuex');
                window.localStorage.removeItem('language');
                window.localStorage.removeItem('_secure_Is_metadata');
                location.href = loginUrl
                processQueue(err, null)
                reject(err)
            }).finally(() => {
            	isRefreshing = false
            })
        })
    }
    return Promise.reject(error
}

https://medium.com/swlh/handling-access-and-refresh-tokens-using-axios-interceptors-3970b601a5da

 

Handling Access and Refresh Tokens using Axios Interceptors.

Axios is a promise-based HTTP client which is written in JavaScript to perform HTTP communications. It has one powerful feature called…

medium.com

 

 

import axios from 'axios'
import { store } from '@/store'
// import router from '@/router'

// 인스턴스 생성
export const apiAxios = axios.create({
  // eslint-disable-next-line no-undef
  baseURL: process.env.NODE_ENV === 'development' ? process.env.VUE_APP_AXIOS_URL : config.BASE_URL,
})

// then이나 catch로 처리되기 전에 요청이나 응답을 가로챌 수 있다.
// interceptor 토큰 설정 전역 처리
apiAxios.interceptors.request.use(config => {
  // 인증토큰
  if (store.getters.getJwt) {
    config.headers.Authorization = 'Bearer ' + store.getters.getJwt
  }
  return config
})

// api 통신간 토큰 만료시 토큰 갱신 로직
let isRefreshing = false
let pengingQueue = []

const processQueue = (error, token = null) => {
  pengingQueue.forEach(prom => {
    if (error) {
      prom.reject(error)
    } else {
      prom.resolve(token)
    }
  })
  pengingQueue = []
}

apiAxios.interceptors.response.use(
  function (response) {
    return response
  },
  function (error) {
    const originalRequest = error.config
    if (error.response.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          pengingQueue.push({ resolve, reject })
        }).then(token => {
          originalRequest.headers.Authorization = 'Bearer ' + store.getters.getJwt
          return axios(originalRequest)
        }).catch(err => {
          return Promise.reject(err)
        })
      }
      originalRequest._retry = true
      isRefreshing = true
      const token = store.getters.getRefresh_token
      return new Promise(function (resolve, reject) {
        apiAxios.post('/api/user/refresh', {
          jwt: store.getters.getJwt,
          refreshToken: token,
        })
          .then(res => {
            if (res.status === 200) {
              if (res.data.jwt && res.data.access_token && res.data.refresh_token) {
                this.$store.commit('setJwt', res.data.jwt)
                this.$store.commit('setAccess_token', res.data.access_token)
                this.$store.commit('setRefresh_token', res.data.refresh_token)
                originalRequest.headers.Authorization = 'Bearer ' + res.data.jwt
                apiAxios.defaults.headers.Authorization = 'Bearer ' + res.data.jwt
                processQueue(null, res.data.jwt)
                resolve(axios(originalRequest))
              }
            }
          })
          .catch(err => {
            console.log('err : ', err)
            // 로그아웃 처리 해야한다.
            // 로그인 페이지로 이동?
            processQueue(err, null)
            reject(err)
          })
          .finally(() => { isRefreshing = false })
      })
    }
    return Promise.reject(error)
  },
)

export default apiAxios