액세스 토큰과 리프레시 토큰

신민철·2023년 7월 16일
1

Spring Security

목록 보기
1/1
post-thumbnail

이번에 COMO 프로젝트를 진행하면서 새로운 로그인 모듈 방식으로 JWT를 이용한 로그인 방식을 선택하게 되었다.

선택하게 된 이유는 첫번째로 저번에 Session 방식으로 프로젝트를 해본 경험이 있기에 이번에는 JWT 방식으로 구현하기로 했다. 두번째로는 자체 로그인 + OAuth2.0을 구현하려면 어차피 OAuth가 토큰 방식이기 때문에 자체 로그인도 토큰 방식으로 하는 것이 효율적일 것이라고 판단했다.

먼저 JWT를 공부하면서 Token을 공부하게 되었는데 Token의 종류에는 두가지가 존재한다.


Access Token

  • 사용자가 로그인을 할 때 백엔드 서버에서 토큰을 만들어 클라이언트에 전송한다.
  • 클라이언트는 서버에 요청할 때 서버로부터 받았던 토큰을 요청과 함께 전송한다.
  • 서버는 토큰을 검증하여 로그인한 사용자를 확인한다.

Access Token은 위에서 말했듯이 요청과 함께 전달하게 된다. 이 Access Token은 저장하는 위치에 따라 장단점이 달라지게 된다.

그럼 Access Token은 어디에 저장해야 할까?

일반적으로 웹 프로젝트에서는 로컬 스토리지, 세션 스토리지, 쿠키에 저장하는 것이 일반적이다.

로컬 스토리지와 세션 스토리지는 데이터의 영구성에서 차이가 나는데, 로컬 스토리지는 사용자가 지우지 않는 이상 브라우저에 계속 남게 된다. 하지만 세션 스토리지는 브라우저나 탭을 닫을 경우에 데이터가 휘발된다. 그렇기에 자동 로그인과 같은 기능에 필요한 것은 로컬 스토리지가 적합하고 일회성 로그인은 세션 스토리지가 적합할 것이다.

하지만 단점이 있다. 이 두 스토리지는 XSS(Cross Site Scripting) 공격에 취약하다는 것이다.

XSS 공격은 공격자가 대상 컴퓨터에 스크립트를 실행시켜 세션을 가로채거나, 악의적 컨텐츠를 삽입하는 등 피싱 공격 등을 일컫는다. 이 두 스토리지는 자바스크립트로 값을 꺼낼 수 있기 때문에 XSS 공격에 취약하다. 그렇기 때문에 토큰을 이 곳에 저장하는 것은 안전하지 않다.

그럼 남은 것은 쿠키이다. 쿠키는 만료 기한이 있는 키와 값으로 이루어져 있는 저장소이다. 쿠키는 항상 안전할까? 그렇지만은 않다. 쿠키 또한 자바스크립트로 접근이 가능하다. 하지만 Http Only 옵션을 켜둔다면 자바스크립트로 접근할 수 없게 만들어 XSS 공격을 방지할 수 있다. 하지만 쿠키는 CSRF(Cross-Site Request Forgery)공격에 취약해진다. XSS 공격은 토큰의 값 자체를 가져와 공격하는 방식이지만 CSRF는 로그인 된 상태로 특정 동작을 하게 만든다. 따라서 CSRF는 토큰 값 자체를 가져올 수 없기 때문에 이 방식이 합리적일 것이다.


Refresh Token

Access Token은 위에 말한 공격이나 탈취의 문제 때문에 유효 기간이 짧다고 설명했다. 그러면 Access Token의 유효 기간이 만료된다면 어떻게 해야 할까? 그냥 강제 로그아웃밖에 없을까?

정답은 Refresh Token이다.

Refresh Token은 Access Token과는 다르게 유효기간이 일반적으로 2주 정도로 긴 편이다.

이 Refresh Token은 어디에 저장하는 것이 좋을까?

필자는 빠른 접근이나 RDB의 TTL(Time To Live)고려 문제 때문에 In-memory Redis DB에 저장하고 있다. 이러면 보안적으로 안전하게 저장할 수 있게 된다.

그러면 여기에서 “Refresh Token은 탈취 안당하나요?”라는 질문이 나올 수 있다.

물론 Refresh Token도 탈취를 당할 수 있다.

이를 막기 위해서 Refresh Token Rotation(RTR) 기법이 있다.

Refresh Token Rotation(RTR) 이란?

Refresh Token을 One time Use Only로 설정한다.

한번 이상 사용된 Refresh Token은 탈취된 것으로 간주하고 간주된 Refresh Token으로 인해 발급된 모든 Refresh Token을 폐기한다. 이를 위해서는 Token Chain을 만들어야 하고 이것을 관리해야 한다고 한다.

하지만 이 방식에도 허점이 있는데..

해커가 지속적으로 Access Token만 탈취한다면 RTR 방식이 무용지물이 된다.


결론

Access Token은 수명이 짧고 이것을 보완하기 위해 Refresh Token으로 갱신한다.

두 토큰은 탈취당할 수 있는데 각 토큰마다 저장 위치나 방지하는 방법이 다르다.


참조

[Network] JWT - 왜 refresh 토큰이 필요하지? (refresh 토큰이 탈취된다면?)

Access Token 저장 위치에 대한 고찰

JWT의 Refresh Token과 Access Token은 어디에 저장해야 할까?

0개의 댓글