[React Native & 공통] 지극히 프론트엔드 개발자 관점에서의 액세스 토큰과 리프레시 토큰

김종혁·2023년 4월 28일
1
post-thumbnail

20230428

오늘은 AccessTokenRefreshToken에 대해서 알아보겠습니다.

백엔드 팀원은 제게 말합니다.

액세스토큰리프레시토큰을 줄테니 AccessToken이 만료되면 RefreshToken을 헤더에 담아서 보내라.

이게 당최 무슨 말일까요. 우리는 로그인을 계속 하고 있었던 것이 아닌걸까요?

1. 토큰이란 무엇인가?

우리는 주민등록번호를 하나씩 가지고 살아갑니다. 웹, 모바일 생태계에서도 마찬가지. 로그인 했을 때 우리가 누구인지 판명해주는 것이 바로 accessTokenrefreshToken입니다.

다른 주민등록번호로 할 수 있는 것들은 세션과 쿠키입니다. 이것에 대한 내용은 다른 글에서 알려드릴게요.
저는 글이 짧은게 가독성이 좋다고 생각해요.

2. 토큰 인증방식인 JWT(Json Web Token)을 활용해보자

  • 인증에 필요한 정보를 암호화시킨 토큰을 사용해 인증하는 방식입니다.
  • 내가 이사람이오! 인증하는 방식은 헤더에 AccessToken을 담아 서버에 보내는 방식입니다.
  • 토큰의 구성요소는 다음과 같습니다.
    - Header : 토큰의 암호화 방식, 타입 등
    - Payload : 서버에서 보낼 데이터. 유저의 고유 ID 값, 유효기간 등
    - Verify Signature : 인코딩한 Header + Payload + SECRET KEY + 서명
  • 그래서 우리는 AccessToken을 사용자인증이 필요한 페이지들에서 API의 헤더에 담아보내어 필요한 값들을 받아오게 됩니다.

3. 다만 액세스 토큰만으로는 취약합니다.

Access Token (JWT)를 이용한 인증 방식의 문제점이 있습니다.
제3자에게 토큰을 탈취당할 경우 보안에 취약할 수 있다는 점입니다.
이 점을 해결하기 위해 유효기간을 짧게 하면, 그만큼 사용자가 로그인을 자주 해야 하는 불편함이 생기겠죠.

Access Token의 유효기간을 짧게 하면서도, 사용자의 불편함을 줄일 수 있는 방법으로 나온 것이 Refresh Token입니다.

Refresh TokenAccess Token과 똑같은 형태의 JWT입니다.
Refresh Token은, 처음에 로그인을 완료했을 때 Access Token과 동시에 발급을 합니다.
Refresh Token은 긴 유효기간을 가지면서, Access Token이 만료되었을 때 Access Token을 새로 발급해주는 열쇠로 사용되는데, 예제는 다음과 같습니다.

# React Native에서 TypeScript로 작성된 기본코드입니다.

import AsyncStorage from "@react-native-async-storage/async-storage";
import axios from "axios";
import Config from "react-native-config";


# 앱의 localstorage라고 할 수 있는 AsyncStorage에 저장한 액세스 토큰을 가져오는 함수

async function getAccessToken(req?: any): Promise<string | null> {
  const token = await AsyncStorage.getItem("accessToken");
  return token;
}

# 앱의 localstorage라고 할 수 있는 AsyncStorage에 저장한 리프레시 토큰을 가져오는 함수

async function getRefreshToken(req?: any): Promise<string | null> {
  const refreshToken = await AsyncStorage.getItem("refreshToken");
  return refreshToken;
}

# 리프레시 토큰을 헤더에 담아 보낸 API주소에서 accessToken을 받아와서 다시 저장하는 함수

async function saveAccessToken(token: string): Promise<void> {
  await AsyncStorage.setItem("accessToken", token);
}


# 새로운 accessToken을 받아오는 함수
# RN에서는 env.PROCESS_ 가 아니라 Config."env 내용" 으로 baseURL을 구성한다.

async function getNewAccessToken(
  refreshToken: string
): Promise<string | null | undefined> {
  try {
    const response = await axios.get(
      `${Config.API_URL}/user/token-reissurance`,
      {
        headers: {
          "X-REFRESH-TOKEN": refreshToken,
        },
      }
    );
    if (response.data && response.data.accessToken) {
      await saveAccessToken(response.data.accessToken);
      return response.data.accessToken;
    }
  } catch (error) {
    console.error("Error new access token: ", error);
    return null;
  }
}
  • 이렇듯 Refresh Token의 유효기간이 만료되었을 경우에만 사용자가 새로 로그인을 하면 됩니다.
  • 단, Refresh Token도 탈취될 가능성이 있기 때문에 적절한 유효기간 설정이 필요하다는 점입니다. (주로 2주)

그렇지만 해당 함수를 매번 getAccessToken을 호출하여 API 주소에 postget HTTP_METHOD를 사용하면 번거롭겠죠?
다음에는 AXIOS의 모듈화를 통해 사용하는 모든 API에서 기본으로 만들어놓은 AXIOS와 인터셉터에 대한 개념을 이야기해보겠습니다.

AccessToken은 왜 탈취당하기 쉬운지에 대해서도 좀 더 알아보면 좋을 것 같습니다.

profile
세상을 한 걸음씩 발전시키고 싶습니다.

0개의 댓글