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