API 연동에서 401·403이 반복되면, 코드보다 토큰을 먼저 의심하세요. JWT는 Header·Payload·Signature 세 부분으로 이뤄지며, JWT 디코더로 디코딩·만료·클레임을 빠르게 확인할 수 있습니다.
JWT 구조
| 파트 | 내용 | 디버깅 포인트 |
|---|---|---|
| Header | alg, typ | alg 불일치 |
| Payload | sub, exp, roles | exp 만료 |
| Signature | HMAC/RSA | secret·키 불일치 |
eyJhbGciOiJIUzI1NiIs... ← Header.Payload.Signature
디버깅 5단계
- 디코더에 Bearer 토큰 붙여넣기 (로그에 secret 노출 금지)
expvs 현재 Unix time — 60초 skew 허용 여부 확인iss·aud가 API 설정과 일치하는지- 역할(roles) 클레임이 RBAC와 매칭되는지
- Signature verify 실패 시 환경별 secret (.env) 대조
흔한 실수
- 프론트에 refresh token 장기 보관
- Payload에 PII 과다 저장
- Base64 디코딩만 하고 서명 검증 생략
팁: 스테이징·프로덕 secret이 바뀌면 구 토큰은 전부 401입니다. API 문서의 Auth 섹션과 Bearer 헤더 검증 패턴을 함께 업데이트하세요.
환경별 체크리스트
| env | 확인 |
|---|---|
| local | .env secret |
| staging | iss URL |
| prod | clock skew NTP |
401이 intermittent면 만료 직전 refresh race condition을 의심하세요.
보안
디코더에 prod real user token 붙여넣지 마세요. staging synthetic user 또는 jwt.io 대신 사내 도구만 사용하고, 붙여넣은 토큰은 세션 종료 시 클립보드 clear.
Postman 연동
디코더에서 확인한 exp·roles를 Postman pre-request script와 대조하세요. 수동 Bearer 붙여넣기와 automated refresh token flow가 다른 claims를 쓰면, 'Postman에선 되는데 앱에선 401' 패턴이 생깁니다.
mobile app refresh token rotation bug는 '가끔 401'로 나타납니다. 디코더로 old/new token pair의 iat·jti diff를 비교하면, duplicate refresh request인지 single-use violation인지 5분 안에 갈립니다.