JWE is the encrypted side of JWT that almost nobody talks about: five parts, two encryption layers, and a full zoo of attacks - Invalid Curve on ECDH-ES, Bleichenbacher on RSA1_5, Padding Oracle on AES-CBC, PBES2 DoS with one request, and the forbidden attack on AES-GCM.
The math behind HMAC, RSA, and ECDSA from an attacker's perspective: why Sony lost the PlayStation 3 to a single repeated number, and how leaking just a few nonce bits is enough to recover a private key.
A signature of all zeros passes ECDSA verification on Java 15-18. For any message, with any key. Five lines of Python - and you're admin.
JWT contains everything for an offline attack: message and signature. Hashcat on GPU runs through 150 million HS256 per second. The secret 'secret' is cracked in 2 seconds.
The JWT header can contain a URL, and the server will go to that URL to download the key for signature verification. This isn't a bug - it's RFC 7515.
The RFC doesn't define the structure of kid. Developers use it as a file path, SQL parameter, or command argument. Each option is a separate class of vulnerability.
Take the server's public key from open access, sign a token with it - and the server accepts it. The signature exists, the signature is correct, but the token is forged.
The RFC requires every JWT library to support the none algorithm. Change one field in the header - and the server skips signature verification.
Taking a real token and dissecting it like a pathologist: header, payload, signature, Base64url, claims, edge cases.
70+ CVEs over ten years. A bug from 2015 still fires in 2026. Let's figure out why JWT stubbornly remains broken.