JWT 검증 절차 — 토큰이 유효한지 판단하는 단계
JWT 검증 절차 — 토큰이 유효한지 판단하는 단계
서버가 받은 JWT를 '검증한다'고 하면 흔히 서명만 확인한다고 생각하기 쉬운데요. RFC 7519 §7.2는 검증을 훨씬 더 단계적으로 정의해요. 형식이 맞는지, 헤더가 이해되는지, 서명이 맞는지, 페이로드가 온전한 JSON인지를 순서대로 확인해요. 나열된 단계 중 하나라도 실패하면 토큰은 반드시 거부돼야 해요.
본문
검증 단계 사이에 의존성이 없는 경우 순서는 중요하지 않아요. 다음 단계 중 하나라도 실패하면 JWT는 거부돼요. 즉, 애플리케이션에 잘못된 입력으로 취급돼요.
- JWT에 점(.) 문자가 하나 이상 들어 있는지 확인한다.
- 첫 번째 점(.) 이전 부분을 Encoded JOSE Header로 둔다.
- Encoded JOSE Header를 Base64url 디코딩한다. 이때 줄바꿈, 공백, 기타 추가 문자가 없어야 한다.
- 결과 옥텟 시퀀스가 RFC 7159를 따르는 온전한 JSON 객체의 UTF-8 인코딩인지 확인하고, 이 JSON 객체를 JOSE Header로 둔다.
- JOSE Header에 포함된 파라미터와 값이 모두 이해·지원되는 문법과 의미를 갖고 있는지(또는 이해하지 못할 때 무시하도록 명시됐는지) 확인한다.
- JWT가 JWS인지 JWE인지 판별한다.
- JWS라면 JWS 검증 절차를 따르고, JWS Payload를 Base64url 디코딩한 결과를 Message로 둔다. (JWE라면 복호화한 평문을 Message로 둔다.)
- JOSE Header의
cty값이JWT라면, Message는 중첩 서명/암호화의 대상이 된 JWT이므로, 이 Message를 새 JWT로 삼아 1단계로 돌아간다. - 그렇지 않다면 Message를 Base64url 디코딩한다(추가 문자 없이).
- 결과가 RFC 7159를 따르는 온전한 JSON 객체의 UTF-8 인코딩인지 확인하고, 이 객체를 JWT Claims Set으로 둔다.
검증은 서명 확인만이 아니다
이 절차를 보면 검증이 '서명이 맞는지'만 보는 게 아니라는 게 분명해져요. 형식 검사(14) → 헤더 이해도 검사(5) → 실제 서명·암호 검증(67) → 중첩 여부 처리(8) → 페이로드 온전성(9~10)까지가 한 흐름이에요.
특히 마지막에 주의점이 하나 있어요. JWT가 성공적으로 검증됐더라도, 사용된 알고리즘이 애플리케이션에 허용된 것이 아니라면 거부해야(SHOULD) 해요. 이 판단은 각 애플리케이션의 몫이에요. 그래서 검증 시 alg를 화이트리스트로 확인하는 게 표준 절차의 일부로 권장돼요.
만료·시간 검증은 어디서?
RFC 7519 §7.2의 절차는 구조·서명·형식 검증을 다루고, exp(만료), nbf(시작 전), aud(수신자) 같은 클레임의 의미적 검증은 애플리케이션이 수행해요. 예를 들어 현재 시간이 exp 이후라면 만료된 토큰으로 거부해야 해요. 라이브러리들은 보통 이 두 층위(형식·서명 검증 + 클레임 검증)를 함께 제공하지만, 개념적으로는 구분해서 이해하는 게 좋아요.