Comprehensive JWT Security Guide

A practitioner’s reference for JSON Web Token security – vulnerabilities, exploitation techniques, attack vectors, implementation flaws, and defense strategies. Covers algorithm confusion, signature bypass, header injection, key confusion, library-specific issues, cryptographic attacks, attack chaining, and secure implementation patterns. Compiled from 42 research sources.


Table of Contents

  1. Fundamentals
  2. JWT Structure & Components
  3. Algorithm Confusion Attacks
  4. Signature Bypass Techniques
  5. Header Manipulation
  6. Payload Tampering
  7. Cryptographic & Protocol-Level Attacks
  8. Library-Specific Vulnerabilities
  9. Attack Chaining
  10. Implementation Security
  11. Attack Methodology
  12. Secure Development Practices

1. Fundamentals

JWT Overview

ComponentPurposeSecurity Relevance
HeaderAlgorithm and token type declarationAlgorithm confusion vector
PayloadClaims and dataAuthorization decisions
SignatureIntegrity and authenticity proofBypass target

Common Use Cases

ApplicationJWT RoleAttack Impact
AuthenticationIdentity assertionAccount takeover
AuthorizationPermission claimsPrivilege escalation
Information ExchangeSecure data transmissionInformation disclosure
API AccessBearer tokenUnauthorized access
MicroservicesStateless sessionCross-service token reuse

JWS vs JWE

FormatPurposeSecurity Consideration
JWS (JSON Web Signature)Signed tokens – integrity and authenticityMost common; payload is readable (base64url), not encrypted
JWE (JSON Web Encryption)Encrypted tokens – confidentialityPayload confidential; format confusion with JWS possible

2. JWT Structure & Components

Token Anatomy

JWT STRUCTURE:
Header.Payload.Signature

Example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header Parameters

ParameterDescriptionSecurity Implications
algSignature algorithmAlgorithm confusion attacks
typToken typeType confusion, JWS/JWE format confusion
kidKey identifierPath traversal, SQL injection, command injection
jkuJWK Set URLSSRF, URL manipulation, external key loading
jwkEmbedded JSON Web KeyKey injection – attacker embeds own public key
x5uX.509 URLCertificate injection, SSRF
x5cX.509 Certificate ChainCertificate substitution

Standard Claims

ClaimPurposeAttack Vectors
iss (Issuer)Token originIssuer spoofing, substitution attacks
sub (Subject)Token subjectUser ID manipulation
aud (Audience)Intended recipientAudience bypass, cross-service token reuse
exp (Expiration)Token lifetimeExpiry bypass, token persistence
iat (Issued At)Issue timestampReplay attacks
nbf (Not Before)Activation timeTiming bypass

3. Algorithm Confusion Attacks

Attack Mechanism

ALGORITHM CONFUSION FLOW:
1. Server expects RS256 (RSA + SHA256)
2. Attacker changes alg to HS256 (HMAC + SHA256)
3. Server's public RSA key used as HMAC secret
4. Attacker generates valid HMAC signature
5. Server verifies with same key -> bypass

Vulnerable Algorithm Transitions

Original AlgorithmConfused AlgorithmAttack Method
RS256/RS384/RS512HS256/HS384/HS512Public key as HMAC secret
ES256/ES384/ES512HS256/HS384/HS512Public key as HMAC secret
PS256/PS384/PS512HS256/HS384/HS512Public key as HMAC secret
Any AlgorithmnoneNo signature verification

Exploitation Techniques

Attack VectorPayload ExampleImpact
RSA->HMAC{"alg":"HS256"} + HMAC(payload, rsa_public_key)Complete authentication bypass
Algorithm None{"alg":"none"} + unsigned tokenTotal signature bypass
None Variants{"alg":"NoNe"}, {"alg":"NONE"}, {"alg":"nOnE"}Blacklist bypass on case-insensitive checks
Weak Algorithm{"alg":"HS256"} with known/weak secretSignature forgery

CVE-2024-54150: cjwt C Library

A real-world algorithm confusion in the xmidt-org/cjwt C library. The cjwt_decode() function reads the algorithm from the JWT header without requiring the caller to specify an expected algorithm. The verification function jws_verify_signature() dispatches based on the header-controlled alg value, allowing an attacker to sign with HMAC using the server’s RSA public key.

