플랫폼, 사이트, 모바일 앱등 대부분의 상용화된 애플리케이션들은 회원가입 및 로그인 기능이 구현되어있다.
단순히 이 기능들을 구현하는 것은 간단하지만 보다 보안성이 좋게 만드려면 약간의 기술들이 필요하다.
상대적으로 간단한 기술인 jsonwebtoken 을 구현하는 방법을 정리할 것이다.
서버로는 Node.js express 를 사용하였으며, npm 모듈인 jsonwebtoken 을 사용하였다.
현재 포스트에서 다루는 token 제어는 기술보다 사이클을 이해하는 것이 더 중요한데,
해당 기능을 구현하면서 왜 두가지 token 을 사용하고 어떤 방식으로 동작되는지를 찾아보았다.
accesstoken 이란 말 그대로 접근(access)을 제어하는 token 이다. 즉 이 token 을 통해
사용자 본인이라는 인증이 가능하게 하는 token 인 것이다.
이 token 에는 서버에서 내부적으로 복호화 등을 하여 사용자임을 판별할 수 있는 정보들이 payload(정보) 로 포함된다.
refreshtoken 은 사용자를 판별할 수 있는 정보를 담고 있지는 않지만 accesstoken 을 재발급 할때 사용하는 token 이다.
우선 사용자는 제일 처음으로 로그인을 할 것이다. 로그인 전에는 accesstoken, refreshtoken 을 가지고 있지 않은 상태이다.
로그인을 하게되면 첫번째 accesstoken 과 refreshtoken 을 서버로부터 발급받게된다.
refreshtoken 은 DB 에 저장하고 이후 재발급 및 만료 부분에서 유효성을 검증하는 용도로 사용된다.
이렇게 사용자(client) 는 특정 저장소, 예를들어 local storage 에 두가지 token 을 가지고 있다가 서버로 요청을 할 때 같이 보내는 것이다.
요청을 받은 서버는 정보를 반환해주기 전에 우선적으로 accesstoken 을 분석해서 만료된 token 인지, 문제가 있는 token 인지 유효성(availability) 을 판별한다.
판별후 문제가 없다면 정보를 반환한다.
token 재발급 및 만료를 담당하는 서버 api 를 생성한다.
이 api 는 주기적, 또는 특정 요청을 하기전에 우선적으로 요청하여 token 의 유효성을 판단한다.
accesstoken 과 refreshtoken 을 받아서 우선적으로 refreshtoken 의 유효성을 DB 와 비교하여 판단한다.
refreshtoken 이 문제가 있다면 즉시 만료를 시켜 client 에서 로그아웃 되도록 조치하고, refreshtoken 이 문제가 없다면 이제 만료가 되었는지 확인한다. 이때 경우가 네가지가 존재한다.
*RTR(Refresh Token Rotation) : token 을 사용해서 사용자 인증을 시도하였을 경우 기존 token 은 만료 또는 폐기하고 새로운 token 을 발급하는 방식으로, 보안면에서 좋다.
accesstoken 이나 refreshtoken 이 탈취되었을 경우 만료시간이 되기 전까지는 해커가 정보를 무단으로 사용하게 둘 수 밖에 없으므로 accesstoken 의 시간은 짧게 두는데, 이럴 경우 사용자 입장에서는 빈번한 로그아웃 경험을 하게 될 수 있다.
refreshtoken 을 사용하는 이유는 정상적인 사용자가 잦은 로그아웃 경험을 하게 하지 않으면서 사용자의 정보를 보호하는 것이 주 목적으로, 이렇게 refreshtoken 을 도입하되 RTR 방식 또한 같이 도입하여 주기적으로 token 들을 재발급하면서 보안성도 높이는 것이다.
refreshtoken 의 경우 DB 에 기록돼있으므로 사용자 인증을 시도했을때 문제가 있는 token 이거나 이미 만료된 token 일 경우 만료를 시켜 버리기 때문에 정상적인 사용자와 해커 모두에게서 로그아웃 조치가 되므로 사용자 정보 탈취를 보호할 수 있는것이다.
npm install jsonwebtoken
우선 서버에서 jsonwebtoken 을 install 한다.
token 을 생성하는 방법은 아주 간단하다.
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '1h' });
상기는 npm 에 등록돼있는 jsonwebtoken 의 메뉴얼에서 가져온 코드인데,
총 인자 세개를 받고있다.
첫번째 데이터(payload), 두번째가 암호키, 세번째는 옵션으로 만료일자등을 지정할 수 있다.
자세한 내용은 참조에 표시된 사이트를 참조하면 된다.
jsonwebtoken 의 경우 base64 로 인코딩 되는것이므로 간단하게 디코딩할 경우
내용을 확인할 수 있어 보안상 중요한 데이터는 포함하지 않는것이 좋다.
혹은 암호화를 시켜서 payload 에 담는 방법도 있다.
REFS