개발 기록/Javascript

Javascript/jQuery - Access Token 자동 갱신 소스코드

JasonM 2023. 6. 12. 14:59
반응형

JWT Access Token을 사용한 웹 어플리케이션에서 서버로 API를 요청할 때마다 Access Token을 담아서 보내야 하는데, 이때 Access Token이 만료된 경우 Refresh Token을 이용한 Access Token의 갱신이 필요하다. 
 
처음 화면 로딩 시 메뉴에 로그인 정보를 표시해준다거나, 화면을 새로고침 하거나, 사용자가 특정 화면을 열어 놓고 한참 지나서 데이터를 조회하려고 하는 경우 등을 고려해서 언제든 서버로 API 요청 시 항상 Access Token의 유효성을 체크해서 만료 시 Refresh Token을 이용해서 자동으로 Access Token을 갱신하는 스크립트를 작성 해 봤다.
 
특별한 아니고 Javascript/jQuery Ajax를 이용해서 API를 서버에 요청해 보고 권한 에러 시 자동으로 refresh API를 호출해서 갱신 후 다시 원래 사용하려던 API를 다시 호출해주는 로직이다.
 
[참고] 아래 소스코드는 서버에서 Token 발급 시 HTTP Only 쿠키(Cookie)에 Access Token 및 Refresh Token를 저장해 둔 상태이다.
 

사용 방법 (HTML 화면)

<script src="/js/common.js"></script>
<script>

$(function () {
  getNoticeList()
});

function getNoticeList(){
  var reqBody = {};
  reqBody.item = something;
			
  sendXMLHttpRequest("GET", "/board/notice/list", $.param(reqBody), sNoticeList, COM_AjaxFailCallBack);
}

var sNoticeList = function sNoticeListCallBack(list){
  console.log(list);
}

</script>

 
공지사항 목록을 불러오는 화면을 예로 설명해 보면, HTML 화면에서 페이지 로딩이 모두 끝난 후 위와 같이 getNoticeList() 함수를 호출해서 서버에 저장되어 있는 공지사항 목록을 불러오는 API를 호출한다.
 
이때 sendXMLHttpRequest()라는 공통 함수를 사용해서 API를 호출하면/board/notice/list 라는 API 요청 시 Access Token이 만료되었더라도 자동으로 토큰을 갱신한 뒤 다시 /board/notice/list API를 호출한다.   
 
sNoticeList/board/notice/list 가 정상적으로 데이터를 불러온 경우에 수행되는 callback 함수이며, COM_AjaxFailCallBack 함수는 에러가 난 경우 공통적으로 수행하는 Callback 함수다. 상황에 맞게 공통으로 쓰거나 sNoticeList와 같이 화면별로 다르게 callback 함수를 만들어서 사용할 수도 있다.
 
 

반응형

 

공통 AJAX Reqeust 함수 (common.js)

function sendXMLHttpRequest(type, url, rq, successCallBack, failCallBack){
  $.ajax({
    type : type,
    contentType: "application/json;charset=UTF-8",
    dataType: "json",
    url : url,
    data : rq,
    success : function(data){
      successCallBack(data);
    },
    error: function(xhr, statusText, err){
      if(xhr.status == 401){
        if(xhr.responseJSON.code == "[Custom Business Error Code]"){
          $.ajax({
            type : "POST",
            contentType: "application/json;charset=UTF-8",
            dataType: "json",
            url : "/auth/v2/token/refresh",
            success : function(data){
              $.ajax({
                type : type,
                contentType: "application/json;charset=UTF-8",
                dataType: "json",
                url : url,
                data : rq,
                success : function(data){
                  successCallBack(data);
                },
                error: function(xhr, statusText, err){
                  failCallBack(xhr);
                }
              });
            },
            error: function(xhr, statusText, err){
              Swal.fire("인증 오류", xhr.responseJSON.message, "warning").then(function(){
                location.href = "/login";
              });
            }
          }); 
        }else{
          Swal.fire("시스템 오류", "인증 서비스 접속에 실패했습니다.", "warning").then(function(){
            location.href = "/login";
          });
        }
      }else{
        failCallBack(xhr);
      }
    }
  });
}

 
최대 3번의 ajax 요청을 보내게 되며, 흐름은 아래와 같다. 

  1. 모든 ajax 요청을 보낼 때 위 함수를 통해 사용.
  2. 서버에서 Access Token이 유효하다고 판단한 경우 바로 정상 응답.
  3. 서버에서 401 에러를 준 경우 중 서버가 지정한 커스텀 비즈니스 에러코드가 반환된 경우, Access Token이 유효하지 않은 것으로 판단
  4. 위 경우 ajax로 access token 갱신 요청 API를 호출 (url : "/auth/v2/token/refresh")
  5. Refresh에 성공한 경우, 다시 처음 요청한 Endpoint로 API 요청

 

공통 Error Callback 함수 (common.js)

var COM_AjaxFailCallBack = function ajaxFailCallBack(data){
  if(data.responseJSON != null){
    Swal.fire("데이터 조회 실패", data.responseJSON.exception_message, "warning");
  }else{
    Swal.fire("데이터 조회 실패", "서버에서 데이터를 불러오지 못했습니다.", "warning");
  }
}

 

반응형