keepcalculator

06 Numbers and Powers

JWT Validation: What an API Can and Cannot Trust

Card No. 06·63840 · Updated · Standard formula, shown below

JWT validation tells an API which claims inside a token are safe to act on and which are not. An API can trust the signature, expiration, and any claims it issued itself, but it cannot trust claims from external sources, unverified headers, or any data that was not signed by the issuer it recognizes.

Background: Why JWTs Need Validation

JSON Web Tokens (JWTs) are a compact, URL-safe way to pass identity and authorization data between parties. They are widely used in modern APIs for stateless authentication: after a user logs in, the server issues a signed token, and the client sends that token with each request. The API then verifies the token to decide what the user may do.

The danger is that a JWT is just a string of base64-encoded JSON. Anyone can craft a token with any claims they want—”admin”: true, “user_id”: 12345, or “role”: “superuser”—but only tokens signed by a trusted issuer are valid. Without proper validation, an attacker can forge a token and gain unauthorized access.

Validation is the process of checking the token’s structure, signature, and expiration before trusting any of its contents. It is the difference between accepting a token at face value and verifying that it really came from the party you trust.

How JWT Validation Works

A JWT has three parts: a header, a payload, and a signature. The header declares the signing algorithm (like HS256 or RS256). The payload contains claims such as sub (subject), exp (expiration), iat (issued at), and custom claims like role or permissions. The signature is computed over the header and payload using a secret (HMAC) or a private key (RSA/ECDSA).

Validation typically involves these steps:

  • Check the header: ensure the alg is one you expect (e.g., RS256, not “none”).
  • Verify the signature: recompute the signature using the issuer’s public key or shared secret and compare it to the token’s signature.
  • Check the expiration: the exp claim must be in the future. Some tokens also have nbf (not before) which must be in the past.
  • Validate issuer and audience: the iss and aud claims must match what your API expects.
  • Check custom claims only after the above pass: only then can you trust claims like role or user_id.

Most JWT libraries (like jsonwebtoken for Node.js, PyJWT for Python, or java-jwt) handle these steps if you configure them correctly. The key is to never skip the signature check and never trust a token that fails any of these checks.

What an API Can Trust

Once a token passes validation, the API can trust the claims that were signed by the issuer. Specifically:

  • The identity claims: sub (the user ID) and any other claims the issuer put in the payload.
  • Authorization claims: roles, permissions, or scopes that the issuer assigned. These are safe because they were signed, so they cannot be altered without invalidating the signature.
  • Time-based claims: exp, iat, nbf are reliable for enforcing token lifetime.
  • Audience and issuer: these are safe to check because they are part of the signed payload.

In short, an API can trust anything that is inside the signed payload, provided the signature is valid and the token has not expired. The signature guarantees that the claims were not tampered with after issuance.

What an API Cannot Trust

There are several things an API must never trust, even if the token looks valid:

  • The header’s alg field: an attacker could change the algorithm to “none” or to a weaker one if the server does not enforce a fixed algorithm. Always pin the expected algorithm.
  • Claims from unverified tokens: if the signature check fails, the token is invalid and no claim should be trusted.
  • Claims that are not signed: some JWTs include unsecured JWTs (with no signature) or tokens where the signature is optional. Those are not trustworthy.
  • Data from external sources: if your API receives a token from a third-party identity provider, you can trust claims that the provider signed, but you cannot trust claims that your own system added after the fact unless they are re-signed.
  • User-supplied claims in the payload: if a client can send a token with a custom claim like "role": "admin" and your API accepts it without verifying the signature, that is a critical vulnerability.
  • The token’s “freshness” beyond exp: if you need to revoke a user immediately, a JWT cannot be invalidated until it expires unless you maintain a blocklist or use short-lived tokens with refresh tokens.

A common mistake is to decode the JWT (base64-decode the payload) without verifying the signature. Decoding is not validation. Anyone can decode a JWT; the signature is what makes it trustworthy.

How to Choose the Right Validation Strategy

