Back to DashboardProtocolsPhase 5 · Pilots & Migrationintermediate60 min

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.
Practice in the Simulation

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.

JWT Compact Serialization (JWS)
BASE64URL(Header).BASE64URL(Payload).BASE64URL(Signature)

The header specifies the algorithm (alg) and token type (typ). The payload carries claims. The signature covers both header and payload.

Header

header with alg (signing algorithm) and typ (token type). Base64url-encoded JSON.

Payload

Claims: sub, iss, exp, aud, plus custom claims. Base64url-encoded JSON.

Signature

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.

AlgorithmJOSE IDTypeQuantum AttackStatus
RS256 (RSA-2048)RS256SigningShor's algorithmVulnerable to a CRQC
ES256 (ECDSA P-256)ES256SigningShor's algorithmVulnerable to a CRQC
EdDSA (Ed25519)EdDSASigningShor's algorithmVulnerable to a CRQC
ECDH-ES (P-256)ECDH-ESKey AgreementShor's algorithmVulnerable to a CRQC
ML-DSA-65ML-DSA-65SigningNone knownPost-quantum
ML-KEM-768ML-KEM-768Key AgreementNone knownPost-quantum
Signed JWTs (JWS): a forgery risk, not HNDL

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.

Encrypted JWTs (JWE) and TLS: Harvest Now, Decrypt Later

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.

ML-DSA-44

Level 2

Public key: 1,312 bytes

Signature: 2,420 bytes

Category 2: at least as hard as a SHA-256 collision search

ML-DSA-65

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

ML-DSA-87

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.

Classical: ECDH-ES Key Agreement
Sender generates ephemeral EC keypair
↓
ECDH(ephemeral_sk, recipient_pk) → shared secret
↓
Concat KDF → Content Encryption Key (CEK)

ECDH falls to Shor's algorithm on a CRQC (discrete log on elliptic curves).

PQC: ML-KEM Encapsulation
ML-KEM.Encaps(recipient_pk) → (ct, shared_secret)
↓
HPKE key schedule(shared_secret) → AEAD key + nonce
the suite's KDF (SHAKE256 in the ML-KEM suites)
↓
AES-256-GCM-Encrypt(key, payload, AAD = header) → ciphertext

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.

Classical Header
{
  "alg": "ES256",
  "typ": "JWT",
  "kid": "ec-key-2024"
}
PQC Header
{
  "alg": "ML-DSA-65",
  "typ": "JWT",
  "kid": "ml-dsa-key-2025"
}
FieldClassicalPQCNotes
algES256ML-DSA-65Algorithm identifier changes to PQC equivalent
typJWTJWTToken type remains unchanged
kidec-key-2024ml-dsa-key-2025Key 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.

ES256 JWT (~300 bytes)~300 B
ML-DSA-65 JWT (~4,700 bytes)~4.7 KB (4,412 + 300 B)
HTTP Header Limit (default)8 KB
HTTP Header Limits

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.

Cookie Storage

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.

Bandwidth

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.

Access Tokens (JWS)
HIGH PRIORITY

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.

ID Tokens (JWS)
HIGH PRIORITY

OpenID Connect identity assertions

Same size increase as access tokens. Frontend libraries must handle larger tokens in cookies/localStorage.

DPoP Proofs (JWS)
MEDIUM PRIORITY

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.

JWKS Endpoints
MEDIUM PRIORITY

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.

Client Authentication
LOW PRIORITY

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.

Token Introspection
LOW PRIORITY

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).

Pin the algorithm to the key

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).

Resolve keys safely

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).

Validate the claims

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).

Use explicit typing

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).

Validate every layer

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.

Keep the steps separate

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.

In the Industry Landscape

Check your understanding

10 questions on API Security & JWT, each with its answer and the reason.

Take the quiz

Next step

Practice it: API Security & JWT Workshop

API 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.