Key code review red flags:

  • Single decode function for both HMAC and RSA with identical call signatures
  • Algorithm determined by parsing untrusted JWT header (cJSON_GetObjectItemCaseSensitive)
  • No API parameter for caller to restrict accepted algorithms

4. Signature Bypass Techniques

Direct Signature Attacks

MethodTechniqueRequirements
Empty SignatureRemove signature sectionVulnerable parser
Signature StrippingModify to alg: "none"Missing algorithm validation
Brute ForceHMAC secret guessing via hashcatWeak secret key
Dictionary AttackCommon secret wordlistsPredictable secrets
decode() vs verify()Application uses decode-only functionDeveloper misunderstanding

Brute Forcing HMAC Secrets

HMAC BRUTE FORCE WITH HASHCAT:
hashcat -a 0 -m 16500 <JWT_TOKEN> /path/to/jwt.secrets.list

Mode 16500 = JWT signature cracking
Use --show to display previously cracked results
Wordlists: SecLists/Passwords/scraped-JWT-secrets.txt

Key insight (RFC 8725): Human-memorizable passwords MUST NOT be directly used as HMAC keys. Minimum 256 bits of entropy required for HS256.

Signature Validation Flaws

COMMON VALIDATION ERRORS:
├── Missing Algorithm Verification
│   ├── Accept any algorithm in header
│   ├── No algorithm allowlist
│   └── Default to insecure algorithms
├── Improper Key Handling
│   ├── Same key for multiple algorithms
│   ├── Public key reuse
│   └── Key confusion attacks
├── Logic Bypasses
│   ├── Empty signature acceptance
│   ├── Null signature handling
│   └── Exception swallowing
└── decode() vs verify()
    ├── Using jwt.decode() instead of jwt.verify()
    ├── Decoding without signature check
    └── Trusting decoded payload as authenticated

Audience Verification Bypass (Go jwt-go)

The dgrijalva/jwt-go library’s VerifyAudience function accepted empty string ("") as a valid audience value, allowing audience verification to succeed when it should fail. Fix was available in v4.0.0-preview1 but not merged to master, leaving most Go projects vulnerable.


5. Header Manipulation

Key Identifier (kid) Attacks

AttackPayloadEffect
Path Traversal"kid":"../../dev/null"Sign with empty/known file content
Path Traversal"kid":"../../../public.key"Use predictable file as key
URL Injection"kid":"http://attacker.com/key"External key loading
SQL Injection"kid":"' UNION SELECT 'known-secret'--"Return attacker-controlled key from DB
Command Injection"kid":";cat /etc/passwd"Code execution

Remediation pattern (kid path traversal):

// VULNERABLE: direct file path from kid
const keyPath = `/keys/${kid}`;
const key = fs.readFileSync(keyPath);

// SECURE: allowlist mapping
const allowedKeys = {
  'key-2024-01': '/secure/keys/2024-01.pem',
  'key-2024-02': '/secure/keys/2024-02.pem'
};
if (!allowedKeys.hasOwnProperty(kid)) throw new Error('Invalid key');
const key = fs.readFileSync(allowedKeys[kid]);

Remediation pattern (kid SQL injection):

// VULNERABLE: string concatenation
String query = "SELECT key FROM keys WHERE kid = '" + kidValue + "'";

// SECURE: parameterized query
PreparedStatement stmt = conn.prepareStatement("SELECT key FROM keys WHERE kid = ?");
stmt.setString(1, kidValue);

JWK Set URL (jku) Manipulation

JKU ATTACK CHAIN:
1. Attacker controls jku parameter
2. Points to malicious JWK Set (hosted on attacker server)
3. Server fetches attacker's keys without URL validation
4. Token validates with attacker's key
5. Complete authentication bypass

SSRF CLASSIFICATION: jku fetching = server-side request to attacker URL

Mitigations:

  • Disable jku parameter support entirely (recommended)
  • Strict URL allowlisting (full URL, not just domain)
  • Disable HTTP redirects when fetching JWKS
  • Validate URL before any fetch operation

JWK Header Injection (jwk Parameter)

JWK INJECTION ATTACK:
1. Attacker generates own RSA key pair
2. Modifies JWT payload (e.g., role: "admin")
3. Adds own public key in jwk header parameter
4. Sets kid to match the embedded jwk
5. Signs token with own private key
6. Server uses embedded public key to verify -> bypass

REQUIRES: Server accepts jwk parameter without key allowlisting

X.509 Certificate Attacks