Choosing a validation strategy depends on your architecture and security requirements. Here are the main options:

  • Local validation: your API has the public key (RS256) or shared secret (HS256) and verifies the signature itself. This is fast and stateless, but you cannot revoke a token before it expires.
  • Introspection: your API calls the authorization server’s introspection endpoint to check if the token is still valid. This allows immediate revocation but adds a network round-trip per request.
  • JWKS (JSON Web Key Set): your API fetches the issuer’s public keys dynamically from a JWKS endpoint, so you can rotate keys without redeploying your service.
  • Hybrid: use local validation for performance, but also call an introspection endpoint for sensitive operations or when revocation is critical.

For most APIs, local validation with RS256 and a JWKS endpoint is the recommended approach because it is secure, fast, and supports key rotation. HS256 is simpler but requires sharing a secret, which is harder to manage across multiple services.

Common Problems and Pitfalls

Even with validation, there are common pitfalls that can break security:

  • Algorithm confusion: if your server accepts both HS256 and RS256, an attacker could sign a token with the public key as the HMAC secret. Always whitelist the exact algorithm.
  • Not checking exp: if you forget to check expiration, a stolen token works forever.
  • Trusting the alg header: the “none” algorithm allows unsigned tokens. Never allow it.
  • Using a weak secret for HS256: if the secret is short or guessable, attackers can brute-force it.
  • Ignoring aud: if your API does not check the audience, a token issued for another service could be used against yours.
  • Storing tokens insecurely: even a valid token is useless if it is stolen from logs, browser storage, or URL parameters.

Another misconception is that JWTs are encrypted. They are not—they are only signed. The payload is base64-encoded, which is not encryption. Anyone can read the claims; only the signature prevents tampering. If you need confidentiality, use JWE (JSON Web Encryption) or transport the token over HTTPS (which you should always do).

Costs and Performance Considerations

JWT validation has minimal computational cost. Verifying an HMAC signature is very fast; RSA/ECDSA verification is slightly slower but still negligible for most APIs (microseconds to milliseconds). The main cost is network I/O if you use introspection or fetch JWKS frequently. To mitigate, cache the JWKS keys and rotate them periodically. The real cost of JWT is not performance but complexity: you must handle key rotation, revocation, and algorithm management correctly.

Alternatives to JWT

JWTs are not the only option for API authentication. Alternatives include:

  • Opaque tokens: random strings stored server-side. They are simple and revocable, but require a database lookup on every request.
  • Session cookies: traditional server-side sessions. They are easy to revoke but not stateless.
  • API keys: simple but not suitable for user-level authorization.
  • Mutual TLS: client certificates for machine-to-machine communication. Strong but harder to manage.

Choose JWT when you need stateless, distributed systems and do not require immediate revocation. Choose opaque tokens or sessions when you need control over revocation and do not mind the extra lookup.

Frequently Asked Questions

Can an API trust the role claim in a JWT?

Yes, but only after verifying the signature and checking that the token is not expired. The role claim is part of the signed payload, so if the signature is valid, the role was set by the issuer and cannot be altered without invalidating the signature. However, you must also ensure that the issuer is the one you trust and that the audience matches your API.

What happens if a JWT expires while a user is using the app?

The API will reject the token on the next request. The client must obtain a new token, typically by using a refresh token or re-authenticating. Short-lived access tokens (e.g., 15 minutes) are common, and the refresh token is used to get a new access token without asking for credentials again.

Is it safe to decode a JWT without verifying the signature?

No. Decoding only reveals the claims; it does not prove they are authentic. An attacker can craft a token with any claims and base64-encode it. You must verify the signature before trusting any claim. Decoding is useful for debugging, but never for authorization decisions.

How do I revoke a JWT before it expires?

JWTs are stateless, so you cannot invalidate them directly. Options include maintaining a blocklist of revoked token IDs (jti claim), using short-lived tokens with a refresh token flow, or switching to an introspection endpoint that checks against a server-side store. The blocklist approach adds a lookup but allows immediate revocation.

What is the difference between HS256 and RS256?

HS256 uses a shared secret for both signing and verification, so the same secret must be kept on every server. RS256 uses a private key to sign and a public key to verify, so only the signer holds the private key. RS256 is generally safer for APIs because the public key can be distributed freely and keys can be rotated without sharing secrets.

Can I trust a JWT from any issuer?

No. Your API must be configured to trust specific issuers. Always check the iss claim against a whitelist of known issuers. If you accept tokens from any issuer, an attacker could create their own token and sign it with their own key, and your API would accept it.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →