본문 바로가기

JWT 디코딩

JSON Web Token의 헤더, 클레임, 만료 시각을 확인하세요. 토큰은 실제로 쓰이는 인증 정보이므로, 여기서는 어떤 것도 어디로 전송되거나 저장되지 않습니다.

  • 저장되지 않음
  • 대기열 없음, 기다림 없음
  • 회원가입 없음, 워터마크 없음

토큰은 이 페이지 밖으로 나가지 않아요. 어떤 서버에도 요청하지 않고 바로 여기에서 디코딩합니다. JWT는 보통 실제로 쓰이는 인증 정보이기 때문에 이 점이 중요해요. 페이지가 로드된 뒤 Wi-Fi를 꺼도 디코딩이 되는 걸 확인할 수 있어요. 아무것도 전송되지 않습니다.

“Bearer ” 접두어가 붙어 있어도 괜찮아요. 무시됩니다.

사용 방법

1

토큰 붙여넣기

"Bearer " 접두어가 있어도 없어도 됩니다. 토큰은 이 페이지 안에만 있으며, 어떤 요청도 보내지 않습니다.

2

세 부분 확인

헤더, 페이로드, 서명을 각각 디코딩하고 정렬해 보여 드립니다. 타임스탬프는 실제 날짜로 바뀌고, 남은 시간도 알려 드립니다.

3

경고 확인

만료된 토큰, 만료 시각 누락, “none” 알고리즘 등의 문제를 그 의미와 함께 짚어 드립니다.

검사하는 것과 읽기만 하는 것

이 페이지에서 날짜 비교 두 가지를 빼면 모든 것은 옮겨 적기일 뿐입니다. 헤더와 페이로드는 Base64URL로 디코딩해 출력하고, 서명은 복사해 보여 줄 뿐 전혀 건드리지 않습니다. 여기에는 키가 없고 어떤 암호 연산도 실행되지 않기 때문입니다. 이 페이지가 내리는 판단 두 가지는 사용자 기기의 시계를 기준으로 한 산수입니다. 만료 클레임을 현재 시각과 비교하고, 유효 시작 클레임을 현재 시각과 비교합니다. 시계 오차는 고려하지 않습니다. 같은 토큰을 검사하는 서버는 보통 1~2분의 여유를 둡니다. 5분 빠른 노트북에서는 유효한 토큰이 만료된 것으로 보이지만, 토큰에는 아무 문제가 없습니다.

실제로 보이는 내용을 좌우하는 파싱 세부 사항이 두 가지 있습니다. 시간 클레임은 JSON 숫자로 들어 있을 때만 읽습니다. 만료 시각이 문자열 "1699999999"로 적힌 토큰은 만료 시각이 전혀 없는 것으로 처리되어, 스스로 만료되지 않는다는 경고를 받습니다. 사실과 정반대입니다. 그리고 페이로드는 저희 JSON 도구가 쓰는 자릿수 보존 파서가 아니라 브라우저 자체의 JSON 파서로 파싱하므로, sub에 든 스노플레이크 사용자 ID 같은 64비트 숫자 클레임은 끝자리가 반올림되어 표시됩니다. JWT의 식별자가 보통 문자열인 이유가 바로 이것입니다. 숫자로 되어 있다면 클레임 표가 아니라 원본 페이로드에서 읽으세요.

다섯 부분으로 된 토큰은 암호화된 JWE로 보고 거부하며, 이 판단은 헤더를 읽지 않고 부분의 개수만으로 내립니다. 실제로는 맞지만, 지름길이라는 점은 알아 둘 만합니다. 세 부분이 아닌 토큰은 모두 바로 거부하며, 페이로드가 객체가 아니라 JSON 배열이나 단순 문자열로 디코딩되는 경우도 마찬가지입니다. 경고는 “none” 알고리즘과, 서명 키가 공개 키가 아닌 공유 비밀인 HS 계열에 대해 표시됩니다. RS, ES, PS로 서명된 토큰에는 아무 경고도 뜨지 않으므로, 이 페이지에서 아무 말이 없다는 것은 알려진 위험한 형태가 없다는 뜻일 뿐, 승인이 아닙니다.

