JWT를 사용하는 것이 좋을까?
포스트
취소

JWT를 사용하는 것이 좋을까?

Rest(REpresentational State Transfer) API를 설계할 때 서버의 Stateless를 지키기 위해

그리고 MSA(MicroService Architecture)를 고려한 서비스를 개발할 때

사용자 인증과정에서 가장 먼저 떠오르는 것이 JWT이다.

JWT를 이용한다면 서버가 별도의 상태를 가질 필요가 없고 MSA로 구성된 여러 서비스가 하나의 세션DB를 조회해야 하는 역설적인 상황을 피할 수 있다.

다만, 서버의 Stateless를 위해서 JWT를 사용하는 것이 과연 옳은가에 대한 고민을 계속 하게된다.

서버에서 접속한 사용자에 대한 State가 없다면 포기해야 되는 기능들이 꽤 많다.

  1. 모든 디바이스에서 로그아웃
  2. 동시 접속 제한하기
  3. 한 사용자에게서 발생하는 비정상적인 트래픽 감지하기

그럼 JWT를 사용함으로써 얻는 장점은 어떤게 있을까?

우선 앞서 얘기했듯이 하나의 세션DB에 서비스의 전체가 영향을 받는 불상사를 피할 수 있다.

다음으론 자동로그인 기능에서 JWT를 사용할 경우 짧은 만료시간을 갖는 accessToken과 긴 refreshToken으로 구성하는 경우가 많은데

네트워크 상에서 accessToken이 탈취되었을 경우에도 해당 accessToken의 짧은 만료시간으로 약간의 보안적인 이점을 가져갈 수 있고 accessToken이 만료시간이 한참 지난 뒤에도 refreshToken을 이용해서 새로운 accessToken을 얻은 뒤 자연스럽게 다음 동작을 진행할 수 있다. (사실 이건 JWT를 통해 얻는 이점이라고 보기는 어렵지만)

이에 반해 세션으로 구성한다면 만료시간이 지났을 경우 사용자는 반드시 새로 로그인을 해야하기 때문에 불편함을 느낄 수 있고 이를 보완하기 위해서 session rolling을 가능하도록 한다면 네트워크 상에서 세션아이디가 탈취되었을 경우 그 위험성이 더욱 커질 것이다.

(refreshToken이 탈취된다면 비슷한 상황인 것 같긴 하지만…)

JWT를 사용하는 웹서비스는?

그럼 JWT를 사용하는 웹서비스가 어떤 것들이 있는지 확인해보고 싶어서 몇가지 서비스를 조사해봤다.

넷플릭스

NetflixId라는 쿠키로 462바이트의 데이터, 1년의 만료기간을 가진다.

동시 접속을 제한하기 위해서일 거라고 추측한다.

네이버

vibe, 네이버메인, 네이버쇼핑 세 개 정도 조사해봤는데 모두 같은 형식을 갖는다.

모두 다 naver.com의 서브도메인임에도 브라우저는 각각 다른 쿠키를 가지고 있는 점도 신기했고 3개의 쿠키로 관리되는 것도 신기했다.

위 서비스들은 NID_SES, NID_JKL, NID_AUT 세 개의 쿠키가 구성되있고 셋 중 하나만 삭제해도 로그아웃 된다.

NID_SES의 크기가 591바이트, 한달의 만료기간이고 HttpOnly 옵션과 Secure 옵션 모두 비활성화이다.

NID_JKL은 51바이트 2년의 만료기간 Secure 옵션만 활성화

NID_AUT는 71바이트 2년의 만료기간 HttpOnly 옵션만 활성화이다.

왜 HttpOnly옵션이랑 Secure옵션이 비활성화일까?

_naver_usersession_ 이라는 이름의 쿠키도 있었는데 43바이트에 5분의 만료시간을 갖는다. 살짝 이상한 점은 쿠키를 삭제해도 아무런 변화가 없고 새로고침했을 때도 바로 생기지도 않는다. 둘 다 HttpOnly 옵션과 Secure 옵션 모두 비활성화.

이 쿠키는 서비스별 체류시간을 측정하기 위한… 뭐 그런건가?

페이스북

sb라는 이름의 쿠키, 26바이트, 2년의 만료기간

c_user라는 이름의 쿠키, 21바이트, 1년의 만료기간, Secure 옵션만 활성화

c_user만 삭제했을 때는 현재 접속중인 계정이 로그아웃되지만 접속 가능한 계정 리스트가 남아있다.

sb까지 삭제했을 때는 접속 가능한 계정도 모두 사라진다.

로컬스토리지에 Session 이라는 키값도 있었는데 이건 어디에 쓰는 건지 삭제를 해봐도 자동으로 혼자 생성된다.

깃허브

user_session이라는 이름의 쿠키, 60바이트, 2주의 만료기간

이름에 한점 숨김이 없다. 2주의 만료기간이었으면 종종 새로 로그인을 했을텐데 그런 기억이 안나는 걸 보아하니 session rolling이 이루어지고 있는 것 같다.

깃허브 OAuth는 JWT가 아닌 accessToken을 준다.

조사하면서 알게 된 특이점은 깃허브는 로컬스토리지에서 엄청 많은 데이터를 사용한다.

??

대부분의 서비스에서 session을 사용하는 것 같다.

그리고 만료기간도 짧지 않다. 보안적인 측면은 ssl만으로도 충분한건가? 아니면 내부적으로 다른 프로세스를 동작시킬까?

JWT를 사용하는 웹서비스는!!

JWT를 사용하는 케이스는 업비트의 OPEN API에서 찾았다.

특이점은 accessKey와 secretKey를 모두 유저에게 발급한다는 점이다.

클라이언트는 payload에 accekey를 포함시키고 발급받은 secretKey로 JWT를 생성한 뒤 요청을 보내게 된다.

이러면 사용자도 secretKey를 관리해야하고 서버도 secretKey를 관리해야 한다. 게다가 업비트의 API는 요청 수 제한도 있기 때문에 서버에서 stateful하게 관리를 하고있을텐데 궂이 JWT를 이용해야 했는가 싶었지만 업비트의 API 호출방식을 살펴보면

  1. JWT를 검증

  2. payload에 hashed_query를 API로 전달된 쿼리와 비교해서 검증

으로 두 단계 검증을 거친다는 것을 알 수 있다.

일반적인 웹서비스에서는 서버에서 받은 JWT를 그대로 사용해서 API를 호출하지만

업비트의 API 서비스는 클라이언트가 요청을 포함한 JWT를 만들어내고 서버는 그 JWT를 해석하는 절차를 거쳐서 보안에 신경을 쓴 것이다.

결국

결국은 또, 케이스 바이 케이스 인가보다

아니 그 전에 Stateless 서버가 가능하긴 한건가 싶다.

MSA를 위해서 JWT를 꼭 좀 써보고 싶은 마음이 있어서 공부해봤지만 스스로를 설득하지 못하는 것 같다.

서버에서 Session 관리를 더 신경써야 하는게 맞는 것 같다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
Recently Updated
Tranding Tags
Contents

타입스크립트 인덱스

-

Tranding Tags