JSON Web Token (JWT) Security

JSON Web Tokens (JWTs) are a widely deployed mechanism for representing authenticated identity claims and authorization state across distributed systems, APIs, and web applications. This page covers the structural composition of JWTs, the vulnerability classes that arise from implementation flaws, the regulatory and standards context that governs their use, and the decision boundaries that determine when JWT-based authentication is appropriate. Security professionals, application architects, and auditors working in authentication and authorization security or API security will find this a structured reference for the JWT threat landscape.

Definition and scope

A JSON Web Token is a compact, URL-safe data format defined in RFC 7519 by the Internet Engineering Task Force (IETF). It encodes a set of claims — assertions about a subject, such as user identity, role, or session expiration — as a Base64URL-encoded JSON object. The specification is part of the broader JOSE (JSON Object Signing and Encryption) framework, which includes RFC 7515 (JSON Web Signature, JWS), RFC 7516 (JSON Web Encryption, JWE), and RFC 7517 (JSON Web Key, JWK).

JWTs are not a session management system in the traditional sense. They are stateless bearer tokens: the server does not maintain session state; instead, the token itself carries verifiable claims. This architectural property creates both scalability advantages and a distinct set of security risks, since a validly signed token is sufficient for access regardless of server-side context.

NIST Special Publication 800-63B (NIST SP 800-63B) addresses authenticator assurance levels and session binding, providing the federal baseline against which JWT implementations in regulated environments are evaluated. The Open Web Application Security Project (OWASP) identifies broken authentication — a category that encompasses JWT misuse — as a persistent risk in the OWASP Top Ten Vulnerabilities framework.

How it works

A JWT consists of three dot-separated segments: a header, a payload, and a signature (or, in encrypted tokens, a ciphertext and authentication tag).

  1. Header — A JSON object specifying the token type (typ: JWT) and the algorithm used to sign or encrypt it (alg). Common signing algorithms include HS256 (HMAC-SHA256, symmetric), RS256 (RSA with SHA-256, asymmetric), and ES256 (ECDSA with P-256 and SHA-256, asymmetric).
  2. Payload — A JSON object containing registered claim names (defined in RFC 7519) such as iss (issuer), sub (subject), aud (audience), exp (expiration time), and iat (issued at), alongside application-defined private claims.
  3. Signature — Computed over the Base64URL-encoded header and payload using the algorithm declared in the header and a secret or private key. In JWE tokens, the payload is encrypted rather than merely signed, providing confidentiality in addition to integrity.

Validation sequence required by RFC 7519:

  1. Verify the token is well-formed (three segments, valid Base64URL encoding).
  2. Verify the alg header matches the expected algorithm on the server side — never accept the client-declared algorithm without server-side enforcement.
  3. Verify the signature using the correct key.
  4. Validate registered claims: exp has not elapsed, nbf (not before) has been reached, iss matches the expected issuer, aud matches the intended recipient.
  5. Enforce application-specific claims (roles, scopes, tenant identifiers).

Failure at any validation step must result in token rejection. The cryptography in application security discipline governs key length requirements: RS256 keys below 2048 bits are considered insufficient under current NIST guidance.

Common scenarios

The alg: none attack — RFC 7519 defines none as a valid algorithm value indicating an unsecured JWT. Libraries that honor a client-supplied alg: none header will skip signature verification entirely, allowing an attacker to forge arbitrary claims. The OWASP JWT Security Cheat Sheet explicitly flags this as a critical implementation failure. Mitigation requires server-side algorithm whitelisting, rejecting any token declaring alg: none.

Algorithm confusion (RS256 to HS256 downgrade) — When a server accepts both asymmetric (RS256) and symmetric (HS256) algorithms, an attacker may submit a token with alg: HS256 signed with the server's public RSA key. If the library uses the public key as the HMAC secret for HS256 verification, the forged token passes validation. This attack class was documented in security research published by Tim McLean in 2015 and remains relevant wherever multi-algorithm support is implemented without strict algorithm binding.

Weak secret keys in HS256 — Symmetric JWTs signed with short or guessable secrets are vulnerable to offline brute-force attacks. A secret of fewer than 256 bits provides insufficient security margin for HMAC-SHA256 (NIST SP 800-107).

Unvalidated claims — Tokens lacking exp validation enable session persistence beyond the intended window. Tokens with an unvalidated aud claim may be accepted by unintended services (audience confusion). Both represent broken access control, a category detailed in broken access control risks.

JWK Set (JWKS) injection — Some libraries allow a token to supply its own signing key via an embedded jwk header parameter. If the library trusts the embedded key without verifying it against a server-controlled JWKS endpoint, an attacker can generate a self-signed token with an arbitrary key pair. Server implementations must validate signing keys exclusively against a pre-configured, server-controlled JWKS endpoint.

JWT vulnerabilities intersect with secrets management for applications when signing keys are stored in source code, environment variables without protection, or version control repositories.

Decision boundaries

The choice between JWT-based stateless tokens and server-side session tokens involves explicit trade-offs:

Dimension JWT (Stateless) Server-Side Session
Revocation Requires token blocklist or short expiration Immediate, server-controlled
Scalability No server state required Session store required
Confidentiality Claims visible unless JWE used Claims remain server-side
Attack surface Signature validation complexity Session fixation, hijacking

JWTs are appropriate when horizontal scaling eliminates shared session state feasibility, when token lifetime is short (15 minutes or less is a common operational ceiling), and when revocation latency is acceptable within the application's risk model.

JWTs are inappropriate when immediate revocation of individual tokens is required (e.g., privilege escalation responses, account compromise scenarios), when sensitive personal data must not be transmitted client-side, or when the development team cannot enforce strict algorithm binding and claim validation through code review and secure code review processes.

Regulated environments — particularly those subject to PCI DSS (PCI DSS v4.0, Requirement 8) or HIPAA Security Rule provisions under 45 CFR §164.312(a) — require authentication mechanisms to support audit logging and session termination capabilities that stateless JWTs do not natively provide without supplemental infrastructure.

For OAuth and OpenID Connect implementations, JWTs serve as the standard format for ID tokens under OpenID Connect Core 1.0, and as one supported format for access tokens under RFC 9068. In these contexts, the Authorization Server's JWKS endpoint is the authoritative key source; relying parties must not accept tokens with algorithm values outside a server-configured allowlist.

References

Explore This Site