Hi Neil,
thanks for the detailed review. Here are my thoughts:
*1.* DPoP exists because TLS alone was judged insufficient to protect
access tokens in real deployments. We're applying the same reasoning to
the request the token authorizes. TLS termination at DDoS protection or
corporate proxies is a deployment reality. The difference from HttpSig
is that a terminating proxy gets full read/write access under TLS, but
cannot forge a signature. Stripping it doesn't help either, because the
AS/Credential Issuer requires it.
The motivating payloads (holder keys and key attestations in OpenID4VCI
proofs) aren't secret, so confidentiality isn't my concern. The attack
is substituting them so the credential is bound to an
attacker-controlled key, so integrity is the property at stake. Where
additional confidentiality is needed, OpenID4VCI provides options for
application-level encryption, but that's debatable.
The signature is verified where the request is semantically consumed,
i.e. the Credential Issuer endpoint. The issuer's internal decomposition
is its own trust domain, which is the same scoping as DPoP.
*2.* One of the ideas here is that you may want to bind an RT to a
different key (e.g. HSM) than an AT.
*3/4.* I'm working in regulated industries, where usage of HSM is
mandatory, loading private keys in memory is simply not allowed.
RFC 9449 doesn't require a server to return |DPoP-Nonce| on a proof-less
request, and doesn't mandate error precedence, so clients can't rely on
this interoperably. The AS may simply return an |invalid_request|, and
not return a nonce. It also only covers the first request: on nonce
rotation, the client discovers expiry only through a failed signed request.
Best regards,
Paul
On 9/23/26 2:53 PM, Neil Madden wrote:
Hi Paul,
Thanks for sharing this slide deck. I think it would be useful if some
of this rationale was summarised into the draft introduction, so that
it is clear to readers what problems the new proposal is intended to
solve.
I summarise your arguments as follows:
1. DPoP doesn't protect the contents of HTTP messages, such as public
keys in OpenID4VCI proofs.
2. DPoP doesn't protect refresh tokens for confidential clients, and,
when it is used for (public client) RTs it uses the same key as
for ATs.
3. Nonce negotiation requires an additional roundtrip with a "wasted
signature" to retrieve an initial/updated nonce. This is
potentially expensive in time and money especially for HSM-backed
signing keys.
4. The HTTP 400 status code when requiring a nonce is confusing and
leads to broken client logic.
My responses to these issues are as follows:
1. The need to protect message bodies:
The cited need for this is to protect against active attackers "after
TLS termination". I would firstly question why OAuth needs to address
what clearly appears to be architectural defict. If the payload needs
protection "after TLS termination" then why has TLS been terminated
prematurely? (And what would prevent HttpSig also being terminated
similarly prematurely at some middlebox?).
Why only protect integrity? TLS also protects confidentiality, and
that protection is also being lost by this early termination. I fear
that if we approve this approach, then it's only a matter of time
before somebody then claims that confidentiality also needs to be
protected downstream of TLS termination. Signatures are no help at all
with that.
There is also the question of what happens even further downstream.
TLS termination is presumably being done at a gateway which is then
forwarding the request un-altered. But what happens when it then hits
eg a frontend service and results in N new requests to backend
microservices, each request slightly different (but perhaps including
sensitive details from the original)? All those requests would also
need protection under your rationale, but neither DPoP nor HttpSig can
address that, being point-to-point solutions rather than end-to-end.
Either you need to go back to properly configuring TLS where it is
needed (perhaps via a service mesh), or else design a solution that
does work end-to-end.
Finally, as already noted, using a non-repudiable signature over the
entire HTTP body is using a sledgehammer to crack a nut, and will have
unintended consequences (see my other messages in this thread).
2.
i. No DPoP for Confidential Client RTs
I don't really understand this problem. As the DPoP RFC notes, RTs for
confidential clients are already sender-constrained, so what is the
problem?
ii. Using the same key for RTs and ATs
Again, what is the problem here? There's nothing inherently bad about
using the same key to sign DPoP proofs for ATs and RTs. What threat
model are you trying to address?
3. Nonce negotiation is expensive.
4. Nonce negotiation using 400 status is annoying.
I don't disagree with this. I don't particularly love the DPoP nonce
negotiation. (A long time ago I proposed an alternative based on ECDH
key agreement and then the use of a short-term HMAC key instead, but
it was rejected by the WG).
IMO the HSM issue is also an architectural problem. After much
real-world experience with HSMs and KMSes I have formed the conclusion
that you want them out of the hot path of your systems as much as
possible: they are a reliability and performance bottleneck. Instead,
I always recommend that people follow the approach of Google's Tink
cryptography library: use the HSM to decrypt a set of keys on
startup/periodically and then use those keys locally rather than
calling out the HSM every time. Rotate them regularly mitigate to
reduce the risk of compromise. I appreciate this is not always
possible, but I've never seen anything but pain from having a direct
dependency on a HSM at runtime.
But aren't these issues solved anyway by the client simply not sending
a DPoP proof at all in its first request? The server should then
respond with a 401 and WWW-Authenticate: DPoP header, and could simply
include a DPoP-Nonce header too at that time. No extra overhead for
the client, normal 401 return code, and all done in a single
roundtrip. This already seems permitted by the spec.
On contrast, the draft being proposed here doesn't support
server-generated responses at all, only client-supplied ones. This
doesn't address the precomputation attack discussed section 11.2 of
RFC 9449, which was the reason for adding nonces in the first place.
So this argument doesn't appear to be addressed in any case by the
proposed draft.
-- Neil
On 22 Sep 2026, at 20:41, Paul Bastian <[email protected]> wrote:
Hi Warren,
Here is the slide deck from OSW:
https://docs.google.com/presentation/d/1M54dFlaJP0UXeuIpYS3iPDDW3ulmySYP4yStO14SrbE/edit?usp=drivesdk
We asked people at the end of the presentation which direction to go.
Nobody supported extending DPoP. 5 people supported the direction of
this draft.
Best regards,
Paul
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]