JWT를 디코더에 붙여넣어 사용자 이름과 만료 시각이 보였다고 해서 서버가 신뢰할 토큰이라는 뜻은 아닙니다. 이 사이트의 JWT 디코더도 Header·Payload를 해독하고 Signature 문자열을 표시하는 기능이며, 서버의 검증 키로 서명을 확인하는 기능은 아닙니다.
서명된 JWT의 세 구간
일반적인 JWS compact 형식의 JWT는 header.payload.signature로 나뉩니다. 앞의 두 구간은 JSON을 Base64url로 표현한 값이므로 서명 키 없이도 읽을 수 있습니다. 서명은 위변조 검증을 위한 것이고 내용을 숨기는 암호화와 다릅니다. 암호화된 JWE compact 형식은 다섯 구간을 사용하므로 모든 JWT를 세 구간으로 일반화하면 안 됩니다. JWT 형식과 클레임
| 구간·필드 | 읽을 수 있는 정보 | 읽는 것만으로 알 수 없는 정보 |
|---|---|---|
Header의 alg |
토큰이 주장하는 알고리즘 | 서버가 허용하는 알고리즘인지 |
Payload의 sub |
주체 식별자 | 그 주체가 실제 인증됐는지 |
iss·aud |
발급자·대상 값 | 우리 서비스가 신뢰하는 값인지 |
exp·nbf |
만료·사용 시작 시각 | 서명과 정책 검증까지 통과했는지 |
| Signature | 서명 데이터 | 올바른 키로 검증했는지 |
해독과 검증이 다른 이유를 직접 보기
다음 코드는 실제 JWT나 비밀키를 쓰지 않습니다. 설명용 Payload 구간을 만들고 읽은 뒤 역할만 바꿔 다시 인코딩합니다. 유효한 서명을 만들거나 서비스에 요청을 보내는 코드는 아닙니다.
import base64
import json
def encode_part(value):
raw = json.dumps(value, separators=(",", ":")).encode("utf-8")
return base64.urlsafe_b64encode(raw).rstrip(b"=").decode("ascii")
def read_part(value):
padded = value + "=" * (-len(value) % 4)
return json.loads(base64.urlsafe_b64decode(padded))
original = encode_part({"sub": "demo-user", "role": "reader"})
changed = encode_part({"sub": "demo-user", "role": "admin"})
print(read_part(original)["role"]) # reader
print(read_part(changed)["role"]) # admin
양쪽 모두 해독되지만 두 번째 값이 관리자 권한을 갖는다는 뜻은 아닙니다. 서버가 원래 서명과 변경된 Payload를 검증하면 일치하지 않아야 합니다. 화면에 표시된 role을 그대로 권한으로 사용하는 구현이 잘못된 것입니다.
서버가 검증해야 하는 것
검증 라이브러리에 서버가 정한 허용 알고리즘과 신뢰할 키를 전달하고, 서명뿐 아니라 발급자·대상·사용 기간·필수 클레임을 확인합니다. 토큰의 alg를 그대로 따라 검증 방식을 결정하거나 서명 검증을 끄고 Payload만 읽어 인증에 사용하면 안 됩니다. JWT 보안 권고 RFC 8725
exp는 초 단위의 NumericDate입니다. 허용된 시간 오차를 별도로 두지 않는다면 현재 시각이 exp에 도달한 시점부터 만료로 판단합니다. 브라우저 시계가 잘못되어 있을 수도 있으므로 디코더의 시간 안내를 서버 인증 결과와 동일하게 보지 않습니다. 이 사이트 디코더의 현재 구현은 만료 경계의 표시도 별도 개선 대상입니다.
JWT와 로그인 방식은 별개의 선택
JWT는 클레임을 전달하는 형식이며 로그인 시스템 전체를 대신하지 않습니다. Access Token이 반드시 JWT인 것도 아니고 Refresh Token이 반드시 JWT일 필요도 없습니다. 재발급 토큰을 회전하거나 강제 로그아웃·계정 정지를 즉시 반영하려면 서버의 추가 상태 관리가 필요할 수 있습니다.
win-j 관리자 로그인은 현재 Django 세션을 사용합니다. JWT 소개 글과 도구가 있다는 이유로 관리자 인증에 JWT가 적용되어 있다고 해석하면 안 됩니다. 세션 방식은 쿠키·세션 글에서 실제 프로젝트 구성과 연결해 설명합니다.
디버깅할 때 남길 정보
만료 오류는 서버 시각과 exp, 잘못된 대상 오류는 aud, 서명 오류는 키 선택·키 교체 시점·허용 알고리즘을 나누어 확인합니다. 로그에는 전체 토큰이나 비밀키 대신 요청 식별자와 오류 분류를 남깁니다. 온라인 도구에는 운영 토큰을 붙여넣지 말고 위와 같은 합성 데이터를 사용합니다.
JWT 도구의 해독 성공 표시는 구조를 읽었다는 뜻으로만 사용해야 합니다. 이 글은 토큰 생성 도구의 모든 보안 동작을 검증했다는 의미가 아니며, 실제 인증은 서버의 검증 절차와 권한 검사에서 결정됩니다.
첫 댓글을 남겨보세요.