Access Token, Refresh Token 이란
JWT 를 이용하면서 처음에는 엑세스 토큰만을 가지고 모든 프로젝트를 진행했었습니다.
그런데 처음에는 이에 대해서 깊이 생각하지 않았고 또, 실제로 프로젝트 진행 중에는 이로 인해서 문제가 발생하거나 불편함을 겪지는 못했습니다.
그만큼 작고 가벼운 프로젝트였고 토큰의 생존시간이 길었기 때문입니다.
물론 토큰의 만료시간으로 인해 불편함이 생긴적도 없었고 기능 개발을 하는것에도 충분히 바빴기 때문이었습니다.
그런데, 지난번 글에서 JWT 에 대해서 정리하면서 하는김에 이와 연관되서 같이 사용했던 Access Token 과 Refresh Token 에 대해서도 재차 정리하면 좋을 것 같아서 이 글을 작성하게 되었습니다.
우선 내가 어떻게 알고 있느지가 궁금해서 검색하기 전에 일부 정리해볼까 합니다.
내가 진행했던 프로젝트를 기준으로 로그인 및 로그아웃 상황을 예시로 들어서 설명하자면..
AccessToken
- 로그인할 때 발급이 됩니다.
- 해당 토큰 안에 있는 유저 정보를 통해 어떤 유저가 요청을 하는지 알 수 있습니다.
- 일반적으로는 리프레쉬가 같이 사용시에는 수명을 짧게 설정합니다. (대게 5~10분 정도로 알고 있습니다)
- 만료시 사용자는 재로그인을 해서 새롭게 발급 받아야 합니다. 하지만 리프레쉬가 있을 경우 리프레쉬의 수명이 만료되기 전까지는 재로그인할 필요가 없습니다.
RefreshToken
- 액세스 토큰의 단점인 보안성강화와 잦은 재로그인을 해결하기 위해서 나온 개념입니다.
- 리프레쉬 토큰은 서버에 저장되기 때문에 탈취당했다고 판단되면 서버에서 리프레쉬 토큰을 삭제해 강제 로그아웃이 가능합니다.
- 앞서 말한 액세스 토큰이 만료시 리프레쉬 토큰을 검증해 액세스를 재발급 받는 식으로 동작합니다.
즉, 액세스 토큰의 재발급을 위한 키로서 작동합니다.
이제껏 사용한 액세스 토큰과 리프레쉬 토큰의 개념을 검색하지 않고 머리속의 내용을 풀어서 정리하면 위와 같습니다.
다만, 이를 깊게 파본적은 없기에 이 기회에 다시 정리해볼까 합니다.
이번에도 참고하게 되어버린 인파님의 글...
[WEB] 📚 Access Token & Refresh Token 원리 (feat. JWT)
Access Token과 Refresh Token 이번 포스팅에서는 기본 JWT 방식의 인증(보안) 강화 방식인 Access Token & Refresh Token 인증 방식에 대해 알아보겠다. 먼저 JWT(Json Web Token) 에 대해 잘 모르는 독자들은 다음 포
inpa.tistory.com
그래서 Access / RefreshToken 이 뭔디?
위에서 내가 정리해서 말했듯이 AccessToken 만을 이용한 인증 방식의 문제는 해커에게 탈취당할 경우 보안에 취약하다는 단점이 있습니다.
액세스 토큰의 경우 발급된 이후, 서버에 저장되지 않고 유저가 가지고 있는 토큰 자체로 검증을 하며 사용자 권한을 인증하는 도구인데요.
그래서 이를 탈취당하면 토큰이 만료되기 전 까지, 토큰을 가지고 있는 유저는 누구나 권한 접근이 가능해집니다.
JWT는 발급하면 유저가 가지고 있기 때문에 삭제가 불가능합니다.(StateLess 한 방식)
그래서 이를 해결하는 방법이 토큰의 유효시간을 설정해서 이 문제에 대응을 하게 됩니다.
하지만, 유효기간을 짧게 가져가면 토큰 남용을 방지할 수 있지만 그만큼 사용자가 만료될 때 마다 토큰을 재발급을 받아야 하기 때문에 재로그인 빈도가 너무 잦아져 서비스 이용에 불편할 수 있습니다.
그렇다고 반대로 시간을 길게 가져가면 토큰이 탈취당했을 때 보안에 굉장히 위험해집니다.
위와 같이 이러지도 저러지도 못하는 상황에서 이를 해결하기 위해 나온것이 바로 RefreshToken 입니다.
로그인 하는 상황을 예시로 들어 설명하자면...
유저가 로그인을 하면 AccessToken 과 RefreshToken 이 같이 발급됩니다.
이 때, 서버에 RefreshToken 을 저장하고, 클라이언트는 AccessToken 과 RefreshToken을 쿠키, 세션 혹은 웹 스토리지에 저장하고 요청이 있을때마다 이 둘을 헤더에 담아서 보내게 됩니다.(Request Token)
RefreshToken도 마찬가지로 유효시간이 존재합니다. 하지만, 액세스 토큰과는 다르게 유효시간을 길게 가져갑니다.
예로 액세스 토큰이 5~10분을 가진다고 하면 리프레쉬는 1주일 또는 2주일 이런식으로 길게 가져가게 됩니다.
그래서 유저가 만약 만료된 액세스 토큰을 보내게 되면 서버에서 같이 보내진 리프레쉬 토큰을 DB에 있는 것과 비교해서 일치할 경우 다시 액세스 토큰을 발급하는 방식입니다.
또한, 유저가 로그아웃을 할 경우 DB의 Refresh Token 또한 함께 삭제하여 사용이 불가능하도록 하며 다시 로그인할 경우 서버에서 다시 재발급해서 DB에 저장하게 됩니다.
정리하고 보니 제가 이해하고 있는것에서 딱히 틀린 부분은 없어 보여서 다행입니다...
즉, 리프레쉬 토큰은 접근에 대한 권한을 주는 것이 아니라 액세스 토큰의 재발급에만 관여합니다.
이 아래의 내용은 인파님 블로그에서 가져온 것이며 프로젝트 진행중에는 생각지 못했던 상황들에 대한 설명도 있기에 같이 적게 되었습니다.
Access / RefreshToken 재발급 원리
1. 로그인 과정을 성공적으로 거치면 Access 와 RefreshToken 이 모두 발급됩니다.
이 때, 리프레쉬만 서버측의 DB에 저장하게 되며, 발급된 두 토큰은 유저의 쿠키 혹은 웹 스토리지에 저장합니다.
2. 사용자가 인증이 필요한 API 에 접근하고자 하면 가장 먼저 토크을 검사합니다.
이 때, 토큰을 검사함과 동시에 각 경우에 대해서 토큰의 유효기간을 확인하여 재발급 여부를 결정합니다.
- 액세스와 리프레쉬 모두가 만료된 경우
👉 에러 발생 (다시 로그인해서 둘 다 새롭게 발급받습니다) - 액세스는 만료, 리프레쉬는 유효한 경우
👉 리프레쉬 토큰을 이요해서 검증하고 액세스 토큰을 재발급 합니다. - 액세스는 유효, 리프레쉬가 만료된 경우
👉 액세스 토큰을 검증해서 리프레쉬 토큰을 재발급 합니다. - 액세스와 리프레쉬 모두 유효한 경우
👉 정상 처리
3. 로그아웃의 경우 액세스와 리프레쉬 토큰 모두 만료시킵니다.
제가 진행했던 프로젝트에서도 위와 같은 방식으로 처리했습니다.
유저가 가지고 있는 형태의 경우 액세스는 리퀘스트 헤더로 넘겨주면 프론트에서 받아서 쿠키로 만들어 주는 형태였으며,
리프레쉬의 경우에만 보안성 강화를 위해 직접 set-cookie 를 통해 생성해서 넘겨주는 방식이었습니다.
이 때, Cookie 의 속성에서 Secure 속성과 HttpOnly 속성을 활성화 시켜 보안을 강화하는 방식이었습니다.
둘 모두 쿠키 탈취를 방지하기 위한 방식으로 아래에 간단하게 설명하겠습니다.
- Secure
Https 로 통신하는 경우에만 웹브라우저가 쿠키를 서버로 전송합니다. - HttpOnly
자바스크립트를 통해 쿠키에 접근하는 것을 막습니다.
흔히들 크롬에서 개발자도구를 통해 열어보는 것에서 막아주는 것이라고 생각하면 됩니다.
RefreshToken 인증 과정
- 사용자가 ID, PW 를 통해 로그인합니다.
- 서버에서는 회원 DB에서 값을 비교합니다.
- 로그인이 완료되면 Access / Refresh Token 을 발급합니다. 이 때, 회원 DB 에도 Refresh Token 을 저장합니다.
- 사용자는 Refresh Token 은 안전한 저장소에 저장한 후, Access Token 을 헤더에 실어 요청을 보냅니다.
- Access Token 을 검증하여 이에 맞는 데이터를 보냅니다.
- 시간이 지나 Access Token 이 만료되었습니다.
- 사용자는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보냅니다.
- 서버는 Access Token 이 만료됨을 확인하고 권한이 없다고 신호를 보냅니다.
- 사용자는 Refresh Token 와 Access Token 을 함께 서버로 보냅니다.
- 서버는 받은 Access Token 토큰이 정상적인 토큰인지 검증을 하고, Refresh Token 과 사용자의 DB에 저장되어 있는 Refresh Token을 비교합니다.
- Token 이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token 을 발급합니다.
- 서버는 Access Token 을 헤더에 실어 다시 API 요청 응답을 진행합니다.
위와 같은 방식이라고 설명이 나와있는데 어..
확실히 그림과 함께 굉장히 정리가 잘 된 글을 보니 훨씬 머리에 잘 들어오는 것 같습니다.
다음에는 아무생각없이 진행하던 인증/인가 과정에 대해서 다시 공부해볼까 합니다.
그리고 리프레쉬가 만료되었을 경우에 어떤 방법이 있느지도 함께 알아보면 좋을거 같아 이와 관련한 글을 작성할까 합니다.