개요
- 리프레시 토큰을 Redis에 저장한다는 사례를 들어서 직접 구현해봤습니다.
- Token Based Authenticaion, Refresh Token을 공부해보았습니다.
- 결론: 해당 방식은 비효율적이고 보안적 가치가 없는 방식이었습니다.
What is Redis?
레디스는 인메모리 방식의 데이터베이스입니다.
Diff Basic DB vs In-Memory DB
기존 DB(e.g. mysql, postgreSQL)은 보조기억장치에 데이터를 저장합니다.
그래서 많은 양의 데이터를 오래 저장하는 데에 적절합니다.
인메모리 DB(e.g. Redis, MemCache)는 주기억장치에 데이터를 저장합니다.
그렇기에 데이터 조회 성능이 월등히 빠릅니다.
주기억장치를 이용하기 때문에 RAM의 휘발성 메모리의 특징도 가지고 있습니다.
중요한 데이터의 삭제를 예방하기 위해 fork 기능을 사용하여 보조기억장치에 저장하기도 합니다.
그 외의 Redis의 특징
- key-value 구조.
- 데이터 만료시간 설정 가능.
- 수평적 확장에 용이함.
위 특징 때문에 "자주 조회되는 값인 Refresh Token을 Redis에 사용하자!"라는 설명을 들었지만,
해당 방식은 아무런 의미가 없다는 것을 알았습니다.
먼저, 왜 Refresh Token을 왜 사용할까요?
Why Use Refresh Token?
이를 알기 위해서는 토큰 베이스 인증부터 확실히 알고 가야합니다.
우선, 초보자가 오해할 수 있는 개념을 정리하겠습니다.
- 완벽한 보안은 존재하지 않습니다.
- 세션 베이스 인증과 '토큰'은 상호 대체적이지 않습니다. (세션 베이스 인증에서도 토큰 사용함)
엑세스 토큰의 한계점
잦은 로그아웃
엑세스 토큰을 단독으로 사용하면 재발급 시 로그인을 해야합니다.
때문에 만료시간을 짧게 하면 재로그인을 자주 해야하며, 만료시간을 길게하면 아래와 같은 보안 문제가 발생합니다.
보안 문제
Access Token의 만료 시간을 길게하면 탈취 당했을 때 유저의 모든 권한을 탈취자가 가지게 됩니다.
토큰은 state-less 구조로 state의 주도권을 서버가 가지고 있지 않습니다.
때문에 탈취 당했다고 하더라도 토큰 자체를 파기할 수 없습니다.(이는 비용적으로는 장점이지만, 보안적으로는 단점입니다.)
Refresh Token이란?
Refresh Token은 Access Token의 문제점을 방지하기 위하여 생겨났습니다.
- 잦은 로그아웃
Refresh Token을 사용하여 Access Token을 갱신하여 재로그인 주기를 늘릴 수 있습니다. - 보안 문제
Access Token의 만료시간을 짧게 함으로써 탈취 시 문제를 조금이나마 방지할 수 있습니다.
Refresh Token이 탈취 당하면 우짤건데?
이는 Refresh Token의 한계입니다. 서버 측에서의 대응이 불가능합니다. 니가 뭘 할 수 있는데
이를 예방하기 위해 여러가지 Refresh Token 전략이 존재합니다.
Refresh Token 전략들
상호 대체적인 전략도 존재하며, 상호 보완적 전략도 존재합니다.
RTR(Refresh Token Rotation) 전략
RTR은 Refresh API 사용 시, Access Token과 함께 Refresh Token을 갱신시켜버리는 방식입니다.
RTR의 핵심은 Refresh Token을 1회용으로 구현하는 것입니다.
구현 방식으로는 DB에 저장, rotation_type 옵션 사용, Refresh Token의 짧은 만료시간 등이 있습니다.
다만 해당 방식도 XSS 취약점을 사용한 공격은 막지 못합니다.
Refresh Token에 http-only 적용 전략
Access Token은 http authorization header에 담아야하기 때문에 노출되는 것을 막을 수 없습니다.
하지만 리프레시 토큰을 사용할 때는 http only옵션을 사용하여 쿠키로 보냅니다. JS에서는 Refresh Token에 접근할 수 없기 때문에 위 XSS공격을 예방할 수 있습니다.
다만 이 방법 또한 csrf(Cross-site request forgery)을 사용하면 탈취할 수 있습니다.
Access Token 만료시간 단축 전략
위에서 설명했던 부분이지만, 엑세스 토큰의 만료 시간을 짧게 설정하여 탈취 시 문제를 조금이나마 방지할 수 있습니다.
재발급이 횟수가 늘어나겠지만, 탈취 리스크를 줄이기 위해 권장하는 방식입니다.
사용자 정보를 Access Token에 저장 전략
발급 당시 IP, 기기/브라우저 정보 등을 저장하고 엑세스 토큰을 사용하는 자의 정보와 크게 다르다면 재로그인을 수행하는 전략입니다.
이 또한 권장합니다. IP 주소의 정보
Token DB 저장 전략?
Access/Refresh Token을 계정에 엑세스 토큰이 1:1로 매핑되도록 DB에 저장하는 방식입니다.
Refresh API를 수행할 때 이미 발급된 Access Token이 탈취 되었을 때 인증서버에서 거부할 수 있습니다.
이렇게하면 state-less 구조의 장점을 잃어버립니다. 이 방식으로 사용 할바에는 세션을 사용하는게 맞습니다.
(Redis를 사용하는 이유에는 보안적인 이유는 없습니다.)
Refresh Token의 한계점
Refresh Token은 한계점이 명확합니다. 보안적 역할을 하지 못한다는 평가도 존재하구요.
- 탈취된 Access Token을 만료시킬 수 없음.
- Refresh Token이 탈취된다면 결국 아무것도 할 수 없음.
저는 이렇게 사용합니다.
저는 브라우저 환경인 웹 서비스는 Session을 사용하여 보안성을 가져가고,
모바일 환경에서는 상대적으로 해킹이 어렵기 때문에 Token 방식을 사용하려고 합니다.
레퍼런스
- https://pragmaticwebsecurity.com/articles/oauthoidc/refresh-token-protection-implications.html
- https://okky.kr/questions/1007579
- https://hudi.blog/refresh-token/
- Refresh Token을 어디에 저장해야 할까?(Feat. XSS, CSRF, CORS)
- https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
- https://youtu.be/Gimv7hroM8A
- https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies
'트러블 슈팅' 카테고리의 다른 글
[MySQL 복구 1] .ibd 파일을 이용하여 데이터 복구하기 (0) | 2023.09.08 |
---|---|
돈이 없는데 서버의 하드디스크가 꽉찼다. (docker chromium) (0) | 2023.06.04 |
인덱스의 카디널리티, 복합키의 성능 최적화 (0) | 2023.03.30 |
팀원이 설정한 알람이 내 폰에서 울려야한다. (0) | 2023.03.28 |
어떨 때 composite key를 사용해야 할까? (0) | 2023.03.19 |
글 내용 중 잘못되거나 이해되지 않는 부분은 댓글을 달아주세요! 감사합니다! 문의: puleugo@gmail.com