다른 작업이 필요할 때

여기서는 아무것도 저장하지 않으며, 이 페이지가 존재할 수 있는 유일한 이유가 그것입니다. 그래도 들일 만한 습관은 아닙니다. 개인정보 보호 주장은 읽는 것만으로는 확인할 수 없습니다. 페이지를 불러온 뒤 연결을 끊고 디코더가 계속 작동하는지 보세요. 서버에 의존하는 도구는 바로 그것을 할 수 없습니다. 그리고 확인할 수 없는 곳에 붙여 넣은 토큰이 아직 유효하다면, 따져 보지 말고 교체하세요. 교체는 1분이면 끝납니다. 그러지 않으면 여전히 문을 열 수 있는 인증 정보를 두고 오랫동안 혼자 고민하게 됩니다. 브라우저 탭이 아니라 컴퓨터에서 토큰을 읽으려면 셸 한 줄이면 됩니다. 점으로 구분된 두 번째 필드를 잘라 base64 -d로 디코딩하고 jq로 넘기세요.

토큰이 말하는 내용이 아니라 토큰이 진짜인지가 궁금하다면, 이 페이지는 구조상 맞지 않는 도구이며 다른 모든 온라인 디코더도 마찬가지입니다. 검증은 키가 이미 있는 곳, 즉 서버에서 사용하는 언어의 JWT 라이브러리로 발급자가 공개한 JWKS와 대조해 해야 합니다. 몇 줄이면 되고, 의미 있는 답은 그것뿐이며, 대신 해 주겠다는 사이트는 절대 웹사이트에 주면 안 되는 단 하나의 비밀을 달라는 것입니다.

자주 묻는 질문

제 토큰이 어딘가로 전송되나요?

아니요. 그리고 이 페이지에서는 그것이 하나의 기능이 아니라 존재 이유 그 자체입니다. JWT는 보통 실제로 쓰이는 인증 정보입니다. 토큰을 가진 사람은 만료될 때까지 여러분인 척 행동할 수 있습니다. 토큰을 서버로 전송하는 온라인 디코더에 붙여 넣으면 작동하는 열쇠를 넘겨주는 것이며, 로그를 남기지 않겠다는 어떤 약속도 이를 되돌릴 수 없습니다. 이 디코더는 지금 보고 있는 페이지 안의 평범한 JavaScript입니다. 아무것도 저장하지 않고, 로그도 남기지 않으며, 어떤 요청도 보내지 않습니다. 페이지를 불러온 뒤 Wi-Fi를 꺼도 똑같이 작동합니다. 저희 말을 믿는 대신 개인정보 보호 주장을 직접 확인하는 가장 간단한 방법입니다.

서명도 검증하나요?

아니요. 서명 키 없이 그것을 정직하게 할 수 있는 온라인 디코더는 없습니다. 디코딩과 검증은 완전히 다른 작업입니다. 디코딩은 토큰의 Base64를 풀기만 할 뿐이며, 누구나 어떤 토큰에든 할 수 있고, 토큰이 진짜인지에 대해서는 아무것도 증명하지 못합니다. 검증은 토큰에 서명한 비밀 키나 공개 키로 서명을 다시 계산하는 것이며, 그 키는 절대 웹사이트에 붙여 넣으면 안 됩니다. 여기서 보이는 것은 토큰이 스스로 ‘주장하는’ 내용입니다. 그 주장을 믿을 수 있는지는 키를 가진 여러분의 서버만 답할 수 있습니다.

제가 보낸 JWT를 다른 사람이 읽을 수 있나요?

