Join our Newsletter — 33% off our NHI Course
Home› Guides› JWT Security Guide: Signing, Validation and Token Attacks
Guide Authentication

JWT Security Guide: Signing, Validation and Token Attacks

Free PDF · we’ll email you a download link

← All guides
By Lalit Choda, NHI Mgmt Group Updated 23 October 2026 17 min read
On this page

A JSON Web Token is only as trustworthy as the code that validates it, and most JWT failures come from verifiers that let the token decide how it should be checked. JWTs carry access decisions for APIs, single sign-on, service-to-service calls and workload federation, so one missing check (algorithm, key source, audience, type or expiry) turns a signed token into a forgery path. This guide covers the JOSE structure, algorithm pinning, key handling for kid, jku and x5u, JWKS rotation, claim validation, the RFC 9068 access-token profile, RFC 8725 best practices, storage, revocation and the JWTs that non-human identities use. It is written for application security engineers, API and platform teams and identity architects who build or review JWT issuers and verifiers.

Key takeaways

  • Configure, never negotiate: the verifier fixes the accepted algorithm, issuer, audience, type and key set in advance; nothing in the token header can widen that.
  • Reject on any failed check: RFC 8725 requires the whole JWT to be rejected if any cryptographic operation fails, and ASVS 5.0 requires signature, validity time, type and audience checks before contents are used.
  • Treat header key pointers as attacker input: kid, jku, x5u and jwk may only select from keys already trusted for that issuer.
  • Use explicit typing and separate keys per token class: typ values such as at+jwt and distinct audiences stop an ID token or client assertion being replayed as an access token.
  • Plan revocation before you need it: a JWT stays valid until exp, so short lifetimes, sender-constrained tokens and a rehearsed signing-key rotation are the real kill switches.

How a JWT is built

A JWT (RFC 7519) is a set of claims inside a JOSE structure: a JSON Web Signature (JWS, RFC 7515) when signed or MACed, or a JSON Web Encryption object (JWE, RFC 7516) when encrypted. The compact JWS form is three base64url parts: protected header, payload and signature. A signed payload is encoded, not encrypted, so anyone holding the token can read it.

  • Header parameters: alg (algorithm), typ (media type), cty (JWT for a nested token), kid (key ID hint) and the key-source parameters jku, x5u, jwk and x5c. RFC 7515 requires header parameters used in a trust decision to be integrity protected, and a recipient must reject a token whose crit list names an extension it does not understand.
  • Unsecured JWTs: RFC 7519 defines tokens with alg set to none and requires conforming libraries to implement HS256 and none. Implementing is not accepting: RFC 7518 says unsecured objects must not be accepted by default.
  • Related formats: SD-JWT and verifiable credentials build selective disclosure on JWS. See the Verifiable Credentials Guide.
Registered claimMeaningVerifier rule
issIssuerExact match to the configured issuer; keys must belong to that issuer (RFC 8725 s3.8)
subSubject (user, client or workload)Meaningful only within the issuer's namespace
audIntended recipientsReject if the verifier is not listed; required when one issuer serves several relying parties (RFC 8725 s3.9)
exp / nbfExpiry and not-before timesReject outside the window, allowing only small clock skew
iatIssued atOptional sanity check on implausible values
jtiUnique token IDReplay detection and deny-list key

Choosing and pinning the signing algorithm

RFC 8725 requires libraries to use only the algorithm the application expects and to allow only current algorithms. ASVS 5.0 V9.1.2 asks for a per-context allowlist without none, ideally either symmetric or asymmetric but not both; where both are needed, extra controls must prevent key confusion.

FamilyExamplesKey requirementChoose whenTrade-off
HMACHS256, HS384, HS512At least the hash size (256 bits for HS256, RFC 7518), random, never a password (RFC 8725 s3.5)Issuer and verifier are the same service or trust domainEvery verifier can mint tokens; weak secrets can be brute forced offline
RSARS256, PS2562048 bits or largerMany independent verifiersLarger keys and tokens
Elliptic curveES256, EdDSA (RFC 8037)Curve fixed by the algorithmNew deployments wanting small, fast signaturesConfirm every verifier library supports it
NonenoneNo keyNever for authentication or authorisation; RFC 9068 forbids it for access tokensAnyone can forge tokens
  • Pin per issuer: store the expected algorithm with the issuer's key configuration and pass it explicitly to the verify call, as the OWASP Java JWT Cheat Sheet advises, rather than reading it from the token.
  • Bind algorithm to key type: a public key must never be usable as an HMAC secret. RFC 7515 s10.7 recommends restricting algorithms and matching them to application data to prevent substitution.
  • Asymmetric for distributed verification: when verifiers are separate from the issuer, public-key signatures mean a compromised API cannot mint tokens.

