API Security & JWT with PQC
JWT/JWS/JWE with post-quantum algorithms — ML-DSA signing, ML-KEM key agreement, and OAuth 2.0 migration.
Why this matters: Every OAuth token and API call your systems sign today could be forged retroactively once ML-DSA-breaking hardware exists — JWT/JWS is one of the most exposed, highest-volume surfaces in any stack.
Start here: Paste a JWT or pick a sample token in the JWT Inspector: the header, payload and signature are decoded, and the declared algorithm is classed as classical or post-quantum (a claim the token makes, not proof) with its key and signature sizes.
For your role
- Developer / Engineer
- Decode a JWT in the inspector, sign and verify with ML-DSA, build a dual classical-plus-PQC token, encrypt with ML-KEM and compare sizes across algorithms: the workshop is the token pipeline you ship, step by step.
- Security Architect
- The dual-signature step and the size comparison decide whether a PQC token still fits your headers and gateways; the last step audits the JOSE row of the protocol matrix and proposes a patch.
- Researcher / Academic
- The size comparison across ML-DSA and SLH-DSA sets and the JOSE matrix audit are the measurements; the workshop runs real PQC signing with in-browser KAT vectors.
JWT/JWS/JWE Fundamentals
are the foundation of modern API authentication. A JWT is a compact, URL-safe means of representing claims between two parties. The token format is defined in RFC 7519, with signing (, RFC 7515) and encryption (, RFC 7516) as separate specifications.
The header specifies the algorithm (alg) and token type (typ). The payload carries claims. The signature covers both header and payload.
header with alg (signing algorithm) and typ (token type). Base64url-encoded JSON.
Claims: sub, iss, exp, aud, plus custom claims. Base64url-encoded JSON.
Cryptographic signature over header.payload using the algorithm specified in the header. This is the part PQC replaces — the claims and the encoding stay the same.
Current JWT Algorithms & Quantum Vulnerability
The widely deployed asymmetric JWT signature algorithms — (RSA-PKCS1-v1_5), (ECDSA P-256), and (Ed25519) — rely on mathematical problems that would solve efficiently on a cryptographically relevant quantum computer (CRQC). None is broken today; they are vulnerable to a machine that does not yet exist. Key agreement with ECDH-ES is exposed in the same way. HMAC-based JWTs (HS256) are different: they use a shared secret, and Grover's algorithm only reduces their effective strength, so a 256-bit key remains adequate.
| Algorithm | JOSE ID | Type | Quantum Attack | Status |
|---|---|---|---|---|
| RS256 (RSA-2048) | RS256 | Signing | Shor's algorithm | Vulnerable to a CRQC |
| ES256 (ECDSA P-256) | ES256 | Signing | Shor's algorithm | Vulnerable to a CRQC |
| EdDSA (Ed25519) | EdDSA | Signing | Shor's algorithm | Vulnerable to a CRQC |
| ECDH-ES (P-256) | ECDH-ES | Key Agreement | Shor's algorithm | Vulnerable to a CRQC |
| ML-DSA-65 | ML-DSA-65 | Signing | None known | Post-quantum |
| ML-KEM-768 | ML-KEM-768 | Key Agreement | None known | Post-quantum |
A signed JWT is not encrypted — anyone holding it can already read its claims, so there is nothing to "decrypt later". The quantum risk is forgery: a CRQC could recover a signing key from its public key and mint new tokens that any verifier still trusting that key accepts. What matters is how long verifiers trust a key (JWKS rotation, pinned keys, signatures kept as long-term evidence), not how long one token lives.
Anything protected by ECDH today — a JWE using ECDH-ES, or the TLS connection that carries a bearer token — can be recorded now and decrypted once a CRQC exists. That is the HNDL threat, and it is why confidentiality migrates first.
PQC JWT Signing with ML-DSA
RFC 9964 (published May 2026 by the COSE working group) registers JOSE/COSE alg values for -44/65/87 (), along with a new kty="AKP" (Algorithm Key Pair) key type that carries a 32-byte FIPS 204 seed as the private key. ML-DSA replaces ECDSA and RSA for JWT signing. The rest of the JOSE PQC stack is still in draft: SLH-DSA (draft-ietf-cose-sphincs-plus-10, two parameter sets), PQ/T composite signatures (draft-ietf-jose-pq-composite-sigs-04), and ML-KEM encryption for JWE, which now goes through HPKE (draft-ietf-jose-hpke-encrypt, in the RFC Editor queue, plus the PQ suites in draft-ietf-jose-hpke-pq-pqt), which the workshop's JWE tab implements. An earlier direct-KEM draft for JWE was narrowed to COSE in its revision -06.
Level 2
Public key: 1,312 bytes
Signature: 2,420 bytes
Category 2: at least as hard as a SHA-256 collision search
NIST Level 3
Public key: 1,952 bytes
Signature: 3,309 bytes
Category 3 (≈ AES-192); this module's default example, not a NIST recommendation
NIST Level 5
Public key: 2,592 bytes
Signature: 4,627 bytes
Category 5 (≈ AES-256); the level CNSA 2.0 requires
PQC JWT Key Agreement with ML-KEM
(JSON Web Encryption) protects token payloads with authenticated encryption. () replaces ECDH-ES for key agreement in JWE, using a instead of Diffie-Hellman key exchange. The standards route is HPKE: ML-KEM (alone or combined with X25519) supplies the KEM, and the HPKE suite fixes the key derivation and AEAD.
In HPKE Integrated Encryption (draft-ietf-jose-hpke-encrypt) the JWE header carries only "alg", such as HPKE-12 (ML-KEM-768) or HPKE-9 (ML-KEM-768 + X25519, the X-Wing hybrid) from draft-ietf-jose-hpke-pq-pqt. There is no "enc", because HPKE itself encrypts the payload. The JWE Encrypted Key holds the 1,088-byte (or 1,120-byte) encapsulated secret, and the IV and Authentication Tag segments are empty. A recipient must still check that "alg" is one it expects for that key before decrypting.
ECDH falls to Shor's algorithm on a CRQC (discrete log on elliptic curves).
ML-KEM is a lattice-based KEM with no known quantum attack at its standardized parameters.
JOSE Header Changes
The token format survives the migration: the header's alg value changes and the compact serialization does not. That is the easy part. Around it, nearly everything that handles tokens changes too:
- Keys: ML-DSA keys use the new
kty: "AKP"JWK type (RFC 9964), so every JWKS publisher and consumer must understand it, and each public key is ~1.3–2.6 KB. - Verifier policy: each verifier needs an explicit allowlist of algorithms per key (RFC 8725 §3.1) — never "whatever the header says".
- Sizes and transport: header, cookie and proxy limits (below).
- Libraries: most JOSE libraries do not ship ML-DSA yet; check the JOSE layer, not just the crypto provider underneath.
- Rollout: a period where verifiers accept both old and new keys, and a plan to stop accepting the classical ones so the transition can't be used as a downgrade path.
{
"alg": "ES256",
"typ": "JWT",
"kid": "ec-key-2024"
}{
"alg": "ML-DSA-65",
"typ": "JWT",
"kid": "ml-dsa-key-2025"
}| Field | Classical | PQC | Notes |
|---|---|---|---|
| alg | ES256 | ML-DSA-65 | Algorithm identifier changes to PQC equivalent |
| typ | JWT | JWT | Token type remains unchanged |
| kid | ec-key-2024 | ml-dsa-key-2025 | Key ID references the PQC key |
Token Size Implications
The most significant practical impact of PQC JWTs is token size. ML-DSA-65 signatures are 3,309 bytes vs 64 bytes for ES256 — a 51x increase. This has cascading effects on HTTP headers, cookies, bandwidth, and storage.
Many servers default to 8 KB header limits. A single ML-DSA-65 JWT in an Authorization header uses ~60% of that budget (4.7 ÷ 8 = 0.59). With DPoP, two PQC JWTs could exceed the limit.
Browsers cap a cookie at about 4 KB, so a ~4.7 KB ML-DSA-65 JWT does not fit in one. Rather than moving bearer tokens into request bodies, keep the JWT server-side and give the browser an opaque session cookie (the backend-for-frontend pattern), or use reference tokens. Measure the real limits of your browsers, proxies and servers — they vary.
Mobile APIs with high request rates will see measurable bandwidth increases. Consider token caching and reference tokens as mitigation strategies.
OAuth 2.0 / OIDC with PQC
OAuth 2.0 and use JWTs in several places, but not everywhere: ID tokens are always JWTs; access tokens may be JWTs (RFC 9068) or opaque strings; refresh tokens are usually opaque handles the authorization server looks up, so a quantum computer cannot forge them unless they are themselves signed tokens. proofs (RFC 9449) are JWTs signed by the client, so PQC changes their key binding and verifier support as well as their size. Migrating requires coordinated changes across authorization servers, resource servers, and client applications.
Bearer tokens signed by the authorization server
ML-DSA-65 signatures increase token size from ~800 bytes to ~5 KB. May exceed default HTTP header limits.
OpenID Connect identity assertions
Same size increase as access tokens. Frontend libraries must handle larger tokens in cookies/localStorage.
Proof of possession for sender-constrained tokens (RFC 9449)
Each API request includes a DPoP proof JWT. PQC signatures add ~4 KB per request overhead.
JSON Web Key Sets published by the authorization server
ML-DSA public keys are 1,312–2,592 bytes (about 1.7–3.5 KB as base64url in an AKP JWK) vs 32–65 bytes for EdDSA/EC keys. JWKS payloads grow significantly during key rotation, when old and new keys are both published.
private_key_jwt client assertions
private_key_jwt assertions are signed with the client key, so they grow with PQC and the server must verify ML-DSA. client_secret_jwt uses HMAC and is not affected by Shor.
Server-side token validation (RFC 7662)
Larger tokens increase network overhead. Consider opaque tokens with introspection as an alternative.
JWT Validation Basics That PQC Does Not Change
A post-quantum signature protects a token only if the verifier checks the right things. Most real-world JWT breaches come from validation mistakes, and PQC fixes none of them. The rules below come from RFC 8725 (JWT Best Current Practices), RFC 9700 (OAuth 2.0 Security BCP) and RFC 9068 (JWT access tokens).
Decide which algorithm each key may be used with, and reject anything else — including alg "none" and an HMAC alg presented with a public key. The header is attacker-controlled (RFC 8725 §3.1–3.2).
Look keys up in a JWKS you configured, by kid. Never fetch a key from a URL inside the token (jku, x5u) unless it is on an allowlist (RFC 8725 §3.10).
Check iss and aud against what you expect, enforce exp and nbf with a small clock skew, and use jti where replay matters. A valid signature on the wrong audience is still the wrong token (RFC 8725 §3.8–3.9; exp, nbf and jti are defined in RFC 7519 §4.1).
Distinguish token kinds with typ — for example "at+jwt" for access tokens (RFC 9068) — so an ID token cannot be replayed as an access token (RFC 8725 §3.11–3.12).
In a nested JWT, verify the outer and the inner signature, each with the key and algorithm you expect (RFC 8725 §3.3). The Hybrid JWT tab does exactly this.
Decoding is not verifying, verifying is not validating claims, and a valid token is not authorization. Each step can fail independently; only all of them together say "accept".
One PQC-era change helps here: new JOSE registrations such as ML-DSA-65 are fully specified (RFC 9864): the alg value alone names the exact algorithm and parameters, which makes a per-key allowlist straightforward to write.
To see these checks fail on purpose, open the workshop's Attack Lab (Step 7): it aims "alg": "none", edited claims, a token for another API, an expired token and an ID token at a strict validator and at a naive verifier that trusts the header.
Related Resources
Decode JWTs, sign with ML-DSA, create hybrid tokens, and analyze sizes interactively.
Check off all sections and mark this reading done.
Related modules
- Email & Document SigningSame track · Protocols · Same migration phase · Shares ML-DSA, JOSE
- MLS — Group MessagingSame track · Protocols · Same migration phase · Shares ML-DSA, JOSE
- ACVP Lab Workflow: From Vector Set to EvidenceSame track · Protocols · Shares ML-DSA, SLH-DSA
- AI Security & PQCSame migration phase · Shares ML-DSA, SLH-DSA
In the Industry Landscape
Check your understanding
10 questions on API Security & JWT, each with its answer and the reason.
Take the quizNext step
Practice it: API Security & JWT WorkshopAPI Security & JWT Workshop is the hands-on version of this module: the same ideas, run in your browser.
Learning module content can be inaccurate. Please double-check its information. Report inaccuracies in PQC Today GitHub Discussions.