JWT 401/403 Diagnostic Playbook
401 usually indicates authentication failure, while 403 indicates authorization denial. Separate header-level and token-level checks for reproducible diagnosis.
First split to make
- For 401, prioritize WWW-Authenticate challenge details
- For 403, prioritize scope/role/policy evaluation
- If both occur, suspect clock skew and key rotation issues
Diagnostic steps
- 1) Validate scheme and format with Authorization Inspect
- 2) Inspect error/description/scope with WWW-Authenticate Inspect
- 3) Read exp/nbf/aud/iss/scope with JWT Decoder
- 4) Run signature, kid, and iss/aud checks with JWT Verifier
- 5) Quantify expiry and clock drift with JWT TTL Check
Typical causes
- 401: malformed token, expiration, signature mismatch
- 403: missing scope/role, resource policy mismatch
- Mixed failures: iss/aud environment drift, delayed key distribution, unsynced NTP
Operational checklist
- Persist reason codes for 401/403 in logs
- Pin expected iss/aud/scope values in config
- Maintain overlap window for old keys during kid rotation
- Monitor server clock synchronization (NTP)
- Avoid logging sensitive claims
Post-fix verification
- Confirm 401/403 rates return to expected baseline
- Ensure challenge details align with implementation error codes
- Verify successful requests recover after token renewal
Tools to use
- JWT 401/403 Troubleshooting
- Authorization Inspect
- WWW-Authenticate Inspect
- JWT Decoder
- JWT Verifier
- JWT TTL Check
FAQ
- How should 401 and 403 be separated?
- Use 401 for authentication failures and 403 for authorization denials. Separate WWW-Authenticate handling from scope/role checks.
- Can a token return 401 even before exp?
- Yes. Signature mismatch, iss/aud mismatch, nbf constraints, and clock skew can all produce 401.
Referenced specs
Next to view (diagnostic order)
These links are generated from site_map rules in recommended diagnostic order.
- JWT 401/403 Troubleshooting — Troubleshoot 401/403 auth failures from headers and JWT claims
- Authorization Inspect — Parse Authorization header formats
- WWW-Authenticate Inspect — Parse WWW-Authenticate challenges
- JWT Decoder — Decode and pretty-print JWT header/payload
- JWT Verifier — Verify JWT signatures (HS/RS/ES)
- JWT TTL Check — Calculate validity window and remaining TTL from exp/iat/nbf
- Symptom-Based Diagnostic Guide (Start Here) — A central hub that routes cache/CORS/JWT/MIME incidents into shortest symptom-first diagnostic paths
- How to Diagnose Missing 304 Responses — Trace ETag/Last-Modified and If-* round trips to isolate missing 304 behavior
Same-theme links
Scenario Clusters
Operational incident scenarios that route you into the shortest diagnostic path
- Symptom-Based Diagnostic Guide (Start Here) — A central hub that routes cache/CORS/JWT/MIME incidents into shortest symptom-first diagnostic paths
- How to Diagnose Missing 304 Responses — Trace ETag/Last-Modified and If-* round trips to isolate missing 304 behavior
- How to Diagnose Stale Content After Deployment — Check cache policy by HTML/API/static assets to isolate stale deployment issues quickly
- How to Diagnose CORS Preflight Failures — Fix preflight failures by validating OPTIONS responses, Allow-* directives, and origin rules in order
- How to Diagnose Retry Storms on 429/503 — Isolate Retry-After parsing and client implementation gaps to stop excessive retries
- How to Diagnose JS/CSS Blocks from nosniff Mismatch — Trace Content-Type vs nosniff mismatches, fallback responses, and delivery-layer rewrites
- How to Diagnose Set-Cookie Not Persisting — Isolate cookie persistence failures by checking Domain/Path/Secure/SameSite in order
- How to Diagnose Lost Login After OAuth Return — Isolate cookie-delivery failures after IdP return across SameSite, Secure, Path/Domain, and collisions
- How to Diagnose Same-Name Cookie Collisions — Resolve unstable behavior by tracing same-name cookie path/domain variants, overwrite order, and send collisions
- Cookie Incident Operational Checklist — Standardize response from triage to permanent fixes across storage failures, OAuth return issues, and same-name collisions