2026-07-12 · 6 min read · Rahul Chitturi
- jwt
- auth
- debugging
A JWT can be fresh, correctly signed, and still rejected with a 401 if the audience or issuer does not match what the API expects. These failures often appear after moving between staging and production, adding a new identity provider tenant, or copying config from a different service.
Treat the token as evidence, not as proof of authorization. Decode a non-production token, inspect the claims, and compare them with the verifier configuration before changing middleware or relaxing checks.
Compare claims to configuration
The iss claim should match the trusted issuer exactly, including scheme, host, tenant path, and trailing slash behavior. The aud claim should name the API or client identifier that the verifier was configured to accept.
- Decode the header and payload without treating them as trusted input
- Check issuer metadata from the provider against deployed environment variables
- Confirm staging tokens are not being sent to production APIs
- Record exp, nbf, and iat so clock issues do not hide a claim mismatch
Use safe fixtures for review
Production bearer tokens belong in neither tickets nor chat. Recreate the same issuer, audience, and timestamp shape with fake values, then diff expected and failing examples. This makes the contract visible without exposing user identifiers, scopes, or tenant details.
If multiple APIs share an auth gateway, document which audience each route expects. A token that works for one service may correctly fail against another.
A Flashman workflow
Use the JWT decoder to inspect claims, the JSON formatter for provider metadata, the timestamp converter for token time fields, and the diff tool to compare expected config with the failing deployment.
Keep the final note specific: which claim differed, which environment variable or provider setting fixed it, and which fake token fixture proves the next regression test.