Stackbook Logo
security-complianceestablished · low operational burden

JWT Validation at the Resource Server

Also known as: bearer-token-validation, jwks-verification

Intent

Verify signed tokens locally and consistently so APIs can trust claims without calling the issuer on every request.

Problem

APIs receive bearer tokens from untrusted networks. Accepting a token without checking signature, algorithm, issuer, audience and expiry lets attackers forge or replay identities. Calling the identity provider per request adds latency and a hard dependency.

Forces

  • •Every request must be authenticated cheaply
  • •Signing keys rotate over time
  • •Tokens cannot be recalled before expiry
  • •Libraries allow dangerous defaults such as the none algorithm

Solution

Overview

A JSON Web Token carries signed claims. The resource server must treat the token as untrusted input until every check passes. Validation belongs in one shared library or gateway filter, not in each handler.

A good rollout has one internal library or gateway plugin used by every service, with conformance tests that feed it forged, expired, wrong-audience and unsigned tokens. Metrics on rejection reasons quickly reveal clock skew problems, rotation incidents and probing attacks, so expose them on dashboards.

How it works

token = header.payload.signature
1. parse header; alg must be in allow-list; reject none
2. key = jwksCache.get(header.kid)   # refetch once if missing
3. verify signature(key, header.payload)
4. require iss == expectedIssuer
5. require aud contains thisApi
6. require now < exp (+ small clock skew) and now >= nbf
7. authorize: scope / role claims vs route policy

Successful validation yields a principal object passed to business code; raw tokens are not re-parsed downstream.

Pitfalls

  • Trusting the alg header instead of a configured allow-list.
  • Using decode functions that skip verification.
  • Ignoring aud, so a token for service A works on service B.
  • Unlimited JWKS refetching on unknown kid, which lets attackers trigger a flood of outbound calls.
  • Putting PII or secrets in the payload; it is only encoded, not encrypted.
  • Long expiry with no revocation path.

Key takeaways

  • Pin algorithms, issuer and audience; never trust the token header.
  • Cache JWKS, handle rotation, and rate-limit refetches.
  • Keep lifetimes in minutes and add introspection for sensitive actions.
  • Centralize validation so fixes apply everywhere.

✓ When to Use

  • •Stateless APIs behind an OAuth/OIDC issuer
  • •Microservices needing local identity checks
  • •Gateways that forward verified claims downstream

✗ When Not to Use

  • •Opaque session cookies already work well
  • •Instant revocation is mandatory for every call
  • •Tokens carry large or sensitive payloads

Pros

  • +No per-request call to the issuer
  • +Horizontally scalable and stateless
  • +Key rotation handled via JWKS

Cons

  • −Revocation is hard before expiry
  • −Claims can go stale
  • −Subtle validation bugs are catastrophic

Cost Profile

Infrastructure

Low — JWKS cache

Operational

Low — monitor key rotation

Cognitive

Medium — many claims to check correctly

Failure Modes

  • Algorithm confusion accepts forged HS256 tokens signed with the public key

  • Missing audience check accepts tokens meant for other APIs

  • JWKS fetch outage rejects all traffic after cache expiry

Real-World Examples

Alternatives

    Related Patterns

      Competency Domains

      security compliancedistribution communication