2026-06-27 · 6 min read · Rahul Chitturi
- jwt
- auth
- debugging
A JWT can be signed correctly and still fail with a 401 when the audience claim does not match the API that receives it. This often happens after moving between staging and production, adding a new resource server, or copying a token from the wrong client.
Before rotating keys or weakening verification, decode a non-production token and compare the expected audience contract with the value that actually arrived at the API.
Start with the resource identifier
The audience is usually the API identifier, application ID URI, or resource name configured in the identity provider. It is not always the frontend client ID. If the verifier expects one string and the token contains another, the request should fail even when issuer and signature checks pass.
- Confirm whether aud is a string or an array
- Compare staging and production API identifiers
- Check tenant-specific issuer settings before editing code
- Do not accept multiple audiences unless the API really serves them
Separate audience from scopes
Scopes and permissions answer what the caller can do. Audience answers which API the token is for. A token with the right scope but the wrong audience is still unsafe to accept because another service may have been the intended recipient.
When debugging, write down the expected issuer, audience, and scope in one place. That makes it easier to spot a frontend requesting the wrong resource or a backend verifying against stale configuration.
A Flashman workflow
Decode the JWT locally, format any provider metadata JSON, and diff a working token against the failing token after redacting user-specific claims. Look for drift in iss, aud, azp, client_id, scope, and environment-specific URLs.
Flashman runs this inspection in your browser, so the token is not uploaded to a server. Use synthetic or non-production tokens whenever possible, and never paste long-lived secrets into a debugging ticket.