# OAuth 2.0 and PQC: JWS Algorithm Identifiers

**Source**: https://quantumsequrity.com/blog/oauth-2-pqc
**Category**: Implementations

---

[← Back to Blog](../../blog) Implementations

# OAuth 2.0 and PQC: JWS Algorithm Identifiers

11 min read

OAuth 2.0 is the protocol that lets you click "Sign in with Google" or "Sign in with GitHub" and end up logged into a third-party app without ever handing that app your password. It is, in practical terms, the load-bearing identity layer of the modern web. Every API key flow, every social login, every machine-to-machine token exchange in modern SaaS rides on top of it.

The protocol itself, defined in RFC 6749, is mostly about how tokens are issued, refreshed, and presented. But the tokens themselves are usually JSON Web Tokens (JWTs), which are signed with JSON Web Signature (JWS), defined in RFC 7515. And those signatures, today, are almost always made with classical algorithms like RSA-PSS, ECDSA, or EdDSA — algorithms that a sufficiently large quantum computer running Shor's algorithm would shred through.

When NIST finalized FIPS 204 (ML-DSA) in August 2024, the JOSE (JavaScript Object Signing and Encryption) Working Group inside IETF began the slow, careful process of registering post-quantum algorithm identifiers in the JOSE algorithms registry. This blog post walks through what changes, what stays the same, and what implementers need to start thinking about now.

## OAuth 2.0 In One Paragraph

OAuth 2.0 is a delegation protocol. A user (the resource owner) authorizes a client (an app) to access protected resources hosted by a resource server, mediated by an authorization server. The authorization server hands the client an access token. The client presents that token to the resource server, which verifies it and either grants or denies access.

The token is opaque to the client in some flows, but in most modern deployments — especially when OpenID Connect is layered on top — the token is a signed JWT. The signature is what makes the token trustworthy: anyone who has the authorization server's public key can verify that the token was actually issued by that authorization server and has not been tampered with.

That signature is exactly where post-quantum cryptography enters the picture.

## Why JWS Signatures Matter For PQC

Access tokens have short lifetimes — often 5 minutes, sometimes an hour. Refresh tokens last longer, sometimes weeks or months. ID tokens (the OpenID Connect ones that carry user identity claims) are usually short, but they often get logged, and those logs sit around forever.

The threat model for [harvest now, decrypt later](../../blog/harvest-now-decrypt-later) does not apply quite the same way to signatures as it does to encryption. A signature, once verified, has done its job. An attacker who later breaks the signing algorithm cannot retroactively un-verify a transaction.

But the attacker can do something much worse: they can forge new tokens. If a quantum-capable adversary derives the authorization server's private signing key from harvested public keys plus algorithmic break, they can mint arbitrary access tokens that pass verification at every resource server. They can issue themselves admin tokens. They can impersonate any user. They can do this silently, with no log entry that distinguishes a forged token from a legitimate one.

This is why the JOSE WG is being deliberate about getting PQC signature identifiers right.

## The JOSE Algorithms Registry

IANA maintains the JOSE algorithms registry under https://www.iana.org/assignments/jose. Every algorithm name that can appear in a JWS `alg` header — `RS256`, `ES256`, `EdDSA`, and so on — is registered there. The registry is the single source of truth.

For ML-DSA, the IETF draft `draft-ietf-cose-dilithium` (which was renamed during the standardization process and now tracks the FIPS 204 final names) and the related JOSE work specify the identifier scheme. The names follow the FIPS 204 naming directly: `ML-DSA-44`, `ML-DSA-65`, and `ML-DSA-87` correspond to the three parameter sets for security categories 2, 3, and 5 respectively.

So a post-quantum-signed JWT header looks like this:

```
{"alg":"ML-DSA-65","typ":"JWT"}
```

The verification side of the equation is symmetric: the relying party fetches the signing key from a JWKS (JSON Web Key Set) endpoint, sees that the key has a `kty` (key type) appropriate for ML-DSA, and runs the FIPS 204 verification routine.

## Token Size: The Elephant In The Header

Here is where the conversation gets uncomfortable. ECDSA P-256 produces 64-byte signatures. EdDSA over Ed25519 produces 64-byte signatures. RSA-2048 with PSS produces 256-byte signatures. These are small enough that a JWT carrying user claims plus a signature still fits comfortably in an HTTP header, in a URL fragment, or in a cookie.

