A JSON Web Token can carry a request, a session, an access grant, a logout event, or a signed claim from an external service. If a verifier accepts all of them through the same key and the same parser, the token's header becomes a hint rather than a security control. RFC 8725 recommends explicit typing for this reason, and RFC 9068 gives OAuth access tokens a concrete type value that resource servers can enforce.
The algorithm field is another decision point. The token header names an algorithm, but the verifier must choose the acceptable key type and algorithm from its own configuration. Trusting a kid to select any key in a shared set, or trusting alg to select a key type without an allowlist, expands the attack surface across every token issuer that shares the parser.
Give each token a purpose
RFC 8725 describes explicit typing as a way to distinguish different kinds of JSON Web Tokens. A token minted as an ID token, a token minted for a public form, and a token minted for an administrative API should not be interchangeable. They may use the same signing library, but they should not share an undefined token type.
RFC 9068 is a useful example. Its JWT access-token profile requires the typ header to identify the token as an access token. A resource server enforcing that profile must reject any other value. The rule is not that every JWT must use one universal string. The rule is that the verifier knows the expected purpose and rejects a token that does not declare it.
Applications can define their own media types when they need them. The value should be documented, registered where appropriate, and checked before claims are consumed. A missing typ field may be tolerated for a legacy token, but that decision needs an explicit compatibility scope. It should not become the default for new issuers.
Validate the algorithm and key together
Use an allowlist of signing algorithms for each issuer and token purpose. Reject none unless the protocol explicitly requires an unsecured token and the verifier has a separate path for it. Compare the key type to the algorithm. A key identifier should select a key from the issuer's trusted set, not from an arbitrary document supplied by the caller.
Do not let a token carry its own JWKS URL or issuer URL when the verifier is supposed to trust a fixed issuer. Resolve metadata through a preconfigured, authenticated discovery process and cache it with an expiry. Validate the issuer, audience, expiration, issued-at time, and any subject constraints after the signature check. The exact claim requirements depend on the profile, so use the profile rather than a generic JWT valid function.
Audience is especially easy to misuse. A token minted for a calendar integration should not be accepted by a billing API merely because the signing key is trusted. Separate audience values, or separate keys, for materially different trust domains. If one issuer serves many applications, make the audience and token type part of the resource server's configuration.
Make errors indistinguishable to clients
Return a small set of public error codes, such as invalid token or insufficient scope. Keep detailed diagnostics in the security log: issuer, key ID, expected type, algorithm, audience check, and verification stage. Do not put the token in the log. A token can contain personal data, a session identifier, or another bearer secret.
Monitor rejected token types across services. A spike may come from a deployment that started issuing the wrong header or from a client replaying a token to the wrong API. Track accepted tokens by issuer, audience, and type, but aggregate the metrics so an operator cannot reconstruct a user's activity from debugging dashboards.
Test with tokens that look valid
Create test cases for a trusted signature with the wrong typ, the wrong audience, an expired time, a key from another issuer, and an algorithm outside the allowlist. Test nested tokens and encrypted tokens separately. If the application supports both JWTs and opaque tokens, test that an opaque token cannot be interpreted as a JWT and that a JWT cannot bypass the opaque-token lookup.
Do not use a token's type as a substitute for authorization. A correctly typed administrative token still needs a scope or role check. A correctly typed user token still needs an object-level authorization decision. The verifier's job is to establish what the token is and whether it was issued for this service. The application still decides what the subject may do.