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 which 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 <http://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 <mailto: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 
> <mailto:tors...@lodderstedt.net>>, Michael Jones <m...@microsoft.com 
> <mailto:m...@microsoft.com>>, John Bradley <ve7...@ve7jtb.com 
> <mailto:ve7...@ve7jtb..com>>, Brian Campbell <bcampb...@pingidentity.com 
> <mailto:bcampb...@pingidentity.com>>, David Waite 
> <da...@alkaline-solutions.com <mailto:da...@alkaline-solutions.com>>, Daniel 
> Fett <m...@danielfett.de <mailto: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 
> <https://www.ietf.org/internet-drafts/draft-fett-oauth-dpop-03.txt>
> Status:         https://datatracker.ietf.org/doc/draft-fett-oauth-dpop/ 
> <https://datatracker.ietf.org/doc/draft-fett-oauth-dpop/>
> Htmlized:       https://tools.ietf.org/html/draft-fett-oauth-dpop-03 
> <https://tools.ietf.org/html/draft-fett-oauth-dpop-03>
> Htmlized:       https://datatracker.ietf.org/doc/html/draft-fett-oauth-dpop 
> <https://datatracker.ietf.org/doc/html/draft-fett-oauth-dpop>
> Diff:           https://www.ietf.org/rfcdiff?url2=draft-fett-oauth-dpop-03 
> <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 
> <http://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

Reply via email to