Auth & Identity

Validating a JWT

Validating a JWT means more than decoding it. A recipient must verify the signature and check the issuer, audience, and expiry before trusting any claim the token carries.

What you'll learn

  • List the mandatory checks for JWT validation
  • Explain why decoding is not the same as validating
  • Describe how the signing key is selected and verified
  • Avoid the most common validation pitfalls

7 min

Decoding is not validating

Anyone can decode a JWT's header and payload, because they are nothing more than base64url-encoded JSON with no key required. Reading the claims that way tells you what the token asserts — who it says the user is, what it says they may do — but it tells you nothing about whether those assertions are actually trustworthy. Validation is the separate cryptographic and logical process that establishes that trust.

Skipping validation and acting on decoded claims is one of the most dangerous mistakes in API security, and it is alarmingly easy to make because decoding feels like it produced real data. A forged token carrying attacker-chosen claims would sail straight through any code that decodes without verifying. The golden rule is simple: never make an authorisation decision based on a token you have only decoded, never validated.

The mandatory checks

Every validation must confirm several distinct things, and omitting any one of them leaves a gap. The signature must be valid for the issuer's key, proving the token is genuine and unaltered. The issuer claim must match the authorisation server you expect, so a token from some other provider is not accepted. The audience claim must name your service specifically. And the token must fall within its not-before and expiry window, so stale or not-yet-valid tokens are rejected.

Each check defends against a real attack. An unchecked audience, for example, lets a token that was legitimately minted for a different service be replayed against yours by whoever holds it. Verify all of these on the Merion API as an automatic matter of course, not as an optional hardening step you might add later.

Selecting the signing key

The token header's key identifier tells you which public key to use for verification. The correct procedure is to fetch the issuer's keys from its JWKS endpoint, match on that identifier, and verify the signature with the key you found. Crucially, you must also confirm that the signing algorithm is one you actually expect and allow, rather than trusting whatever the header claims.

This is where a great deal of real-world breakage has occurred. Never trust the algorithm field blindly: explicitly reject tokens whose algorithm is set to none, and pin the specific algorithms you will accept so an attacker cannot downgrade or substitute one. The header is attacker-controllable, so it tells you what key to look up, not what to trust. Key publication and rotation are covered in JWKS and Key Rotation.

Common pitfalls

Beware the alg=none attack, in which a token declares that it needs no signature at all and a naive validator obligingly accepts it. Beware, too, algorithm-confusion attacks that mix symmetric and asymmetric algorithms; these have produced genuine bypasses in widely used systems where a public key was mistakenly used as a symmetric secret. And always enforce expiry strictly, allowing only a small tolerance for clock skew between servers rather than ignoring time entirely.

The safest path through all of this is to use a well-maintained, widely audited library rather than hand-rolling verification, because the subtle cryptographic details are exactly where mistakes hide. Configure that library to pin algorithms and check every claim. We list more traps to watch for in Common Auth Mistakes.

Key takeaways

  • Decoding reveals claims; validation establishes whether to trust them
  • Always check signature, issuer, audience, and expiry
  • Select the key by its identifier and pin the expected algorithm
  • Reject alg=none and prefer a vetted library over custom code

FAQ

Why must I check the audience claim?

Without it, a token issued for a different service could be replayed against yours. The audience check ensures the token was intended for you specifically.

What is the alg=none attack?

An attacker sets the algorithm to none, claiming the token needs no signature. A naive validator accepts it. Always reject none and pin allowed algorithms.

Should I write my own JWT validation?

Generally no. Subtle cryptographic mistakes are easy to make. Use a well-maintained library that handles signatures, algorithms, and claims correctly.

Integrate with Merion

Ready to build?

Read the API reference, grab the OpenAPI spec, and ship a resilient integration.