Hi Joe,
Thank you for this -- you're correct that cnonce does not prevent
pre-generation attacks. cnonce is entirely deterministic from public inputs
(SPKI + published epop_cnonce_seed + time-step).

The motivation behind cnonce is distinct from DPoP's server nonce. The
server publishes the time-step parameters (epop_cnonce_step_seconds,
epop_cnonce_seed), and validation runs against the server's clock — the
client is bound to the server's time-step grid and cannot escape it. This
gives the server control over the expiration window without issuing
per-client nonce values, allowing any verifier to check cnonce statelessly
from the client's public key and the published parameters.
cnonce alone does not address pre-generation attacks. The draft addresses
this through atomic key rotation as part of the refresh token flow — the
client rotates to a new key pair, the server validates the rotation chain
and re-binds the new key, and any tokens pre-generated with the old key are
invalidated from that point. Regular key rotation, validated by the server
at each refresh, bounds the window during which a compromised key remains
useful.

The specific goals are: (1) eliminate per-client nonce state on the server,
which matters for horizontally-scaled deployments; (2) support non-HTTP
protocols like Kafka where a server nonce round-trip is not possible; and
(3) address the practical reality that DPoP's server nonce is optional and
frequently skipped precisely because of the per-client state management
burden — against that realistic baseline, cnonce provides an independent
server-governed time-bound with no added server state.

I can consider revising section 7/7.1.. If there are more inputs please
share. This was very helpful.

Regards
Ashwin

On Tue, May 19, 2026 at 10:08 AM Joe DeCock <[email protected]> wrote:

> I would also appreciate if you could talk more about the design of the
> cnonce. It seems like it is meant to replace the server nonce in DPoP, but
> I don't understand how it can accomplish that. As I understand it, the
> purpose of DPoP's server nonce is to prevent pre-generation attacks. It can
> do that because the value of the server nonce is unpredictable. In
> contrast, EPOP's cnonce is entirely deterministic. It seems like cnonce
> isn't really meant to prevent pre-generation attacks. But if that's the
> case, could you simplify the protocol by removing it entirely, since you
> already have iat for time-bounding the token, and jti for replay detection?
>
> Thanks,
> Joe
>
> On Mon, May 18, 2026 at 6:02 PM Joe DeCock <[email protected]> wrote:
>
>> Hi Ashwin,
>>
>> I think this is an interesting idea. Applying sender constraints without
>> being tied to http is clearly a real problem.
>>
>> I'd be curious to hear more from you about the tradeoffs you considered
>> when designing EPOP and why you made the decisions you did. For example, my
>> intuition is that the enveloped approach results in larger data structures
>> compared to a detached signature. Did you consider a design that keeps the
>> detached signatures of DPoP?
>>
>> Thanks for your work on this draft.
>>
>> Joe DeCock
>>
>>
>> On Sat, May 16, 2026 at 9:14 PM Ashwin Ambekar <[email protected]> wrote:
>>
>>> Hi all,
>>>
>>> I've submitted an initial Internet-Draft for a new OAuth 2.0 token
>>> profile called Enveloped Proof of Possession (EPOP):
>>>
>>> https://datatracker.ietf.org/doc/draft-ambekar-oauth-epop/
>>>
>>> ## What EPOP introduces
>>>
>>> EPOP defines a single unified token type that carries both the
>>> credential (authorization code, access token, or refresh token) and its
>>> cryptographic proof of possession as an inseparable envelope. This
>>> eliminates the split between token issuance and proof construction that
>>> exists in current mechanisms, and brings the following properties:
>>>
>>> 1. **Unified credential + proof token** — The credential and its PoP
>>> proof are bound together at issuance into a single JWT envelope,
>>> cryptographically tied to the client's key pair. Possession of the token
>>> alone is insufficient to use it.
>>>
>>> 2. **Transport-agnostic proof of possession** — EPOP proof validation
>>> does not depend on HTTP request parameters, making it applicable uniformly
>>> across HTTP and non-HTTP transports: MQTT, Kafka, gRPC, SASL, and emerging
>>> agentic protocols such as MCP.
>>>
>>> 3. **Extended PoP support for RFC 7628 (SASL/OAuth)** — EPOP provides a
>>> concrete proof-of-possession mechanism for SASL-based OAuth flows defined
>>> in RFC 7628, which currently lacks a sender-constraining profile.
>>>
>>> 4. **Client-derived nonce (cnonce)** — EPOP introduces an
>>> offline-derived client nonce computed deterministically from the client's
>>> private key and token material. This eliminates the server-issued nonce
>>> round-trip required by existing mechanisms, enabling stateless proof
>>> validation at the resource server — critical for high-throughput and
>>> constrained deployments.
>>>
>>> The draft also covers atomic key rotation, discovery metadata
>>> extensions, and security considerations for replay prevention and token
>>> substitution across all supported transports.
>>>
>>> ## Seeking feedback on
>>>
>>> - Whether the unified envelope model introduces any token substitution
>>> or cross-credential attack surface not addressed in Section 10.
>>> - Soundness of the cnonce derivation and replay window model.
>>> - Operator and implementer perspectives, particularly for non-HTTP
>>> deployments.
>>> - Any overlap with active WG drafts I should reference or reconcile
>>> against.
>>>
>>> Source and issue tracker: https://github.com/asambeka/epop
>>>
>>> All review, critique, and collaboration interest welcome.
>>>
>>> Thanks,
>>> Ashwin Ambekar
>>> eBay
>>> _______________________________________________
>>> OAuth mailing list -- [email protected]
>>> To unsubscribe send an email to [email protected]
>>>
>>

-- 
Regards
Ashwin Ambekar
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to