ML-DSA-65, by contrast, produces signatures of 3,309 bytes. ML-DSA-87 produces signatures of 4,627 bytes. Public keys are also bigger: 1,952 bytes for ML-DSA-65 and 2,592 bytes for ML-DSA-87.

A JWT signature in base64url is roughly 4/3 the size of the binary signature. So an ML-DSA-65 JWT signature, encoded for transport, is around 4,400 bytes. The full JWT — header plus claims plus signature — easily exceeds 5 KB.

What does this break?

- **Cookie size limits**: most browsers cap individual cookies at 4 KB. A PQC-signed JWT cookie may not fit.
- **HTTP header size limits**: many HTTP servers default to 8 KB total header size. If your app stores the JWT in `Authorization: Bearer ...` and also has other large headers, you can blow past this.
- **URL length limits**: some flows (like the deprecated implicit grant, or some token introspection responses) put tokens in URLs. PQC JWTs are too big.
- **Mobile networks**: every kilobyte of header sent on every API call adds latency on slow connections.

The mitigation strategies the JOSE WG and OAuth WG are exploring include:

- Pushed Authorization Requests (RFC 9126) to keep large requests off the URL.
- Sender-constrained tokens via DPoP (RFC 9449), where the proof is a separate JWT.
- Token introspection (RFC 7662) so that the resource server can ask the authorization server about the token rather than parsing a giant JWT.

## ML-DSA vs SLH-DSA In OAuth Contexts

NIST standardized two PQC signature schemes: ML-DSA (FIPS 204) based on lattices, and SLH-DSA (FIPS 205) based on hash trees. We have a [whole article comparing these two](../../blog/mldsa-vs-slhdsa), but the OAuth-specific summary is:

- **ML-DSA** has signatures of 2,420–4,627 bytes depending on parameter set. Verification is fast.
- **SLH-DSA** has signatures of 7,856–49,856 bytes depending on parameter set. Verification is fast for the smaller sets but signing is significantly slower.

For high-throughput authorization servers minting millions of tokens per minute, ML-DSA is the realistic default. SLH-DSA's bigger signatures and slower signing make it impractical for hot-path token issuance, though it remains attractive for long-lived signing keys (like trust anchors) where the conservative hash-based foundation is reassuring.

## Hybrid Signatures In OAuth

Just like in [hybrid encryption](../../blog/hybrid-encryption), there is interest in hybrid signatures: a JWT that carries both an ECDSA signature and an ML-DSA signature, with the verifier requiring both to pass.

The JOSE WG has discussed this but has not yet standardized a specific composite identifier scheme. The conservative approach in the meantime is to issue two JWTs — one classical, one PQC — and have the relying party verify both. This is messy but works with deployed code.

## Migration Plan For OAuth Servers

If you operate an authorization server today, here is the practical sequence.

**Step 1: Inventory your signing keys.** Most authorization servers have a small number of signing keys with well-defined rotation schedules. Document them.

**Step 2: Add ML-DSA key generation to your key ceremony.** When you next rotate, generate an ML-DSA key alongside your ECDSA or RSA key.

**Step 3: Publish both keys at your JWKS endpoint.** A JWKS endpoint can serve multiple keys. Add the ML-DSA key with a distinct `kid` (key ID).

**Step 4: Sign with the classical key by default.** Most relying parties cannot verify ML-DSA yet. Do not break them.

**Step 5: Offer ML-DSA signing as an opt-in.** Let advanced clients request ML-DSA tokens via a request parameter or scope.

**Step 6: Monitor the JOSE registry.** Once `ML-DSA-65` is officially registered with a stable identifier, switch your opt-in clients to use it.

**Step 7: Eventually flip the default.** When the majority of relying parties support ML-DSA verification, default to ML-DSA and offer ECDSA as the legacy fallback.

This is a multi-year process. Start now.

## What QNSQY Does With OAuth

QNSQY's file protection is independent of OAuth. Files are encrypted and signed on the user's device, and a file's [post-quantum signature](../../blog/hybrid-encryption) protects its integrity whatever happens to the tokens that authorize access to an online service. Tokens and file signatures are different layers, and each needs its own migration plan.

## DPoP, mTLS, And Sender-Constrained Tokens

A specific OAuth pattern that interacts interestingly with PQC is sender-constrained tokens. With DPoP (RFC 9449), the client holds a private key and signs a "DPoP proof" JWT with each API call, proving possession of the key. The access token references the public key thumbprint, so a stolen access token cannot be used by anyone who lacks the corresponding private key.