네, 전부 읽을 수 있으며, 많은 사람이 이 점을 놓칩니다. JWT는 서명된 것이지 암호화된 것이 아닙니다. 헤더와 페이로드는 비밀이 전혀 없는 인코딩인 Base64이므로, 토큰을 가로챈 사람은 안의 모든 클레임을 읽을 수 있습니다. 서명은 토큰을 ‘바꾸는’ 것을 막을 뿐, ‘읽는’ 것은 전혀 막지 못합니다. JWT 페이로드에는 기밀을 절대 넣지 마세요. 비밀번호, 카드 번호, 엽서에 적지 않을 개인 정보는 넣으면 안 됩니다.

“none” 알고리즘 경고는 무슨 뜻인가요?

토큰이 스스로 서명되지 않았다고 말한다는 뜻이며, 이 페이지가 보고하는 것 중 가장 심각한 발견 중 하나입니다. `alg: none`은 잘 알려진 인증 우회 수법입니다. 공격자는 실제 토큰을 가져와 페이로드를 관리자라고 바꾸고, 알고리즘을 “none”으로 설정하고, 서명을 지웁니다. 그러면 헤더를 믿는 라이브러리가 이를 받아들입니다. 제대로 된 JWT 라이브러리는 이제 모두 기본적으로 이를 차단하지만, `alg`를 믿는 구현은 여전히 존재합니다. `alg: none`인 토큰이 들어오면 아니라는 것이 증명될 때까지 공격으로 간주해야 합니다.

만료 시각은 어떻게 읽나요?

알아서 읽어 드립니다. `exp`, `iat`, `nbf`는 1970년부터 센 초 단위의 Unix 타임스탬프라 숫자 그대로는 읽을 수 없습니다. 각각을 사용자의 시간대에 맞춘 실제 날짜로, 얼마 전인지 또는 얼마 후인지와 함께 보여 드리며, 만료된 토큰은 직접 계산하게 두지 않고 분명하게 알려 드립니다. `exp`가 아예 없는 토큰도 표시합니다. 만료되지 않는 JWT는 만료로 무효화될 수 없으며, 서명 키가 유효한 동안 계속 유효합니다.

토큰이 세 부분이 아니라 다섯 부분이에요

그렇다면 서명만 된 것이 아니라 암호화된 JWE이며, 복호화 키 없이는 내용을 정말로 읽을 수 없습니다. 페이지가 이 형태를 인식해 알아볼 수 없는 내용을 보여 주는 대신 그렇다고 알려 드립니다. 다섯 부분이라는 것은 페이로드가 실제 암호문이라는 뜻이며, 디코딩할 것이 없습니다.

표준 클레임에는 무엇이 있나요?

등록된 클레임은 다음과 같습니다. `iss`는 발급자, `sub`는 토큰이 가리키는 주체(보통 사용자 ID), `aud`는 토큰을 받을 대상, `exp`는 만료 시각, `nbf`는 유효 시작 시각, `iat`는 발급 시각, `jti`는 토큰의 고유 ID입니다. 그 밖의 것은 모두 시스템을 만든 쪽이 정한 사용자 정의 클레임입니다. 결과에서 등록된 클레임마다 의미를 표시해 드리므로, 세 글자 약어가 각각 무엇인지 외울 필요가 없습니다.

참고: 디코딩만 하며 검증은 하지 않습니다. JWT의 서명은 토큰이 변조되지 않았음을 증명하며, 이를 확인하려면 발급자의 비밀 키나 공개 키가 필요합니다. 그런 키는 절대 웹 페이지에 붙여 넣으면 안 됩니다. 여기 표시되는 모든 내용은 증명된 것이 아니라 주장된 것으로 보고, 서버에서 검증하세요.

내 웹사이트에 이 도구 넣기

블로그, 수업 페이지, 도움말 글 어디에나 무료로 넣을 수 있습니다. 코드 한 줄만 붙여 넣으면 방문자가 페이지에서 바로 사용할 수 있습니다.