VectorDescriptionMitigation
Certificate InjectionSupply malicious certificate via x5uStrict URL validation
Self-Signed CertsUse untrusted certificatesCertificate chain validation
Certificate ConfusionMix certificate typesExplicit algorithm binding
x5c Chain InjectionEmbed attacker cert chain in headerValidate against trusted root CAs

6. Payload Tampering

Claim Manipulation

ClaimAttack ExampleImpact
User ID (sub)Change to admin userHorizontal privilege escalation
Role (role)Elevate to administratorVertical privilege escalation
Expiration (exp)Extend lifetimePersistent access
Audience (aud)Change target applicationCross-application attacks (substitution)
UsernameChange "username":"johndoe" to "username":"admin"Identity spoofing

Business Logic Bypasses

PAYLOAD ATTACK PATTERNS:
├── Privilege Escalation
│   ├── Role claim modification (user -> admin)
│   ├── Permission array tampering
│   └── Group membership changes
├── Time-Based Attacks
│   ├── Expiry extension (exp)
│   ├── Not-before bypass (nbf)
│   └── Issued-at manipulation (iat)
├── Cross-Application Attacks (Substitution)
│   ├── Audience switching (aud)
│   ├── Issuer spoofing (iss)
│   ├── Token reuse across services
│   └── Cross-JWT confusion (RFC 8725 Section 2.8)
└── Indirect Server Attacks
    ├── Claims used in LDAP lookups (injection)
    ├── Claims used in database queries (SQLi)
    └── Claims containing URLs (SSRF)

7. Cryptographic & Protocol-Level Attacks

Elliptic Curve Invalid Curve Attacks

JOSE libraries that fail to validate elliptic curve inputs during ECDH-ES key agreement are vulnerable to invalid curve point attacks. An attacker sends JWEs with invalid curve points and observes cleartext outputs to recover the recipient’s private key.

AlgorithmAttackMitigation
ECDH-ESInvalid curve point injectionValidate points per NIST SP 800-56A Section 5.6.2.3.4
ES256Psychic Signatures (CVE-2022-21449)Java EC signature with zero values accepted as valid

JWE-Specific Attacks

AttackDescriptionMitigation
JWE Decompression BombCompressed JWE payload expands to exhaust memoryLimit decompression output size
Compression OracleCiphertext length leaks plaintext information when compression enabledAvoid compression before encryption (RFC 8725 Section 3.6)
JWS/JWE Format ConfusionVerifier doesn’t check if received JWT is JWS vs JWE; successful decryption treated as signature validation (CVE-2023-51774)Explicitly check JWT format type

Hash Iteration DoS

Libraries that support password-based encryption (PBES2) may accept unreasonable iteration counts, causing CPU exhaustion when processing a maliciously crafted token.

ParameterRiskMitigation
p2c (PBES2 count)Attacker sets extremely high iteration countLimit maximum hash iteration count

Bleichenbacher Attack on RSA-PKCS1

RSA-PKCS1 v1.5 encryption algorithms are vulnerable to Bleichenbacher’s chosen-ciphertext attack (padding oracle). Prefer RSAES-OAEP.


8. Library-Specific Vulnerabilities

Historical Vulnerabilities

LibraryCVEVulnerabilityImpact
node-jsonwebtokenCVE-2015-9235Algorithm confusionAuthentication bypass
node-jsonwebtokenCVE-2022-23529RCE via malicious secretOrPublicKey objectRemote code execution (retracted – requires caller misuse)
pyjwtCVE-2017-11424Key confusionSignature verification bypass
php-jwtCVE-2021-46743Algorithm substitutionAuthentication bypass
jose4jCVE-2023-51775Algorithm confusionToken forgery
xmidt-org/cjwt (C)CVE-2024-54150Algorithm confusion – no caller-specified algorithmAuthentication bypass via HMAC/RSA key confusion
dgrijalva/jwt-go (Go)SNYK-GOLANG-596515Audience verification bypass (empty string accepted)Access restriction bypass
Java SECVE-2022-21449“Psychic Signatures” – EC zero-value signature acceptedSignature validation bypass
nimbus-jose-jwtCVE-2023-51774JWS/JWE format confusionAuthentication bypass

Framework Integration Issues

