🪪 JWT 생성 & 서명
헤더, 페이로드, 시크릿을 입력하여 브라우저 내에서 서명된 JWT를 생성합니다. HS256 / HS384 / HS512 지원. Web Crypto API 사용.
⚠️ 보안 주의사항
• 시크릿은 Web Crypto API를 통해 브라우저 내에서만 처리되며 서버로 전송되지 않습니다.
• 프로덕션 시크릿을 웹 도구에 입력하는 것은 권장되지 않습니다. 테스트, 학습, 디버깅 용도로 사용하세요.
• HS256 시크릿은 최소 256비트(32바이트), HS512는 최소 512비트(64바이트)를 권장합니다.
🔗 관련 도구
📖 자주 걸리는 지점
헤더·페이로드·시크릿을 입력하면 Web Crypto API 를 사용해 브라우저 안에서 서명된 JWT 를 생성합니다 (HS256 / HS384 / HS512). iat 나 exp 는 버튼으로 추가할 수 있습니다. 시크릿이 서버로 전송되지 않습니다. 다만 JWT 에 대해 무엇보다 먼저 이해해야 할 것이 있습니다 — JWT 는 암호화가 아닙니다. 페이로드는 Base64URL 로 「부호화」되어 있을 뿐이며 키가 없는 누구든 내용을 읽을 수 있습니다. 서명이 보증하는 것은 「변조되지 않았다」는 것뿐이며 「보이지 않았다」는 전혀 보증하지 않습니다.
| 사례 | 무슨 일이 일어나는가 | 어떻게 하면 되는가 |
|---|---|---|
| 프로덕션 시크릿을 브라우저 도구에 넣어 버린다 | 이 페이지는 값을 서버로 보내지 않지만 「전송되지 않는다」와 「흔적이 남지 않는다」는 다릅니다. 입력한 문자열은 DOM 안에 존재하고, 브라우저의 입력 이력이나 자동 완성에 남을 가능성이 있으며, 스크린샷이나 화면 공유에 찍히고, 설치한 확장 기능에서는 페이지 내용을 읽을 수 있습니다. 클립보드에 복사하면 클립보드 이력 도구에도 남습니다. 그리고 가장 놓치기 쉬운 것이 생성한 토큰 그 자체로, 디버그를 위해 Slack 이나 티켓에 붙인 JWT 는 시크릿이 새지 않았더라도 그 토큰이 유효한 동안 계속 쓸 수 있습니다 — JWT 는 Bearer 토큰이므로 가지고 있는 사람이 본인으로 취급됩니다. | 이 페이지에는 일회용 시크릿만 넣으세요. 「랜덤 생성」 버튼으로 만든 값이면 충분합니다 — 서명 구조를 확인하는 것이 목적이라면 진짜일 필요가 없습니다. 이미 프로덕션 시크릿을 붙여 버렸다면 대처는 하나뿐입니다: 즉시 로테이션하세요. 「아마 괜찮겠지」로 방치하면 유출되었는지를 나중에 판정할 수단이 없습니다 — HMAC 의 시크릿은 토큰 하나만 잡으면 로컬에서 전수 조사할 수 있으므로 사전에 실린 단어나 짧은 문자열은 특히 위험합니다. 그리고 프로덕션 시크릿은 애초에 사람이 눈으로 보지 않는 설계로 만드세요 — 환경 변수나 시크릿 관리 서비스에서 직접 읽어 들이게 하고 복사 붙여넣기의 경로를 만들지 않는 것이 가장 효과적입니다. |
exp 는 검증 측에서만 듣는다 |
exp 는 그저 필드이며 시간이 되면 토큰이 자동으로 무효가 되는 구조가 아닙니다 — 검증하는 쪽이 그 값을 읽고 거부해야 비로소 기한으로 기능합니다. 여기서 네 가지 단골 결함이 나옵니다. (1) exp 를 넣는 것을 잊으면 그 토큰은 영원히 유효합니다. (2) 값의 단위를 틀립니다 — JWT 의 시각은 「에포크로부터의 초」이고 JavaScript 의 Date.now() 는 밀리초이므로 그대로 넣으면 5 만 년 뒤를 가리킵니다. (3) 서버 간 시계의 어긋남으로 발행 직후의 토큰이 nbf 에 걸려 거부됩니다. (4) 발행된 토큰은 취소할 수 없습니다 — 로그아웃해도 비밀번호를 바꿔도 exp 까지 유효합니다. |
액세스 토큰의 exp 는 짧게 하세요 — 15 분에서 1 시간이 일반적인 기준입니다. 장기 로그인 상태는 리프레시 토큰으로 유지하고, 그쪽은 서버에 저장해 개별적으로 무효화할 수 있게 합니다. 「취소할 수 없다」는 문제를 정면으로 푸는 방법은 이것뿐입니다. 즉시 실효가 요건이라면 jti (토큰 ID) 를 넣고 거부 목록을 둡니다 — 다만 그 시점에서 「서버에 상태를 두지 않는다」는 JWT 의 이점은 사라지므로 정말 그 요건이 있는지를 먼저 확인하세요. 검증 측 구현에서는 exp 와 nbf 의 비교에 수십 초의 허용 오차 (leeway) 를 둡니다. 그리고 시각의 단위는 반드시 초 — JavaScript 라면 Math.floor(Date.now() / 1000) 입니다. |
검증 측이 토큰의 alg 를 믿어 버린다 |
헤더의 alg 는 공격자가 고쳐 쓸 수 있는 자리에 있습니다 — 그것을 읽고 검증 방법을 정하는 라이브러리는 공격자에게 검증 방법을 고르게 하고 있는 셈입니다. 유명한 깨뜨리는 방법이 둘 있습니다. (1) alg: none — 「서명 없음」이라는 값을 써 넣고 서명 부분을 비우면 순진하게 구현된 라이브러리는 이것을 받아들입니다. (2) RS256 과 HS256 의 혼동 — 본래 RSA 공개 키로 검증해야 할 토큰의 alg 를 HS256 으로 고쳐 쓰고 「공개 키를 HMAC 의 시크릿으로」 서명하는 수법입니다. 공개 키는 공개되어 있으므로 공격자는 유효한 토큰을 자유롭게 만들 수 있습니다. 둘 다 구현의 버그이지 JWT 자체의 결함이 아닙니다. |
검증 측에서는 사용할 알고리즘을 고정값으로 넘기세요. 대부분의 라이브러리는 algorithms: ['HS256'] 같은 인자를 받습니다 — 생략할 수 있는 API 라도 생략하지 마세요. 토큰에서 읽은 alg 는 검증의 입력이 아니라 검증의 대상입니다. 키도 마찬가지로 고정하고 여러 키를 로테이션한다면 kid 로 고르는 형태로 하되 반드시 자기 키 집합 안에서 고르게 하세요. 시크릿의 강도도 잊지 마세요: HS256 이라면 256 비트 (32 바이트) 이상의 랜덤 값을 쓰고 외울 수 있는 비밀번호는 쓰지 마세요 — HMAC 은 토큰 하나만 있으면 오프라인에서 얼마든지 검증할 수 있으므로 사전 공격이 현실적인 위협이 됩니다. 그리고 마지막으로 라이브러리를 직접 만들지 마세요. |
페이로드에 기밀을 넣지 마세요. 반복하지만 누구나 읽을 수 있습니다 — 메일 주소·전화번호·권한의 내역·내부 ID 등을 넣으면 그것은 토큰을 본 사람 전원에게 공개됩니다. 브라우저의 DevTools 를 열면 자기 토큰의 내용을 읽을 수 있다는 것을 설계할 때 떠올리세요. 클레임은 최소한으로 하고 상세는 필요할 때 서버에서 가져오는 편이 안전합니다. 애초에 JWT 가 최적이 아닌 상황도 많습니다 — 같은 도메인의 일반적인 웹 애플리케이션이라면 서버 측 세션이 더 단순하고 게다가 즉시 로그아웃할 수 있습니다. JWT 가 정말로 효과를 내는 것은 여러 서비스를 넘나드는 인증이나 검증 측이 발행처에 문의할 수 없는 구성입니다. 「모던하니까 JWT」는 이유가 되지 않습니다 — 상태를 두지 않는 대신 취소할 수 없다는 트레이드오프를 받아들일 수 있는지로 고르세요.
📖 사용법
-
1
알고리즘과 페이로드 설정HS256 / HS384 / HS512에서 선택 후 Payload JSON 클레임을 입력합니다. +iat / +exp 버튼으로 표준 클레임을 추가하세요.
-
2
시크릿 입력 또는 생성시크릿 필드에 키를 입력하거나 랜덤 생성 버튼을 클릭합니다.
-
3
생성된 JWT 복사서명된 JWT가 즉시 오른쪽 패널에 표시됩니다.
❓ 자주 묻는 질문
HS256, HS384, HS512의 차이점은?
프로덕션 시크릿을 입력해도 안전한가요?
RS256 또는 ES256(비대칭) 지원 여부?
🐛 이 도구에서 문제가 발생했나요?
무료 · 가입 불필요. 재현 절차만이라도 도움이 됩니다. 보고는 운영자에게 직접 전달되어 개선에 사용됩니다.
보고 감사합니다!
운영자에게 전달되었습니다. 개선에 사용됩니다.