A valid signature proves a token was signed by a key you trust. It does not prove the token was meant for your service or for this purpose. RFC 8725 says to also validate the issuer, subject, audience and, for new uses, an explicit token type.
The substitution problem
Imagine one identity provider issues tokens for ten services. A token for service A carries a valid signature. If service B accepts any validly signed token from that issuer, an attacker with access to A's token can replay it at B. The signature is fine. The token is simply being used where it was never intended.
This is why RFC 8725 treats claim validation as part of verification, not an optional extra.
What each check does
- iss (issuer): confirm the signing keys really belong to the issuer named in the token. Reject if not.
- sub (subject): confirm the subject maps to a valid subject in your application.
- aud (audience): when one issuer serves several relying parties, the token should carry aud, and you must reject it if it is missing or does not name you.
- typ (type): an explicit type distinguishes kinds of JWT, such as an access token from an ID token. The RFC recommends it for new JWT uses.
Mutually exclusive validation rules
RFC 8725 adds a subtle point. If one issuer issues different kinds of tokens, make the validation rules mutually exclusive, so a token for one purpose cannot pass as another. Use distinct typ values, claims, keys, audiences or issuers to separate them.
A common real world example is accepting an ID token where an access token is expected. If both are signed by the same key and carry similar claims, the wrong kind may sail through unless typ or aud tells them apart.
A short implementation list
- Configure the expected issuer, audience and type per endpoint.
- Compare issuer and audience with exact string matches.
- Treat a missing aud as a failure when you expect one, not as a pass.
- Reject the token if any check fails. Do not fall back to a lenient path.
- Keep time checks (exp, nbf) with a small clock skew allowance, and log failures by reason so you can debug.
- Write a test for each claim: wrong issuer, wrong audience, wrong type, missing claim.
Do not trust received claims blindly
Claims inside the token describe the subject. They are only as trustworthy as the issuer's process for setting them. Do not let a client-controlled claim decide authorization without checking it against your own records.
Quick check
Is checking aud needed if I only have one service?
If a single issuer might ever issue tokens for other services, yes. Adding the check early costs little and prevents cross-service replay later.
Where does typ appear?
In the JWT header. RFC 8725 recommends explicit typing for new JWT uses and describes including the type in the inner JWT of nested tokens.
Safeguard's dependency scanning can show which JWT libraries and versions your services use, and the free scan at gold.safeguard.sh/scan covers dependency risk.
Sources
Last reviewed: 19 October 2026.