Echoing Neil's concerns, I posted this to the issue tracker:
https://github.com/danielfett/draft-dpop/issues/56

I've been talking to several large scale API operators about DPoP.  A
consistent concern is the CPU cost of doing an asymmetric key
validation on every HTTP Request at the RS.

Micro-benchmarks on this are easy to make, and at lower in the
protocol stack, eg TLS, there is only one asymmetric operation before
a symmetric key is exchanged, so maybe DPoP as it stands would be hard
to deploy.

I think the primary concern is at the RS level of validation.
Depending on the RS, the "work" of a request can be highly variable,
so adding a single asymmetric key operation could be a significant
portion of CPU usage at scale.

In my discussions, at the AS layer, there is a general belief that the
request rate and overhead of validating a DPoP signature can be OK.
(I work at Okta -- the AS CPU usage is important too, but we already
do a bunch of "other" expensive work on token requests, such that
adding one more EdDSA validate is a rounding error in the short term).

Supporting `HS256` or similar signing of the proof would be one way to
reduce the CPU usage concerns.

The challenge seems to be getting the symmetric key to the RS in a
distributed manner.

This use case could be scoped as a separate specification if that
makes the most sense, building upon DPoP.

Throwing out a potential scheme here:

- **5.  Token Request (Binding Tokens to a Public Key)**: The request
from the client is unchanged. If the AS decides this access token
should use a symmetric key it:
1) Returns the `token_type` as `DPoP+symmetric`
2) Adds a new field to the token response: `token_key`.  This should
be a symmetric key in JWK format, encrypted to the client's DPoP-bound
asymmetric key using JWE.  This means the client still must be able to
decrypt this JWE before proceeding using its private key.

- **6.  Resource Access (Proof of Possession for Access Tokens)**: The
DPoP Proof from the client would use the `token_key` issued by the AS.

- **7.  Public Key Confirmation**: Instead of the `jkt` claim, add a
new `cnf` claim type: JSON Encrypted Key or  `jek`.  The `jek` claim
would be an JWE encrypted value, containing the symmetric key used for
signing the `DPoP` proof header in the RS request.   The JWE
relationship between the AS and RS would be outside the scope of the
specification -- many AS's have registries of RS and their
capabilities, and might agree upon a symmetric key distribution system
ahead of time, in order to decrypt the `jek` confirmation.

I think this scheme would change RS validation of an DPoP-bound proof
from one asymmetric key verify, into two symmetric key operations: one
signature verify on the DPoP token, and potentially one symmetric
decrypt on the `jek` claim.

On Thu, Nov 14, 2019 at 3:20 AM Neil Madden <neil.mad...@forgerock.com> wrote:
>
> I can't attend Singapore either in person or remotely due to other 
> commitments. I broadly support adoption of this draft, but I have some 
> comments/suggestions about it.
>
> Section 2 lists the main objective as being to harden against 
> compromised/malicious AS or RS, which may attempt to replay captured tokens 
> elsewhere. While this is a good idea, a casual reader might wonder why a 
> simple audience claim in the access token/introspection response is not 
> sufficient to prevent this. Because interactions between the client and RS 
> are supposed to be over TLS, is the intended threat model one in which these 
> protections have broken down? ("counterfeit" in the description suggests 
> this). Or is the motivation that clients want to get a single broad-scoped 
> access token (for usability/performance reasons) and use it to access 
> multiple resource servers without giving each of them the ability to replay 
> the token to the other servers? Or are we thinking of a phishing-type 
> vulnerability were a general-purpose client might accidentally visit a 
> malicious site which prompts for an access token that the client then blindly 
> goes off and gets? (UMA?) It's not clear to me w
 hich of these scenarios is being considered, so it would be good to tighten up 
