Hello Ashwin,
Thank you for attempting to solve this concern.
When reading the draft, readers might believe that protecting the
private key will be sufficient.
11.11.Private Key Protection
The security of EPOP depends entirely on the client's private key
remaining secret.
Unfortunately, while necessary this is insufficient.
If two individuals accept to collaborate, whatever kind of cryptography
will be used, *whatever kind of protocol will be used,*
a software-only solution will be unable to prevent the transfer of a
token from another client to the same RS.
Collaboration really makes sense if the content of the token does not
contain a set of attributes that allows the RS
to identify the token owner *and* when the unlinkability property for
the same RS or between two RSs is supported.
It can also make sense if a token owner is willing to allow another
client to impersonate him.
In order to defeat collaboration attacks, for same-device authorization
flows, the RS would need to know
the characteristics of the hardware device and of the applications used
by the individual to perform the access
(without, for privacy reasons,being able to uniquely identify the device
or the application).
In practice, this mandates the use of a TEE and of TAs whichis an area
that has not yet been addressed by the OAuth WG.
Collaboration can also take place for cross-device authorization flows.
The IETF draft draft-ietf-oauth-cross-device-security-16 explores the
best current practices: "Cross-Device Flows: Security Best Current
Practice".
Section 4.3.10 "Out of Scope“ indicates:
“ For other attacks, where the user is willingly colludingwith the
attacker,
the threat model, security implications and potential mitigations
are very different”.
(...)
This document only considers scenarios where a user does not collude
with an attacker.
As currently recommended in this IETF draft, a first step would be to
mandate a proximity mode of connection between the two devices.
A second step would be needed to make sure that both devices are owned
by the same person.
A possible solution would be to use biometric controls, but not those
currently natively supported by the device
which are more a “commodity feature” rather than a “security feature":
e.g., it is a common practice to allow
the use of more than one biometric template for face recognition.
At the moment, it looks difficult to fully defeat collusion attacks for
cross-device authorization flows, but it looks possible to mitigate them.
This is an area that has not yet been explored.
All these considerations do not appear in section 11 (Security
Considerations).
Regards,
Denis
Hi Niel
>While I can see the motivation, IMO the HTTP-specificity of DPoP is
an advantage from a security point of view. Otherwise, like this
draft, you end up with lots of crucial checks being conditional.
Are you suggesting separating drafts by protocols or suggesting that
other protocols should not be supported?
>The problem I think you have is that the EPOP proof is wrapping the
token ..
>EPOP seems to have the further issue that the proof itself contains ..
The trust establishment pattern you describe as "suspending disbelief"
is the same two-phase model used in certificate-based authentication
and codified in RFC 9883: a self-asserted public key is presented, the
relying party verifies the signature with it (establishing key
possession), and authorization of that key is then confirmed via a
separate chain check. Nobody considers TLS client certificate
authentication problematic on these grounds. EPOP follows the same
principle: steps 1–3 establish that the sender holds the private key;
step 8 (cnf.jkt cross-check) establishes that the AS authorized that
key for the nested credential. These answer different questions and
must run in sequence.
On parsing an "untrusted" token: after steps 1–3 pass, the outer token
is not unexamined — its signature has been verified. This proves key
possession. An attacker who wraps a stolen access token in their own
EPOP envelope will pass steps 1–3 but fail step 8, because the cnf.jkt
inside the AS-issued nested token does not match their self-generated
JWK thumbprint. The AS bound that value at issuance; it is not under
attacker control in the resource access flow.
On the cnf.jkt concern: I think there may be a conflation of two
distinct flows. In authorization code exchange, cnf.jkt is
client-declared (same as client_assertion in RFC 7521), and PKCE
provides the complementary binding. In resource access, cnf.jkt is
embedded in the AS-issued access token and is not under attacker
control — this is the primary token substitution defense. In rotation
flow, new cnf.jkt is attested by the previously known EPOP key, which
is attested by the underlying refresh token.
On conditionality: DPoP has the same structural characteristic — nonce
is optional, ath is conditional on token type. EPOP's validation
algorithm in §5 is a strict sequential procedure with explicit
normative requirements at each step. I am open to discussion on
whether specific conditions in the draft need tighter language.
Regards
Ashwin
On Wed, May 20, 2026 at 1:04 PM Neil Madden <[email protected]>
wrote:
> On 20 May 2026, at 19:52, Ashwin Ambekar <[email protected]> wrote:
>
>
> Hi Gabriel,
>
> There is a broader point that I think gets missed in the ~ vs
nesting discussion: neither SD-JWT nor DPoP address
sender-constraining for opaque access tokens across non-HTTP
transports. SD-JWT requires JWT structure — it has nothing to work
with for opaque tokens. DPoP handles opaque tokens on HTTP via
ath, but the htm/htu claims make it HTTP-only. A client holding an
opaque AT on Kafka, MQTT, or SASL has no sender-constraining path
under either mechanism.
While I can see the motivation, IMO the HTTP-specificity of DPoP
is an advantage from a security point of view. Otherwise, like
this draft, you end up with lots of crucial checks being conditional.
>
> EPOP's ntk treats JWT and opaque tokens identically: the
credential goes in ntk, the outer envelope provides the proof, and
validation follows the same path regardless of token format or
transport. This uniform treatment of opaque tokens across all
transports is a primary design goal, not an incidental feature.
> There is a convergence path where SD tokens can be the ntk claim
inside the EPOP token, which I'll be willing to explore as a
follow-on draft if you are interested.
The problem I think you have is that the EPOP proof is wrapping
the token, but the token needs to be validated in order to
establish trust in the proof key. Sure, you can do that, but it
means you have to suspend disbelief for a while - validating the
EPOP proof based on a self-asserted JWK and only much later do you
get around to checking if that key is trusted. That seems a
problematic design to me. (I had a similar concern with DPoP, but
this seems a step even further down that road). I shouldn’t be
having to parse an untrusted token to find another token that’ll
eventually let me tie off the trust knot. That way lies doom.
EPOP seems to have the further issue that the proof itself
contains a self-asserting cnf/jkt claim that sometimes seems to
have to match the jwk header (both under attacker control, so
pointless), but at other times might be a nested token where it
matches the outer proof key.
I think there’s just far too much complexity and conditionality in
this as specified to make a robust security mechanism.
— Neil
Regards
Ashwin Ambekar
_______________________________________________
OAuth mailing list [email protected]
To unsubscribe send an email [email protected]
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]