Key management: kid, jku, x5u and JWKS rotation

RFC 7517 defines a JWK Set as a keys array, usually published at a JWKS URI in OAuth or OpenID Connect metadata. The kid is only a case-sensitive hint. ASVS V9.1.3 requires verification keys to come from trusted, pre-configured sources for the issuer, with jku, x5u and jwk validated against an allowlist.

  • kid: use it only to choose among keys already loaded for the configured issuer. Never pass it to a file path, SQL query or command; RFC 8725 s2.9 warns that values used for lookups become injection and SSRF vectors.
  • jku and x5u: most verifiers should ignore them and use configured metadata. If used, require an exact allowlisted URL fetched over TLS with server identity validation (RFC 7515).
  • jwk and x5c: an embedded key proves nothing unless it chains to a trust anchor configured for that issuer (OWASP JWT Cheat Sheet).
  • One issuer, one key set: never verify against a union of keys from several issuers, and use separate keys or strict audience restriction per token class and audience (ASVS V9.2.4).
  • Custody: keep signing keys in an HSM or KMS that signs in place, with an inventory, owner and retirement date for each. See the Cryptographic Key Management Guide.

JWKS rotation without outages

  1. Publish the new public key in the JWKS with a new kid while still signing with the old key.
  2. After the longest verifier cache period, switch signing to the new key.
  3. Remove the old public key once the longest token lifetime has passed.
  4. On an unknown kid from a trusted issuer, verifiers refresh the JWKS once, rate limited, then reject.
  5. For a suspected compromise, skip the overlap: remove the key at once and accept forced re-authentication.

Validating a JWT: the required checks

RFC 7519 s7.2 says failure at any validation step means rejection, and RFC 8725 s3.12 requires validation rules for different kinds of JWT to be mutually exclusive. Implement this validation checklist once, in a shared library or gateway.

#CheckReject whenSource
1StructureMalformed encoding or JSON, or unsupported crit entriesRFC 7519 s7.2, RFC 7515
2Typetyp does not match the expected class (for example not at+jwt)RFC 8725 s3.11, ASVS V9.2.2
3Algorithmalg is not the pinned value for this issuer and key, or is noneRFC 8725 s3.1, ASVS V9.1.2
4Key sourceKey not in the issuer's configured set; jku, x5u or jwk not allowlistedASVS V9.1.3
5Signature or MACVerification fails; no payload content is used before this passesASVS V9.1.1, V6.8.2
6Issueriss differs from the issuer that owns the keyRFC 8725 s3.8
7Audienceaud missing where required or not matching this service's allowlisted identifierASVS V9.2.3
8TimeOutside nbf to exp beyond a skew of a minute or twoRFC 7519, ASVS V9.2.1
9Replay and revocationjti already used (for one-time tokens) or on the deny listRFC 7519 s4.1.7
10Claim useClaim values fail input validation before reaching queries, paths or URLsRFC 8725 s3.10

To identify a user from an access token, ASVS V10.3.3 requires claims that cannot be reassigned, such as iss plus sub, not an email address.

JWT access tokens: the RFC 9068 profile

RFC 9068 (October 2021) standardises JWT access tokens so resource servers validate them consistently; its rules are a sound default for in-house APIs too. For flows and ID tokens, see the OAuth 2.0 and OpenID Connect Guide.

  • Header: typ is at+jwt and resource servers reject other values; none is forbidden and must be rejected.
  • Required claims: iss, exp, aud, sub, client_id, iat and jti, plus scope when scopes were requested.
  • Validation: check typ, decrypt if encrypted, match iss exactly, confirm aud contains the resource server, verify the signature with the authorisation server's keys, check exp, and return invalid_token on failure.
  • Privacy: signed claims are readable by clients and anyone who captures the token, so clients must treat access tokens as opaque and personal data should stay out unless the token is encrypted.
  • ID tokens are not access tokens: ASVS V9.2.2 accepts only access tokens for authorisation decisions.

Token attacks and the controls that stop them

This attack-class to control table draws on RFC 8725, the OWASP JWT Cheat Sheet and the OWASP API Security Top 10 2023, whose Broken Authentication entry lists accepting unsigned or weakly signed JWTs and skipping expiry checks. ATT&CK has no JWT-specific technique: forging falls under T1606 Forge Web Credentials, theft under T1528 Steal Application Access Token and replay under T1550.001 Application Access Token.

