Security/Web

JWT 다중 토큰 발급

조용우 2025. 2. 18. 17:40

JWT를 이용한 인증/인가는, 토큰이 XSS, HTTP통신 가로채기 등으로 탈취되었을 때 해커가 서비스를 악용할 수 있다. 따라서, 토큰 탈취 방지 및 탈취되었을 때 대비하는 기술이 존재한다.

 

다중 토큰

Access/Refresh 토큰 

자주 사용되는 토큰의 생명주기는 짧게(약 10분), 이 토큰이 만료되었을 때 재발급을 요청 할 Refresh 토큰(24시간 이상) 두개를 함께 발급함.

실행 순서

1. 로그인 성공 시 Access, Refresh 토큰  발급

2. 서비스에 요청 시 권한이 필요할 때 Access 토큰을 통해 요청

3. Access 토큰이 유효할 경우 서버에서 서비스 응답

4. Access 토큰이 만료됐을 경우 Refresh 토큰으로 서버측에서 토큰 검증 후 새로운 Access토큰 발급

 

Access 토큰이 탈취됐을 경우, 이제 Access토큰의 생명주기가 짧기 때문에, 피해가 최소화 된다.

-> 하지만 그 짧은 시간동안은 여전히 악용될 수 있다는 위험성 존재

 

 

하지만 Refresh 토큰이 탈취됐을 경우에는?

 

1. 탈취되지 않도록 토큰의 저장 위치를 로컬/세션 스토리지, 쿠키 등 알맞은 저장소 설정

로컬 스토리지: XSS 공격에 취약, Access 토큰을 저장

httpOnly 쿠키: CSRF 공격에 취약, Refresh 토큰 저장

 

JWT는 보통 XSS 공격으로 로컬 스토리지에 저장된 JWT를 가져가기 때문에 Refresh 토큰을 httpOnly 쿠키에 저장.

그러면 둘 다 쿠키에 저장하면 되는거 아님?

 

Access 토큰을 로컬 스토리지에 주로 저장하는 이유는, 탈취에서 사용까지 기간이 매우 짧고, 에디터 및 업로더에서 XSS를 방어하는 로직을 작성해서 최대한 보호할 수 있어서 애초에 탈취될 위험이 적음.

하지만 CSRF 공격의 경우 클릭 한번으로 단시간에 요청이 진행되기 때문에 CSRF 토큰의 위험보다는 XSS 공격을 받는 게 나은 선택일 수 있음.

 

Refresh 토큰은 XSS와 CSRF 공격 두가지를 받을 수 있지만 httpOnly 설정을 하면 XSS는 완전히 방어.

CSRF 에는 취약하지만 Refresh 토큰의 사용처는 Access 토큰 재발급 용도 하나밖에 없기 때문에 접근에 대한 권한이 없어 피해를 입힐만한 요소가 적음.

 

 

2. Refresh 토큰을 Rotate함.

Refresh 토큰 요청 시 서버측에서 Refresh 토큰도 재발급 해서 한 번 사용한 Refresh 토큰은 재사용하지 못하도록 하는 것

 

Refresh Rotate 를 적용한 상태에서 Access 토큰을 갱신하면 갱신시 Refresh 토큰도 새로 발급되기 때문에 생명주기가 길어짐. 따라서 Refresh 토큰이 만료되기 전까지 한번이라도 요청을 하게되면 로그인은 끊기지 않고 유지됨

 

하지만, Refresh 토큰 Rotate는 탈취 문제가 발생해서 해커가 재인증을 받아가버리는 상황은 막지 못함.


위와 같이 여러가지 방법을 사용하더라도 Refresh 토큰이 탈취되면 여전히 위험할 수 있음

 

로그아웃을 구현하면 Access/Refresh 토큰이 제거됨. 하지만, 제거 전에 이미 토큰을 훔쳐갔다면 백엔드에 요청이 수행됨.

-> JWT를 발급해준 순간 인증/인가의 주도권은 서버에서 유저측으로 넘어가기 때문.

(별개로 Session 방식은, State하게 상태가 관리되기 때문에 주도권이 서버측에 있음)

 

따라서 해결 방법은, 서버측이 주도권을 갖도록 하는 것인데,

생명주기가 긴 Refresh 토큰은 발급과 함께 서버측에도 저장해서 요청이 올때마다 refresh 토큰이 존재하는 지 확인하는 방식으로 주도권을 가질 수 있음.

토큰이 탈취당해 피해를 입는 경우에도, 서버측 저장소에서 refresh 토큰을 삭제하여 피해를 방어할 수 있음.

(= Refresh 토큰 블랙리스팅)

 

로그인 시 알림

로그인 시 의심스러운 접속(평소 사용하지 않던 IP 혹은 브라우저)이 이루어질 경우, 알림이 발생하여 내가 아닐 경우 아니오를 선택하게 되면 서버측 토큰 저장소에서 해당 유저에 대한 refresh 토큰을 모두 제거하여 앞으로의 인증을 막을 수 있음. 

 

1. 기존 인증(통신)하던 IP나 브라우저가 아닌 경우 유저에게 메일 전송 후 계정 블록

2. 해외 아이피 차단 여부

3. csrf 방어 및 챌린지값 전송