FRAMEWORK VULNERABILITIES:
├── Express.js/Node.js
│   ├── jsonwebtoken algorithm confusion
│   ├── jwt.decode() vs jwt.verify() misuse
│   ├── Middleware bypass techniques
│   ├── CVE-2022-23529 (secretOrPublicKey object injection)
│   └── Error handling flaws
├── Django/Python
│   ├── PyJWT verification bypasses
│   ├── Algorithm None attacks
│   ├── Key handling issues
│   └── Flask-JWT-Extended misconfiguration
├── Spring Boot/Java
│   ├── JJWT library flaws
│   ├── Algorithm validation bypass
│   ├── CVE-2022-21449 (EC Psychic Signatures)
│   ├── Token sidejacking defenses (OWASP)
│   └── Key injection vulnerabilities
├── ASP.NET/C#
│   ├── System.IdentityModel flaws
│   ├── Algorithm confusion
│   └── Certificate validation bypass
└── Go
    ├── dgrijalva/jwt-go audience bypass
    ├── Master branch vs tagged release divergence
    └── VerifyAudience empty string acceptance

9. Attack Chaining

JWT Bypass to RCE

CTF EXAMPLE: JWT None Algorithm -> Admin Panel -> SSTI -> RCE

Chain:
1. Decode JWT, identify role claim ("user")
2. Set alg to "none", change role to "admin", strip signature
3. Access admin panel with forged token
4. Discover input field vulnerable to Jinja2 SSTI
5. Execute RCE via Python class hierarchy traversal:
   {​% for x in ().__class__.__base__.__subclasses__() %}
     {​% if "warning" in x.__name__ %}
       {​{x()._module.__builtins__["__import__"]("os").popen('whoami').read()}}
     {​% endif %}
   {​% endfor %}
6. Read flag from filesystem

Impact: JWT auth bypass -> privilege escalation -> code execution

Common JWT Attack Chains

Initial VulnerabilityEscalationFinal Impact
JWT none algorithmAdmin panel accessPrivilege escalation
JWT kid path traversalRead sensitive filesInformation disclosure / auth bypass
JWT kid SQL injectionExtract signing keys from DBFull token forgery
JWT jku injectionSSRF to internal servicesInternal network access
JWT weak secret + brute forceForge tokens for any userAccount takeover
JWT alg confusion + claim modificationAdmin role assignmentFull application compromise

10. Implementation Security

Secure JWT Verification

Security ControlImplementationCommon Mistakes
Algorithm ValidationStrict allowlist (whitelist, not blacklist)Accept any algorithm; blacklist none with case-sensitive check
Key ManagementRotate regularly, separate keys per algorithmReuse across algorithms
Signature VerificationMandatory for all tokens; use verify() not decode()Optional or bypassable; using decode-only functions
Claim ValidationValidate all critical claims server-sideTrust payload data
Format Type CheckExplicitly verify JWS vs JWE formatAccept any JWT structure

Token Sidejacking Defense (OWASP)

TOKEN FINGERPRINTING:
1. On authentication, generate random string (50 bytes, SecureRandom)
2. Send raw value as hardened cookie:
   __Secure-Fgp=<value>; SameSite=Strict; HttpOnly; Secure
3. Store SHA-256 hash of value in JWT claim (userFingerprint)
4. On each request:
   a. Read fingerprint cookie
   b. Hash it with SHA-256
   c. Compare to JWT claim
   d. Reject token if mismatch

BENEFIT: Even if JWT is stolen, attacker lacks the HttpOnly cookie
NOTE: Avoid IP-based fingerprinting (changes on mobile networks, GDPR concerns)

Token Revocation Strategies

StrategyMechanismTrade-off
Short-lived tokensSet exp to 15 minutes maxFrequent re-authentication
Token denylist (DB)SHA-256 digest stored in revocation tableReintroduces server state
Refresh token rotationIssue new access token via refresh endpointRefresh token must be secured
Cookie clearing on logoutClear JWT from sessionStorage + cookieOnly effective if user initiates logout

Key Management Best Practices

SECURE KEY PRACTICES:
├── Key Generation
│   ├── Cryptographically random (SecureRandom, os.urandom)
│   ├── Sufficient entropy (256+ bits for HMAC)
│   ├── Algorithm-specific requirements
│   └── Never use human-memorizable passwords as HMAC keys
├── Key Storage
│   ├── Hardware security modules (HSM)
│   ├── Cloud KMS (AWS KMS, Azure Key Vault, GCP KMS)
│   ├── Environment variables (development only)
│   └── Never hardcode in source code
├── Key Rotation
│   ├── Regular rotation schedule
│   ├── Grace periods for old keys (support both during transition)
│   └── Emergency rotation procedures
├── Key Distribution
│   ├── Secure channels only (HTTPS)
│   ├── JWK Set endpoints (/.well-known/jwks.json)
│   └── Certificate-based PKI
└── Key-Algorithm Binding
    ├── Each key used with exactly one algorithm
    ├── Separate keys for signing vs encryption
    └── Validated at cryptographic operation time