DPoP today uses ECDSA or EdDSA proofs. Migrating DPoP to ML-DSA inherits the same size penalty: every API call now carries a 4 KB DPoP proof on top of the access token. For high-volume APIs, this is operationally painful.

The alternative is mTLS-bound tokens (RFC 8705), where the access token is bound to a TLS client certificate. Here PQC arrives at the TLS layer (via the [TLS 1.3 hybrid handshake](../../blog/tls-1-3-hybrid-handshake)) and the binding to the access token is via the certificate fingerprint, which is not a PQC-affected primitive. This means mTLS-bound tokens may be a more PQC-friendly direction for sender-constrained OAuth than DPoP.

OAuth deployments with security-sensitive sender-constraint requirements should evaluate mTLS over DPoP for the PQC era, especially for high-throughput cases.

## Authorization Server Performance

Authorization servers mint access tokens at very high rates. Major cloud IdPs issue billions of tokens per day. Each token issuance is a signing operation.

ML-DSA-65 signing on modern x86 hardware runs at roughly 100,000 signatures per second per core, comparable to ECDSA-P256 signing speed. So pure CPU cost is not the bottleneck. The bottleneck is the bandwidth and storage cost of the larger tokens flowing through the system: token databases (if you store tokens), rate-limiting state, audit logs, and all the operational telemetry.

For most authorization servers, this means an infrastructure scaling exercise rather than a cryptographic capability gap. The crypto is fast; the surrounding infrastructure needs to absorb the size growth.

## Frequently Asked Questions

**Q: Will my existing OAuth library work with ML-DSA tokens?**
Not yet. Most JOSE libraries do not implement ML-DSA verification. As the IANA registration completes and major libraries (jose-jwt, nimbus-jose-jwt, jsonwebtoken) ship support, this will change. Track your library's release notes.

**Q: Are JWT bearer tokens still safe to use without PQC?**
For now, yes. There is no quantum computer today that can break Ed25519 or ECDSA P-256. The risk is forward-looking. But because rolling out PQC takes years, planning needs to start now.

**Q: Does PKCE need to change for PQC?**
No. PKCE (RFC 7636) uses SHA-256 as a one-way hash for code challenges. SHA-256 is not broken by quantum attacks (Grover's algorithm only halves its security, leaving 128-bit effective security, which is fine).

**Q: What about client authentication via private_key_jwt?**
Same answer as for ID tokens. The client's signing key needs to migrate to ML-DSA on the same timeline as the authorization server's signing key. Plan the migration jointly.

**Q: Is there a smaller PQC signature scheme I could use instead?**
Falcon (FN-DSA, the upcoming FIPS 206) has smaller signatures (around 666 bytes for Falcon-512). But it has implementation hazards around constant-time floating-point arithmetic, and the FIPS standard is not finalized yet. ML-DSA is the safer near-term choice.

## Sources

1. RFC 6749 — The OAuth 2.0 Authorization Framework. https://datatracker.ietf.org/doc/html/rfc6749
2. RFC 7515 — JSON Web Signature (JWS). https://datatracker.ietf.org/doc/html/rfc7515
3. RFC 7519 — JSON Web Token (JWT). https://datatracker.ietf.org/doc/html/rfc7519
4. NIST FIPS 204 — Module-Lattice-Based Digital Signature Standard. https://csrc.nist.gov/pubs/fips/204/final
5. IANA JOSE Algorithms Registry. https://www.iana.org/assignments/jose
6. RFC 9126 — OAuth 2.0 Pushed Authorization Requests. https://datatracker.ietf.org/doc/html/rfc9126
7. RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP). https://datatracker.ietf.org/doc/html/rfc9449

## Related Articles

- [What Is Post-Quantum Cryptography?](../../blog/what-is-post-quantum-cryptography)
- [ML-DSA Explained](../../blog/mldsa-vs-slhdsa)
- [Hybrid Encryption](../../blog/hybrid-encryption)
- [NIST FIPS Guide](../../blog/nist-fips-guide)
- [Harvest Now, Decrypt Later](../../blog/harvest-now-decrypt-later)

---

### Protect Your Data Before Q-Day Arrives

QNSQY's NIST-standardized post-quantum encryption protects files against both current and quantum-era threats.

[Try QNSQY](../../pricing)