this section.
>
> Another potential motivation is for mobile apps. Some customers of ours would 
> like to tie access/refresh tokens to private key material generated on a 
> secure element in the device, that can only be accessed after local biometric 
> authentication (e.g. TouchID/FaceID on iOS). I have suggested using mTLS 
> cert-bound tokens for this, but have heard some pushback due to the 
> difficulty of configuring support for client certs across diverse 
> infrastructure. A simple JWT-based solution like DPoP could fill this need.
>
> My main concerns with the draft though are about efficiency and scalability 
> of the proposed approach:
>
> 1. The requirement to use public key signatures, along with the anti-replay 
> nonce, means that the RS is required to perform an expensive signature 
> verification check on every request. That is not going to scale up well. 
> While there are more efficient schemes like Ed25519 now, these are still 
> typically an order of magnitude slower than HMAC and the latency and CPU 
> overhead is likely to be a non-starter for many APIs (especially when you're 
> billed by CPU usage). Public key signatures are also notoriously fragile (see 
> e.g. the history of nonce reuse/leakage vulnerabilities in ECDSA or
>
> 2. The advice for the RS to store a set of previously used nonces to prevent 
> replay will also hamper scalability, especially in large deployments where 
> such state would need to be replicated to all servers (or use sticky load 
> balancing, which comes with its own problems). This violates the 
> statelessness of HTTP, and it also potentially breaks idempotency of 
> operations: Think of the case where the JWT validation and replay protection 
> is done at an API gateway but then the call to the backend API server fails 
> for a transient reason. The client (or a proxy/library) cannot simply replay 
> the (idempotent) request in this case because it will be rejected by the 
> gateway. It must instead recreate the DPoP JWT, incurring additional 
> overheads.
>
> 3. Minor: The use of a custom header for communicating the DPoP proof will 
> require additional CORS configuration on top of that already done for the 
> Authorization header, and so adds a small amount of additional friction for 
> adoption. Given that CORS configuration changes often require approval by a 
> security team, this may make more of an impact than you'd expect.
>
> It's also not clear to me exactly what threat the anti-replay nonce is 
> protecting against. It does nothing against the replay scenario discussed in 
> section 2, as I understand it - which really seems to be more of a MitM 
> scenario. Given that the connection between the client and the RS is supposed 
> to be over TLS, and TLS is already protected against replay attacks, I think 
> this part needs to be better motivated given the obvious costs of 
> implementing it.
>
> I have a tentative suggestion for an alternative design which avoids these 
> problems, but at a cost of potentially more complexity elsewhere. I'll 
> summarise it here for consideration:
>
> 1. The client obtains an access token in the normal way. When calling the 
> token endpoint it provides an EC/okp public key as the confirmation key to be 
> associated with the access/refresh tokens.
>
> 2. The first time the client calls an RS it passes its access token in the 
> Authorization: Bearer header as normal. (If the RS doesn't support DPoP then 
> this would just succeed and no further action is required by the client - 
> allowing clients to opportunistically ask for DPoP without needing a priori 
> knowledge of RS capabilities).
>
> 3. The RS introspects the access token and learns the EC public key 
> associated with the access token. As there is no DPoP proof with the access 
> token, the RS will generate a challenge in the following way:
>     o The RS generates an ephemeral EC key pair for the same curve as the 
> confirmation key (e.g. P-256 or X25519).
>     o The RS stores the ephemeral private key somewhere, associated with this 
> access token (see below for a scalable implementation choice)
>     o The RS encodes the ephemeral public key into a JWK (epk) and 
> base64url-encodes it. It uses this as a challenge to the client by sending 
> back a 401 response with WWW-Authenticate: DPoP <encoded-epk>
>
> 4. The client decodes the epk challenge and performs an ECDH key agreement 
> between its private key and the challenge epk as per the method described for 
> the existing JWA ECDH-ES encryption algorithm. Rather than deriving an AES 
> key however, it derives a HMAC key for HS256. The "apu" value is set to the 
> access token (string value as ASCII bytes) and the "apv" value is set to the 
> hostname of the RS (e.g. "api.example.com"). This ensures that the derived 
> key is cryptographically bound to the context in which it is used.
>
> 5. The client uses the HMAC key to create a DPoP proof JWT much like the one 
> in the current draft, but signed using the HS256 key. If a "kid" field was 
> present in the challenge JWK sent by the RS then the same value MUST be used 
> in the "kid" header of this discharge JWT. It retries its original request 
> sending Authorization: DPoP <hmac-jwt> at=<access_token>.
>
> 6. The RS uses its stored ephemeral private key to derive the same HMAC key 
> and verify the DPoP discharge JWT. If it validates and all fields are correct 
> then the request is allowed.
>
> Efficient implementation trick:
> Because the client is required to copy and "kid" value from the challenge 
> JWK, the RS can preemptively carry out the ECDH key agreement immediately and 
> generate the derived HMAC key. The RS can then encrypt this derived key using 
> a local authenticated encryption key (e.g. AES-GCM) and use that encrypted 
> value as the "kid" value in the challenge (perhaps along with some context or 
> an expiry time). That way the RS only needs to decrypt this kid value rather 
> than performing the ECDH key agreement on every request. This also avoids the 
> need for the RS to store any per-client state locally.
>
> The challenge-response nature of the scheme prevents traditional replay 
> attacks in the case where a DPoP discharge JWT is accidentally leaked through 
> server logs or some other flaw, without needing to store nonces on the 
> server. Using the RS's hostname in the key derivation process prevents mitm 
> attacks in a similar way to how FIDO/WebAuthn prevents this. Most 
> importantly, once a HS256 key has been derived between a client and RS they 
> can reuse that key for multiple requests, reducing the overhead of the ECDH 
> key agreement step. Either side can decide as a matter of policy how long to 
> let this occur and when to trigger a fresh challenge-response.
>
> Because this fits within the standard HTTP authentication framework, it also 
> requires no additional CORS configuration and is relatively easy to plug in 
> to existing HTTP client libraries.
>
> The main downside of this approach to me is the fact that you can't simply 
> reuse an existing JWT library to implement it, and so it will take time for 
> client libs to develop. (Although I think this might be achievable now with 
> existing *COSE* libraries). This would increase the risk of people 
> hand-rolling solutions, rather than using well-tested libraries. On the other 
> hand, it uses fairly widely supported primitives so e.g. an implementation 
> using WebCrypto is probably only a few dozen lines of code.
>
> -- Neil
>
>
> On 31 Oct 2019, at 19:20, Brian Campbell 
> <bcampbell=40pingidentity....@dmarc.ietf.org> wrote:
>
> Hello WG,
>
> Just a quick note to let folks know that -03 of the DPoP draft was published 
> earlier today. The usual various document links are in the forwarded message 
> below and the relevant snippet from the doc history with a summary of the 
> changes is included here for convenience.
>
> Hopefully folks will have time to read the (relativity) short document before 
> the meeting(s) in Singapore where (spoiler alert) I plan to ask that the WG 
> consider adoption of the draft.
>
> Thanks,
>
>  -03
>    o  rework the text around uniqueness requirements on the jti claim in
>       the DPoP proof JWT
>    o  make tokens a bit smaller by using "htm", "htu", and "jkt" rather
>       than "http_method", "http_uri", and "jkt#S256" respectively
>    o  more explicit recommendation to use mTLS if that is available
>    o  added David Waite as co-author
>    o  editorial updates
>
> ---------- Forwarded message ---------
> From: <internet-dra...@ietf.org>
> Date: Thu, Oct 31, 2019 at 11:53 AM
> Subject: New Version Notification for draft-fett-oauth-dpop-03.txt
> To: Torsten Lodderstedt <tors...@lodderstedt.net>, Michael Jones 
> <m...@microsoft.com>, John Bradley <ve7...@ve7jtb.com>, Brian Campbell 
> <bcampb...@pingidentity.com>, David Waite <da...@alkaline-solutions.com>, 
> Daniel Fett <m...@danielfett.de>
>
>
>
> A new version of I-D, draft-fett-oauth-dpop-03.txt
> has been successfully submitted by Brian Campbell and posted to the
> IETF repository.
>
> Name:           draft-fett-oauth-dpop
> Revision:       03
> Title:          OAuth 2.0 Demonstration of Proof-of-Possession at the 
> Application Layer (DPoP)
> Document date:  2019-10-30
> Group:          Individual Submission
> Pages:          15
> URL:            
> https://www.ietf.org/internet-drafts/draft-fett-oauth-dpop-03.txt
> Status:         https://datatracker.ietf.org/doc/draft-fett-oauth-dpop/
> Htmlized:       https://tools.ietf.org/html/draft-fett-oauth-dpop-03
> Htmlized:       https://datatracker.ietf.org/doc/html/draft-fett-oauth-dpop
> Diff:           https://www.ietf.org/rfcdiff?url2=draft-fett-oauth-dpop-03
>
> Abstract:
>    This document describes a mechanism for sender-constraining OAuth 2.0
>    tokens via a proof-of-possession mechanism on the application level.
>    This mechanism allows for the detection of replay attacks with access
>    and refresh tokens.
>
>
>
>
> Please note that it may take a couple of minutes from the time of submission
> until the htmlized version and diff are available at tools.ietf.org.
>
> The IETF Secretariat
>
>
> CONFIDENTIALITY NOTICE: This email may contain confidential and privileged 
> material for the sole use of the intended recipient(s). Any review, use, 
> distribution or disclosure by others is strictly prohibited..  If you have 
> received this communication in error, please notify the sender immediately by 
> e-mail and delete the message and any file attachments from your computer. 
> Thank you._______________________________________________
> OAuth mailing list
> OAuth@ietf.org
> https://www.ietf.org/mailman/listinfo/oauth
>
>
> _______________________________________________
> OAuth mailing list
> OAuth@ietf.org
> https://www.ietf.org/mailman/listinfo/oauth

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to