11. Attack Methodology

Reconnaissance Phase

TargetInformation GatheringTools
JWT StructureToken analysis, header/payload decodeJWT.io, jwt_tool, CyberChef
Algorithm DetectionHeader inspectionBurp Suite, manual analysis
Key DiscoveryPublic key extraction, JWKS endpointsCertificate analysis, /.well-known/jwks.json
Implementation DetailsError message analysis, library fingerprintingFuzzing, invalid tokens
Framework DetectionWappalyzer, BuiltWithTechnology stack identification

Exploitation Workflow

ATTACK SEQUENCE:
├── Token Acquisition
│   ├── Login with valid credentials
│   ├── Social engineering
│   └── Token leakage (logs, URLs, Referer headers)
├── Token Analysis
│   ├── Decode header and payload (base64url)
│   ├── Identify critical claims (role, sub, aud)
│   ├── Determine algorithm
│   └── Check for optional header params (kid, jku, jwk)
├── Vulnerability Testing
│   ├── Algorithm none (with case variants)
│   ├── Algorithm confusion (RS256 -> HS256)
│   ├── Signature removal / empty signature
│   ├── Weak secret brute force (hashcat -m 16500)
│   ├── kid injection (path traversal, SQLi)
│   ├── jku/jwk injection
│   ├── Claim manipulation (role, sub, exp)
│   └── decode() vs verify() check
├── Escalation
│   ├── Forge admin tokens
│   ├── Chain with other vulns (SSTI, SSRF, SQLi)
│   └── Cross-service token reuse
└── Impact Assessment
    ├── Authentication bypass
    ├── Privilege escalation
    ├── Data access
    └── Remote code execution (via chaining)

Testing Tools

ToolPurposeFeatures
jwt_toolJWT manipulation & testingAlgorithm attacks, claim fuzzing, automated scanning
Burp JWT EditorToken editing & signingReal-time editing, key generation, re-signing
JWT Scanner (Burp)Automated vulnerability scanningNone algorithm, CVE-2022-21449, key confusion, public key forging
JOSEPH (Burp)JOSE pentesting helperBleichenbacher MMA, key confusion, signature exclusion
hashcat (-m 16500)HMAC secret brute forceDictionary/brute force attacks on JWT signing keys
c-jwt-crackerHMAC brute force (C)Fast native cracking
JWT2JohnPassword cracking prepExtract JWT for John the Ripper
jwtXploiterJWT security testingMultiple attack vectors
jwt-pwnJWT security testing scriptsPython-based testing suite
SnykSAST for JWT misuseDetects jwt.decode() misuse, vulnerable library versions

12. Secure Development Practices

Implementation Checklist

Security ControlVerificationRisk Level
Algorithm AllowlistExplicitly define allowed algorithms (whitelist)Critical
Signature VerificationMandatory for all tokens; use verify()Critical
Key ManagementSecure generation, storage, rotation; 256+ bit entropyCritical
Key-Algorithm BindingEach key used with exactly one algorithmCritical
Claim ValidationValidate iss, aud, exp, nbf, subHigh
Format Type CheckVerify JWS vs JWE explicitlyHigh
Header Parameter RestrictionsReject/ignore jku, jwk, x5u unless explicitly neededHigh
kid ValidationAllowlist or parameterized lookups onlyHigh
Token LifetimeShort expiration (15 min access tokens)High
Token FingerprintingBind tokens to client context (hardened cookie)Medium
Error HandlingNo information leakage in error responsesMedium
Token RevocationImplement denylist for logout supportMedium
CompressionNever compress before encryptionMedium
HTTPS TransportTokens transmitted only over TLSMedium

RFC 8725 Best Practices Summary

