An API that accepts JWTs should fix the allowed algorithms in its own configuration, verify the signature, and then check issuer, audience, expiry and token type. Reject the whole token if any check fails. RFC 8725 is the standard reference.
Step 1: choose the algorithm yourself
RFC 8725 section 3.1 says libraries should let callers specify allowed algorithms, and each key should be used with exactly one algorithm. The OWASP REST cheat sheet adds the practical rule: pick the verification algorithm from your own configuration, not from the token header.
The header is attacker-controlled. If your code reads it to decide how to verify, the attacker chooses.
Step 2: use appropriate algorithms
Section 3.2 says to allow only currently secure algorithms and support changing them over time. On the none algorithm, the RFC says it is acceptable only when another layer protects the token, and libraries should not produce or consume unsigned JWTs unless explicitly asked. For an API, reject unsigned tokens. See JWT algorithm myths.
Step 3: validate the cryptography
- Section 3.3: reject the entire JWT if any cryptographic check fails, including both layers of nested tokens.
- Section 3.5: do not use human-memorable passwords directly as HMAC keys such as HS256 keys. Use keys with enough entropy.
- Section 3.4: check elliptic curve inputs for validity before use.
Step 4: validate the claims
- Issuer and subject (3.8). Confirm the signing keys belong to the issuer and that the subject is valid for your application.
- Audience (3.9). When one issuer serves many relying parties, require an audience claim and reject tokens whose audience is not you.
- Expiry. The OWASP cheat sheet says to validate iss, aud and exp by default, plus nbf where your token profile requires it.
Audience is the one teams skip. Without it, a token minted for service A may work on service B.
Step 5: do not trust header claims blindly
Section 3.10 covers the kid header and the jku and x5u URLs. Sanitize kid values to prevent injection, and guard against server-side request forgery from jku and x5u with an allow-list. A key lookup URL taken from the token is an SSRF door.
Step 6: use explicit types
Sections 3.11 and 3.12 say to use the typ header to distinguish JWT types and make validation rules for different kinds of tokens mutually exclusive, for example by distinct typ, claims, keys, audiences or issuers. This stops an ID token from being replayed as an access token.
Step 7: plan for early revocation
JWTs are valid until they expire. The OWASP cheat sheet suggests a jti denylist when you need to end a session early. Keep lifetimes short so the list stays small.
The checklist
- Algorithms fixed in server config.
- Unsigned tokens rejected.
- Signature verified with the right key.
- Issuer matches.
- Audience matches this API.
- exp checked, nbf where relevant.
- Type and token kind checked.
- kid sanitized, jku and x5u allow-listed or ignored.
- Failure of any check rejects the token.
Quick check
Is checking the signature enough?
No. A correctly signed token from the wrong issuer, for the wrong audience, or past expiry should still be refused.
Should I write my own JWT parsing?
Use a maintained library, configure it with allowed algorithms, and keep it updated. Dependency scanning helps you notice advisories in it.
Safeguard's SBOM and dependency scanning can flag known advisories in the JWT library you use, and the free scan at gold.safeguard.sh/scan takes a minute.
Sources
Last reviewed: 19 October 2026.