Attack classWhat goes wrongControl
Unsecured token acceptedVerifier honours alg nonePinned allowlist without none
Algorithm or key-type confusionA public key is used as an HMAC secret because the header chose the routineAlgorithm bound to key type and issuer; no mixing MAC and public-key algorithms
Header key injectionVerifier trusts a key supplied or pointed to by jwk, jku, x5u or kidKeys only from configured metadata; kid as lookup key only
Weak HMAC secretCaptured token is brute forced offline256-bit random secret in a vault, or asymmetric signing
Cross-JWT confusion and substitutionAn ID token or a token for another API is acceptedExplicit typ, strict aud, separate keys per class
Expired or replayed tokenNo exp check, long lifetimes, bearer reuseShort lifetimes, jti tracking, DPoP or mTLS binding
Claim injectionHeader or claim values reach SQL, LDAP, paths or outbound URLsTreat token content as untrusted input
Signing key compromiseAttacker mints valid tokensHSM or KMS custody, rotation, issuance logging
JWE weaknessesRSA1_5 oracle (RFC 7516 s11.4), unchecked inner signature, invalid ECDH-ES points, compression leaks (RFC 8725 s2.3 to s2.5, s3.6)Sign then encrypt and validate both layers; one key per algorithm; single error for all decryption failures; no compression

Lifetime, revocation and replay

A self-contained JWT stays valid until it expires. NIST IR 8587 (September 2026) recommends that access and identity tokens be valid for no more than one hour, and shorter for higher-risk resources. Most deployments combine at least two of these patterns.

PatternHow it worksCost
Short lifetime plus refreshAccess tokens of minutes; refresh tokens rotated with an absolute expiry (ASVS V10.4.8)More token traffic
Deny listRevoked iss plus jti held until exp and checked per requestShared state; loses some stateless benefit
Reference tokensOpaque token checked by introspection (RFC 7662)Call or cache per request; immediate revocation
Sender-constrained tokensBound to a client key with DPoP (RFC 9449) or mTLS (RFC 8705)Client and server changes; stolen tokens fail (ASVS V10.3.5)
Signing-key removalEvery token signed by the key failsMass re-authentication; last-resort kill switch

Key the deny list on iss and jti, not the raw token or its hash: the OWASP JWT Cheat Sheet warns that token encodings are malleable. Continuous access evaluation and session revocation are covered in the Token and Session Security Guide.

Storage and transport

  • Transport: send JWTs over TLS in the Authorization: Bearer header (RFC 6750), never in URLs, where they reach logs, history and referrer headers.
  • Browser storage: ASVS V10.1.1 prefers a backend-for-frontend so tokens never reach browser JavaScript. The OWASP Java JWT Cheat Sheet instead uses sessionStorage with a strict Content Security Policy. A BFF removes the XSS exposure; sessionStorage limits persistence, not script access.
  • Sidejacking defence: OWASP's fingerprint pattern puts a random value in a hardened HttpOnly cookie and only its SHA-256 hash in the token. Do not bind to IP addresses, which change legitimately.
  • Telemetry: strip Authorization headers from application, proxy and APM logs.

JWTs for workloads and non-human identities

  • Client assertions (RFC 7523): a client authenticates to the token endpoint with a signed JWT (client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer, called private_key_jwt in OpenID Connect). iss and sub must be the client_id, aud must identify the authorisation server and exp is required. RFC 7523 does not mandate replay protection, so keep expiry short and track jti. The private key never leaves the client, unlike a shared client secret.
  • Workload identity federation: CI platforms and Kubernetes issue short-lived OIDC JWTs that clouds exchange for access. The trust policy is JWT validation: pin the issuer, require the exact audience and match sub precisely (repository, branch, namespace, service account) instead of broad wildcards. See the Workload Identity Federation Guide.
  • Service-to-service calls: give each downstream API its own audience rather than forwarding the caller's token everywhere. See the OAuth Token Exchange and Delegation Guide.
  • Signing secrets are NHI credentials: HMAC secrets and private keys need an owner, vault storage, rotation and offboarding. See the NHI Authentication Guide.

How to implement

  1. Inventory: list every issuer, key, algorithm, verifier and token class. Flag HMAC secrets shared across services and keys outside a KMS.
  2. Centralise validation: one maintained library or gateway policy, configured per issuer with algorithm, key source, audience, type and skew.
  3. Audit mode: run the stricter rules in log-only mode for two to four weeks and fix issuers that omit aud, typ or jti.
  4. Pilot ring: enforce on internal APIs, then external ones, watching rejection rates by reason.
  5. Enforce and shorten: reject everywhere, then cut lifetimes and add refresh rotation and deny-list checks.
  6. Rehearse rotation: run a planned JWKS rotation and an emergency key removal, timing how long verifiers take to converge.
  7. Roll back safely: keep enforcement behind a per-service flag and the previous public key in the JWKS during rollout.

Small organisations should consume their identity provider's tokens through a framework or gateway validator rather than issuing their own JWTs. Large estates benefit from a platform-owned validation library, audiences managed as policy as code and sender-constrained tokens for high-value APIs.

