🔐 JWT의 주요 목적
JWT는 인증 및 권한 부여를 위한 정보를 안전하게 전달하기 위해 설계되었습니다. 이를 통해 클라이언트와 서버 간의 상태를 유지하지 않고도 사용자의 인증 상태를 확인할 수 있습니다.
🧱 JWT의 구조
JWT는 세 부분으로 구성됩니다:
- Header (헤더):
- 토큰의 유형과 서명 알고리즘을 지정합니다.
- 예시:
{
"alg": "HS256",
"typ": "JWT"
}
- Payload (페이로드):
- 토큰에 담길 클레임(정보)을 포함합니다.
- 예시:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"exp": 1715539200
}
- Signature (서명):
- 헤더와 페이로드를 인코딩한 후, 비밀 키를 사용하여 서명합니다.
- 이 서명을 통해 토큰의 무결성을 검증할 수 있습니다.
🔐 보안 고려사항
- 서명 알고리즘: JWT는 다양한 서명 알고리즘을 지원하지만, 보안상의 이유로 강력한 알고리즘을 선택하는 것이 중요합니다.
- 토큰 저장: 클라이언트 측에서 JWT를 저장할 때는 XSS 공격을 방지하기 위해 HttpOnly 쿠키를 사용하는 것이 권장됩니다.
- 만료 시간:
exp
클레임을 설정하여 토큰의 유효 기간을 제한해야 합니다.



1. accessToken 이 털린다면
정상 루트
- id, password 로 로그인 한다
- accessToken 을 받는다
- accessToken 으로 데이터를 받는다
- accessToken 의 만료 기간이 1주일이다
- 1주일 동안 로그인 할 필요 없다
비정상 루트
- accessToken 을 탈취한다
- accessToken 으로 데이터를 받는다
- accessToken 의 만료 기간이 1주일이다
- 1주일 동안 내 마음대로 할 수 있다
이 털리는 시간을 줄이면 조금 덜 털리지 않을까?
2. accessToken 의 수명을 줄인다
정상 루트
- id, password 로 로그인 한다
- accessToken 을 받는다
- accessToken 으로 데이터를 받는다
- accessToken 의 만료 기간이 1시간이다
- 1시간 마다 로그인을 해야 한다
1시간 마다 로그인을 해야 하는 번거로움이 발생 한다
비정상 루트
- accessToken 을 탈취한다
- accessToken 으로 데이터를 받는다
- accessToken 의 만료 기간이 1시간이다
- 1시간 동안 내 마음대로 할 수 있다
시간이 더 줄어든다면 탈취를 했더라도 사용하기 전에 만료될 수 있다
3. 이 번거로움을 해결해 보자
refreshToken 을 만들어 보자
- refreshToken 은 accessToken 을 재 발행 하기 위한 인증 토큰이다
- id, password 로 로그인을 한다
- accessToken, refreshToken 을 받는다
- accessToken 은 1시간, refreshToken 은 1주일로 만료 기간을 만든다
- accessToken 이 만료가 되어 에러가 발생하면 자동으로 refreshToken 으로 accessToken 을 재 발행한다
- 그러면 1주일 동안은 로그인을 다시 할 필요가 없다
- 만약 refreshToken 을 사용할 때 refreshToken 과 accessToken 을 같이 재 발행 받으면 무한 로그인이 가능하다
- accessToken 이 만료되는 5분 마다 accessToken 과 refreshToken 을 같이 재 발행한다
- 요청이 이뤄지는 동안 계속 로그인 상태가 유지된다
- 요청을 중단한다
- refreshToken 의 수명 1주일 전에 다시 요청을 하면 accessToken 과 refreshToken 을 같이 재 발행한다
- refreshToken 의 수명 1주일 후에 다시 요청을 하면 refreshToken 이 만료되었기 때문에 다시 로그인을 해야 한다
4. refreshToken 도 털린다면?
- accessToken 때와 동일하게 refreshToken 의 만료 기간까지 털릴 수 있다
5. 이걸 보완하는 방법은
refreshToken 을 검증 할 때 필요한 부가 정보
- refreshToken (해시)
- deviceFingerprint (기기 고유 식별자)
- 서버에서 만든 자체적인 해시값를 사용자의 기기에 심어준다
- 기기의 IMEI 값을 사용할 수 없다. 만약 사용한다면 이 값을 해시해서 사용해야 한다
- 요청을 보낼 때 이 키 값을 같이 보낸다
- IP (특정 IP 차단 → 중국, 북한)
- User-Agent (장치 식별 → 브라우저 or 휴대폰)
결국 보완 하는 방법은 서버가 stateful 하게 정보를 가지고 있어야 하는 것
- 서버의 db, session 등 서버쪽에 데이터를 저장한다
- refreshToken 으로 요청이 들어오면 서버의 데이터와 비교해 정상이면 accessToken 을 재 발행한다
- refreshToken 요청이 들어올 때마다 검증을 하기 때문에 refreshToken 이 탈취 당해도 refreshToken 을 새로 발급 받을 때 정상 처리가 되었다면 서버쪽에 저장된 refreshToken 값이 달라지기 때문에 털리더라도 문제 없다
서버는 accessToken 은 stateless 하게 사용하고 refreshToken 은 stateful 하게 사용해야 한다
accessToken 은 15~30분 정도, refreshToken 은 7일 이상 정도로 만들어 둔다
토큰 방식은 이점이 많지만 단점도 명확하기 때문에 은행 같은 곳에서는 session 방식을 아직 사용한다
Share article