개발자 작업 흐름

JWT를 안전하게 디코딩하기

JWT를 안전하게 디코딩하기를 위한 실전 가이드입니다. JWT 디코더를 사용해 입력 확인부터 결과 검토까지 브라우저 안에서 진행합니다.

문제 상황

JWT는 짧고 로그에 붙여넣기 쉽지만, 디코딩된 payload에는 사용자 식별자, scope, tenant ID, 세션 데이터, 만료 시간이 들어 있을 수 있습니다. 디코딩은 인증 문제를 디버깅하는 데 도움이 되지만 signature 검증이나 토큰을 신뢰해도 된다는 증명은 아닙니다.

이럴 때 사용하세요

  • API가 401 또는 403을 반환해 토큰 만료, audience, scope를 먼저 확인해야 할 때 사용합니다.
  • 로그인 후 역할이나 권한이 빠진 것처럼 보일 때 적합합니다.
  • 지원 사례에 일부 가려진 토큰이 포함되어 있고 비밀이 아닌 claim만 확인해야 할 때 도움이 됩니다.
  • staging 토큰은 동작하지만 production API에서 실패해 issuer, audience, tenant claim을 비교해야 할 때 사용합니다.
  • 요청이 access token, ID token, refresh 관련 값을 잘못된 위치에 사용했는지 확인해야 할 때 사용합니다.

단계

  1. 1단계

    민감한 값 먼저 가리기

    티켓, 스크린샷, 채팅, 문서에 공유하기 전에 실제 token 값과 사용자 식별자를 제거하거나 대체합니다.

  2. 2단계

    토큰 종류와 환경 확인

    토큰이 development, staging, production 중 어디에서 왔는지, API, 브라우저 세션, identity claim, refresh flow 중 어디에 쓰이는지 확인합니다.

  3. 3단계

    header와 payload 디코딩

    토큰을 로컬에서 열어 algorithm, key identifier, issuer, audience, subject, expiry, scope claim을 확인합니다.

  4. 4단계

    시간 기반 claim 확인

    exp, nbf, iat 값을 실패한 요청에 관여한 클라이언트나 서버의 시각과 비교합니다.

  5. 5단계

    신뢰하기 전 별도 검증

    토큰을 진짜로 신뢰하기 전에는 애플리케이션, identity provider, backend library에서 signature를 검증해야 합니다.

  6. 6단계

    실패한 요청과 claim 연결

    디코딩한 audience, issuer, scope, role, tenant 식별자를 요청이 거부된 API route, 환경, 권한 검사와 비교합니다.

예시

JWT를 안전하게 디코딩하기 예시

입력

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzQyIiwic2NvcGUiOiJyZWFkOmJpbGxpbmciLCJhdWQiOiJhcGkiLCJleHAiOjE3MDAwMDAwMDB9.signature

출력

{
  "sub": "user_42",
  "scope": "read:billing",
  "aud": "api",
  "exp": 1700000000
}

흔한 실수

디코딩을 검증으로 착각

누구나 JWT payload를 Base64URL로 디코딩할 수 있습니다. 검증은 신뢰할 수 있는 key로 signature와 claim을 확인해야 합니다.

실제 production token을 공유

Access token은 실제 권한을 부여할 수 있습니다. 디코딩한 claim을 어디든 올리기 전에 test token을 쓰거나 민감한 값을 가리세요.

Authorization 헤더 전체를 붙여넣는 경우

Bearer 뒤의 토큰 값만 복사하세요. 헤더 문구, 따옴표, 줄바꿈이 함께 들어가면 정상 토큰도 디코더에서 잘못된 형식처럼 보일 수 있습니다.

검증되지 않은 토큰의 alg 값을 신뢰하는 경우

JWT 헤더도 서명이 검증되기 전까지는 사용자가 제공한 데이터입니다. 디코딩된 alg 필드만 보고 검증 방식을 결정하지 마세요.

다른 환경의 token으로 디버깅

staging token은 정상적으로 디코딩되어도 issuer, audience, key set, tenant, clock 설정이 달라 production에서 실패할 수 있습니다.

access token과 ID token을 혼동

ID token은 로그인한 사용자를 설명하고, access token은 보통 API가 기대하는 값입니다. claim을 디코딩한 뒤 identity provider 문서와 토큰 종류를 대조하세요.

자주 묻는 질문

JWT를 디코딩해도 안전한가요?

로컬에서 구조를 확인하는 단계로는 안전하지만, 실제 token을 공유하거나 signature 검증 없이 claim을 신뢰하면 안 됩니다.

토큰은 디코딩되는데 인증은 왜 실패하나요?

토큰이 만료됐거나 발급자가 다르거나, 다른 audience용이거나, 필요한 scope가 없거나, signature 검증에 실패했을 수 있습니다.

JWT 디코더가 권한을 검증할 수 있나요?

디코더는 권한 관련 claim을 보여줄 수 있지만, 해당 claim이 요청에 유효한지는 backend나 identity provider가 판단해야 합니다.

어떤 JWT 클레임부터 확인해야 하나요?

먼저 exp, nbf, iss, aud, sub, scope, roles, tenant 또는 organization 식별자를 확인하세요. 만료된 세션, 잘못된 환경의 토큰, 누락된 권한을 설명하는 경우가 많습니다.

디코딩한 클레임을 프런트엔드 권한 판단에 써도 되나요?

디코딩한 클레임은 디버깅이나 표시용 힌트로만 사용하세요. 실제 권한 판단은 서버에서 서명, 발급자, 대상, 만료, scope를 검증한 뒤 처리해야 합니다.

디코딩한 JWT 정보를 공유하기 전에 무엇을 가려야 하나요?

원본 token, subject 식별자, 이메일, tenant ID, organization ID, session ID, 내부 계정 구조를 드러내는 custom claim을 제거하세요.

JWT 디코딩과 검증은 무엇이 다른가요?

디코딩은 header와 payload를 읽는 단계입니다. 검증은 신뢰할 수 있는 key로 signature, 발급자, 대상, 만료, 관련 규칙을 확인해 토큰을 받아들일지 결정합니다.