Detection and measurement

  • Rejections by reason: bad signature, disallowed alg, unknown kid, wrong aud or typ, expired. A spike in one reason means probing or a broken issuer.
  • Issuance records: log jti, sub, client_id and key ID at issue, so valid-looking tokens no issuer created stand out as a sign of key compromise.
  • Key use: alert on KMS signing calls from unexpected principals and on JWKS changes outside change windows.

Metrics: percentage of verifiers on the central library with pinned settings; maximum access-token lifetime per issuer (target one hour or less); percentage of signing keys in an HSM or KMS with an owner; time for all verifiers to drop a removed key in the last drill; number of HMAC secrets shared by more than one service (target zero); tokens presented with no issuance record (target zero).

Common failure patterns

  • Trusting the header: reading alg, jku or jwk from the token to decide how to verify it.
  • Signature-only validation: no aud or typ check, so a token for one API, or an ID token, opens another.
  • Passwords as HMAC secrets: short secrets copied into every service, where one leak lets anyone mint tokens.
  • Keys that never retire: long-lived signing keys on developer machines, not rotated at offboarding. The Coupang breach involved an authentication token signing key that was not revoked after an engineer left.
  • Day-long tokens without revocation: logout and account disablement change nothing until exp.

Lessons from incidents

  • Issuer scope is part of validation: Microsoft's July 2023 analysis said Storm-0558 used an acquired Microsoft account (MSA) consumer signing key to forge tokens, and a validation issue allowed that key to be trusted for Azure AD tokens. Microsoft revoked all MSA signing keys valid at the time and issued new ones in more isolated systems. This is RFC 8725 s3.8 and ASVS V9.2.4 in practice. See the Microsoft Storm-0558 key breach.
  • Spoofed JWTs as an authentication bypass: CISA's Known Exploited Vulnerabilities catalog lists CVE-2023-29357 in Microsoft SharePoint Server, where an unauthenticated attacker with spoofed JWT authentication tokens could gain administrator privileges; CISA records known ransomware use. Patch verifier software as urgently as issuers.

Framework mapping

Control areaOWASP ASVS 5.0NIST SP 800-53 Rev. 5Other
Signature and algorithm allowlistV9.1.1, V9.1.2, V6.8.2SC-13, SC-23CSF 2.0 PR.AA-03; ISO/IEC 27001:2022 A.8.24
Trusted key sources and custodyV9.1.3SC-12ATT&CK T1606 (threat)
Time, type and audience claimsV9.2.1 to V9.2.4, V10.3.3IA-5, SC-23ISO/IEC 27001:2022 A.8.5
Lifetime and revocationV7.4.1, V10.4.8AC-12D3FEND D3-TBA Token-based Authentication
Stolen-token resistanceV10.3.5, V10.1.1SC-23D3FEND D3-TB Token Binding; ATT&CK T1528, T1550.001 (threats)
Validation and issuance loggingn/aAU-2CSF 2.0 DE.CM-03

RFC 8725 (BCP 225, February 2020) is the current best practice. Its successor, draft-ietf-oauth-rfc8725bis, was approved and in the RFC Editor queue in October 2026 but remains an Internet-Draft until published. Its changes include case-insensitive alg handling checks, PBES2 iteration and decompression limits, deprecating RSA-PKCS1 v1.5 encryption and treating kid, jku and x5u as attacker-controllable.

Practitioner checklist

  • Pin algorithm, issuer, key set, audience and typ per token class in one shared validator.
  • Disable none and reject any alg that does not match the pinned value for its key.
  • Ignore jku, x5u and jwk unless allowlisted; use kid only to select a pre-loaded key.
  • Prefer asymmetric signing; where HMAC remains, use 256-bit random secrets from a vault, one per trust domain.
  • Keep signing keys in an HSM or KMS with owners, rotation dates and a rehearsed emergency removal.
  • Adopt RFC 9068 for access tokens and never accept ID tokens for authorisation.
  • Keep access tokens to an hour or less, rotate refresh tokens with absolute expiry and keep an iss plus jti deny list.
  • Bind high-value tokens to the client with DPoP or mTLS.
  • Validate client assertions and federation tokens with exact aud and sub matching.
  • Log rejections by reason and issuance by jti, and alert on tokens with no issuance record.

Standards and references

Related NHI Mgmt Group resources: Token and Session Security Guide · OAuth 2.0 and OpenID Connect Guide · Verifiable Credentials Guide · Workload Identity Federation Guide · API Security Guide

Free PDF

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. We’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Written and reviewed by Lalit Choda, NHI Mgmt Group. Last updated 23 October 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org

Free PDF by email

Get the guide

Enter your details and we’ll email you a download link.

Fill in all fields marked * and tick the PDF box to continue.