replace session on front side( json web token )

replace session on front side

전통적으로 웹사이트 로그인부분 처리와 관련해서 server side에서 session에 담는게 일반적이다.
모든사이트가 그렇진않지만 요즘은 RESTFUL 기반 client와 분리하여 독립적으로 개발하는곳도 심심지않게 볼수있다.
이렇게 server side와 client side를 분리하게되면 분명 다양한 이점이 존재한다.
첫번쨰로는 불필요한 빌드를 방지할수있으며( 수정사항 side만 재배포 )
두번째로는 독립적으로 서비스로직이 존재하므로 확장과 시스템자원을 효율적으로 관리할수있다.( backend frontend 담당 역활이 분명히 나뉘어져있어 아키텍처 관점으로 이해하기쉽다. )
이렇게 분리된 backend 와 fronted가 존재할시 로그인관련처리 역시 session을 사용하게되는데 backend가 n 의 클러스터기반에서는 session을 관리하는 server를 따로두어야할것이다.( redis session을 사용한다던지.. )
session을 쓰지않고 로그인 handling을 할수없을까… 하다가 생각한게 jwt( json web token ) 이다.

jwt( json web token )

일단 jwt가 무었인지부터 알아보자.
jwt는 oath2 의 인증 방식을 대체하기위해 나온 메커니즘으로 인증 token을 인증서버에 요청하여 누가 요청하였는지 identify하는 oatuh2와는 달리 token에 존재하는 사용자정보를 기반으로 인증 server를 거치지않고 service backend에서 바로 비지니스로직처리를 가능하게한다.
하지만 oauth2의 장점은 보안에 용이하지만 인증서버를 구축해야한다는점. 시스템적인 자원의 소모가 큰 반면 jwt는 시스템적인 자원은 효율적으로 사용하되 보안 관련 이슈가 존재한다.
다음의 jwt token을 https://jwt.io/ 에서 확인하면 token의 내포된 header와 payload가 확인된다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lSWQiOjEsImlhdCI6MTUyNjE5NTMyNCwiZXhwIjoxNTI2MTk1Mzg0fQ.0B_HNaVdJ2AgUJOQctYMKt56_2fLEXnldBpSBzcNMiU

그러면 제3자가 악용하여 token 내용을 변조하여 api server에 요청할수있지않을까?
결론적으론 요청은할순있지만 변조된 token으로 server side에서 checking이 가능하다.
jwt의 token 구조는 header.payload.signature로 구성되어있으며 header와 payload를 base64로 인코딩된 값을 server side에서 소유하고있는 secret key를 통해 hashing 한다. 그리고 hashing 된 hash 값을 base64로 인코딩하게되면 signature 가 된다.
만약 누군가 token을 변조하였다면 signature부분의 값이 달라지기에 변조된 token임을 알수있다. ( secret key로 hashing된 값이 달라지기에 )

delegate login process on front side

jwt를 사용하게되면 사용자 인증( authe ntication )이 server side에서 담당하게될 역활중 하나이며 이런 인증은 보통 client에서 header에 token 정보를 함께 요청( request ) 한다.
다시말해 인증되지않은 사용자는 server side로 api call을 할수없다.
그럼 인증과 login 처리 session은 무슨 관련이있는것인가.
session은 일반적으로 만료시간( expire time )이 정해져있다. ( 언제든지 접속할때마다 로그인이 되어있다면 server side에서 엄청난 자원낭비가될것이다 )
하지만 jwt나 oauth2 방식을 이용하면 무한적으로 로그인되어있는 웹사이트도 개발가능하다.
인스타그램이나 페이스북, 또는 국내 특정 코인 거래소에서 이런 현상을 볼수있는데 ( 사이트를 들어갈때마다 로그인이 자동으로 되어있다. )
아마도 그런 대기업들은 jwt 보다는 보안적으로좋은 oauth2 방식을 이용하는듯하다 ( 추측 ).
필자는 jwt를 기반으로 client side에서 일정시간 또는 무한정 로그인 처리를 할수있도록 다음과같이 프로세스를 정의하였다.

  1. client가 로그인한다.
  2. server에서 expire time이 작은 accesstoken과 accesstoken보다 expire time이 긴 refreshtoken을 발급한다.
  3. client는 server로부터 발급받은 accesstoken과 refreshtoken을 localstorage에 저장한다.
  4. client는 모든 api call시 accesstoken 을 header에 실어서 요청한다.
  5. accesstoken이 만료되면 refreshtoken을 통해 accesstoken과 refreshtoken을 재발급 받는다.

예를들어

  • accesstoken expire time이 발급일로부터 3일 이라고 가정
  • refreshtoken expire time이 발급일로부터 7일 이라고 가정
  • client 사용자 로그인 -> accesstoken refreshtoken localstorage 저장
  • 3일동안은 client가 api call을 통해 비지니스로직을 수행
  • 3일이후 어느순간부터 server로 부터 error code와 함께 expire token message를 response
  • errorcode에 따른 분기로 refreshtoken을 header에 넣고 body에 accesstoken을 request
  • server는 accesstoken과 refreshtoken 재발급 -> accesstoken refreshtoken localstorage 저장
  • 무한반복 ( 그렇다면 token 발급일로부터 8일이상 client가 어떠한 api call을 요청하지않으면 ? -> 재로그인 )

token expire time에 따라 재 로그인 term이 달라지겠지만 refreshtoken의 expire time이 길면 무한정 로그인된 상태도 가능하다
하지만 refreshtoken이 너무긴 expire time 보다는 일정기간동안 접속하지않으면 재로그인하는 방식으로 유도하는것이 좋을듯하다

참고

jwt의 expire date 는 utc timezone 기반으로 동작하여 local timezone에 관한 이슈는 생각하지않아도 될듯하다.
jwt는 npmjs https://www.npmjs.com/package/jsonwebtoken 에서 가능하다.