RFC 8725 / draft-sheffer-oauth-rfc8725bis KEY REQUIREMENTS:
├── Algorithm Verification
│   ├── Libraries MUST let caller specify supported algorithms
│   ├── MUST NOT use algorithms not in the specified set
│   ├── Each key MUST be used with exactly one algorithm
│   └── MUST be checked at cryptographic operation time
├── Cryptographic Hygiene
│   ├── Validate all cryptographic operations (including nested JWTs)
│   ├── Validate elliptic curve inputs (invalid curve attacks)
│   ├── Keys MUST have sufficient entropy (256+ bits)
│   ├── Avoid compression before encryption
│   └── Use UTF-8 encoding exclusively
├── Claim Validation
│   ├── Validate issuer and subject
│   ├── Use and validate audience
│   ├── Do NOT trust received claims for server-side operations
│   └── Use explicit typing (typ header) to prevent cross-JWT confusion
├── Format Safety (RFC 8725bis additions)
│   ├── Limit hash iteration count (PBES2 p2c parameter)
│   ├── Check JWT format type (JWS vs JWE)
│   └── Limit JWE decompression size
└── General
    ├── Use RSAES-OAEP instead of RSA-PKCS1 v1.5
    ├── Implement ECDSA with deterministic nonces (RFC 6979)
    └── Use mutually exclusive validation rules for different JWT types

Framework-Specific Guidance

SECURE IMPLEMENTATION PATTERNS:
├── Node.js/Express
│   ├── Use jsonwebtoken with explicit algorithms option
│   ├── ALWAYS use jwt.verify(), NEVER jwt.decode() for auth
│   ├── Implement proper error handling (no stack traces)
│   ├── Validate all claims explicitly
│   └── Keep jsonwebtoken >= v9.0.0
├── Python/Django/Flask
│   ├── PyJWT with algorithms parameter (whitelist)
│   ├── Always verify signature before trusting claims
│   ├── Custom middleware for validation
│   ├── Secure key storage (environment variables / KMS)
│   └── Flask-JWT-Extended with secure cookie configuration
├── Java/Spring Boot
│   ├── Spring Security JWT support with algorithm validation
│   ├── Token sidejacking with fingerprint cookies (OWASP pattern)
│   ├── Token denylist for revocation
│   ├── JWK Set endpoints for key distribution
│   ├── Ensure JDK patched for CVE-2022-21449
│   └── Use auth0/java-jwt or nimbus-jose-jwt (latest)
├── .NET/ASP.NET Core
│   ├── Microsoft.IdentityModel.JsonWebTokens
│   ├── TokenValidationParameters (strict configuration)
│   └── Strict algorithm validation
└── Go
    ├── Use golang-jwt/jwt (not dgrijalva/jwt-go)
    ├── Validate audience explicitly
    └── Pin to tagged releases, not master branch

Security Testing Strategy

Test CategoryTest CasesExpected Result
Algorithm Testsnone (all case variants), HS256<->RS256, invalidReject all invalid algorithms
Signature TestsMissing, empty, invalid, decode-onlyReject all invalid signatures
Claim TestsExpired, wrong audience, wrong issuer, missingValidate all critical claims
Header Testskid injection (traversal, SQLi), jku/jwk manipulationReject malicious parameters
Key TestsWeak HMAC secret, brute force, public key confusionResist all key attacks
Format TestsJWE sent where JWS expected, nested JWTExplicit format validation
Chaining TestsJWT bypass + secondary exploitationDefense in depth at each layer

Key Takeaways

  1. Algorithm Validation: Always use explicit algorithm allowlists – never blacklists (case-variant bypass)
  2. Signature Verification: Use verify(), never decode() for authentication decisions
  3. Key Management: Use separate keys per algorithm, 256+ bits entropy, never human-memorable passwords
  4. Claim Validation: Validate all security-relevant claims (iss, aud, exp, nbf, sub)
  5. Header Restrictions: Reject or strictly validate jku, jwk, kid, x5u parameters
  6. Format Awareness: Explicitly check JWS vs JWE format to prevent confusion attacks
  7. Token Binding: Use fingerprint cookies to mitigate token sidejacking
  8. Library Updates: Keep JWT libraries current; review CVE history before adopting new libraries
  9. Defense in Depth: JWT bypass alone may not be critical; prevent secondary exploitation (SSTI, SQLi, SSRF)
  10. RFC 8725 Compliance: Follow IETF Best Current Practices as minimum security baseline

This guide compiles practical JWT security knowledge from 42 research sources. Stay updated with emerging JWT attack techniques, library vulnerabilities, and RFC 8725bis updates.