Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt

"Richard Backman, Annabelle" <> Wed, 27 November 2019 01:26 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id C9A9E1200C5 for <>; Tue, 26 Nov 2019 17:26:21 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -11.8
X-Spam-Status: No, score=-11.8 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_SPF_WL=-7.5] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id MLad17SPh3NS for <>; Tue, 26 Nov 2019 17:26:15 -0800 (PST)
Received: from ( []) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 0366C1200CE for <>; Tue, 26 Nov 2019 17:26:14 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;;; q=dns/txt; s=amazon201209; t=1574817975; x=1606353975; h=from:to:cc:subject:date:message-id:references: in-reply-to:mime-version; bh=jdIaz5roVO2N/sDhf/I2qAIyU6lK5RbL30TWQ3MrMQk=; b=JTbqJuihZJ0c/Hg6Q6X3Exfk+Y96om7p5vb1uE2BOGCeizCy0BOqLDw1 /FnAATsd8FArRANC7jQAE+h8L4Q2Y9n9wm3UT7WurCLjlsjX1UN8KxRNZ M5jIrhw+GtPQ+ZL4tjOC0SoMVjr0nvjuAlOkMDBVm8Z/iVtbk2diVcGvq s=;
IronPort-SDR: Xe0lvXfuoEh8slhwps7fCRsG6GXox+RAsrAcnId5TIjkk6+5SRgD6SszBFahXvRP4BKg7O2WBY KB2d13K49rMQ==
X-IronPort-AV: E=Sophos; i="5.69,247,1571702400"; d="scan'208,217"; a="11468729"
Received: from (HELO ([]) by with ESMTP; 27 Nov 2019 01:25:58 +0000
Received: from ( []) by (Postfix) with ESMTPS id 68AA5A2291; Wed, 27 Nov 2019 01:25:56 +0000 (UTC)
Received: from ( by ( with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 27 Nov 2019 01:25:55 +0000
Received: from ( by ( with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 27 Nov 2019 01:25:55 +0000
Received: from ([]) by ([]) with mapi id 15.00.1367.000; Wed, 27 Nov 2019 01:25:54 +0000
From: "Richard Backman, Annabelle" <>
To: Neil Madden <>
CC: Brian Campbell <>, oauth <>
Thread-Topic: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt
Thread-Index: AQHVmt2iG9RAznniNkuvKQ6riy594aeSJFIAgAD4+QCAAhU5gIAA7zqAgADa3AD//9TtAIAA3uqAgAJjuACAAgu/AIABCd+AgACdmgA=
Date: Wed, 27 Nov 2019 01:25:54 +0000
Message-ID: <>
References: <> <>
In-Reply-To: <>
Accept-Language: en-US
Content-Language: en-US
user-agent: Microsoft-MacOutlook/10.1d.0.190908
x-ms-exchange-messagesentrepresentingtype: 1
x-ms-exchange-transport-fromentityheader: Hosted
x-originating-ip: []
Content-Type: multipart/alternative; boundary="_000_3D5C611E4B034A46A22BD8AC9FE0AC51amazoncom_"
MIME-Version: 1.0
Archived-At: <>
Subject: Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: OAUTH WG <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 27 Nov 2019 01:26:22 -0000

> That’s not proof of possession, that’s just verifying a MAC. PoP requires the other party (client) to provide a fresh proof that they control a key. The client isn’t using any key in this case.

I think we’re operating with slightly different definitions for PoP. My definition is something along the lines of “a possessor of a key generated (or was in possession of) this data blob at some point.” You can probably see why we’re disagreeing over whether or not PoP is fundamental. I don’t think there is any point in continuing this semantic debate. 😃

> That’s not directly attached to the access token. This means that every RS has to know about DPoP.
True, but you could avoid that by embedding the access token in the DPoP proof (similar to draft-ietf-oauth-signed-http-request) and sending that as the sole token. Technically, that’s no longer a bearer token so sending it as “Authorization: bearer <token>” would be wrong, but DPoP already commits that sin.

Also, if the AS is doing all authentication checks, then in a lot of cases the RS will need to provide the AS with additional request metadata along with the macaroon, such as the POST method used, origin (if it’s not inferable from whatever credentials the RS uses when calling the AS), request path, sender IP, client TLS certificate, token binding ID, etc. Obviously there are some caveats that don’t require this (e.g., timestamp). It remains to be seen whether the caveats required to meet DPoP’s use case fall into the former or latter category.

> Please explain how to achieve the examples I gave of layered attenuation without using macaroons.
> 1. The client adds caveats (eg exp = now+5s) to an access token and sends it to the RS. The RS creates four copies of the token with different scope constraints and sends them to four individual microservices.

For my example below:

  *   Let <at_0> be the access token obtained by the client from the AS
  *   Let JWE be a function that generates a JWE given a key and payload.
  *   Let <EKas> be the public encryption key for the AS.

<at_1> = JWE(<EKas>, { at: <at_0>, exp: … })

<at_2> = JWE(<EKas>, { at: <at_1>, scope: scope_a })
<at_3> = JWE(<EKas>, { at: <at_1>, scope: scope_b })
<at_4> = JWE(<EKas>, { at: <at_1>, scope: scope_c })
<at_5> = JWE(<EKas>, { at: <at_1>, scope: scope_d })

This pattern can be applied to the other scenarios you provided. The difference between macaroons and the above is that the former relies on chained HMACs and the latter on asymmetric crypto. You also lose the ability to inspect caveats or context that are already in the token, which may or may not be important. This is an interesting property of the macaroon pattern that I’m not sure you could replicate without basically implementing the macaroon pattern in a JWT format.

> Validation at the AS is an advantage in most cases…
Most, but not all. DPoP’s use of asymmetric signatures makes it more amenable to distributed validation in those scenarios where it is appropriate. Your RS-specific token solution is only applicable to use cases where the RS-specific tokens are appropriate and viable. This is not a restriction that exists for DPoP as written. But you are correct, there are ways to use the macaroon pattern with asymmetric crypto. If that’s your proposal then I suggest specifying that, as most of the documentation I’ve seen (including the vast majority of the paper) focuses on the HMAC approach. While I can see how one could apply the pattern with asymmetric crypto, it wasn’t clear to me from that section of the paper that my thoughts match what they were describing.

> The AS can start issuing macaroons without either clients or RS being aware….
I’m not entirely sure what value you’re trying to get at here. I think you mean that the token handling/validation logic at the RS and AS isn’t significantly different for non-constrained macaroons versus constrained macaroons, whereas it is for DPoP? True, for DPoP the RS would need to know that it should send the DPoP proof to the AS, but RSes could be configured to always include it if present in the request. On the AS side, regardless of token format the AS will need logic to validate that the sender constraint is fulfilled. This may be very simple (e.g., just a timestamp check), or as relative complex as validating a DPoP token, depending on the needs of the use case and the caveats involved.

> (Re: asymmetric crypto) That’s not a requirement, it’s a technology choice.
Fair enough, but technology choices are driven by requirements. Based on conversations I’ve had with John Bradley (and others I think?), this one in particular stems in part from the desire to keep the key locked up behind the browser’s crypto API, and not directly exposed to JavaScript. I’m somewhat skeptical of the value of this, since an attacker could just as easily call the crypto API directly, but if we see this as a requirement, then that would seem to require asymmetric crypto. However, as you noted that would not rule out the use of the macaroon pattern.

> There are plenty of existing interoperable macaroon libraries…
“Use one of these existing libraries” is not appropriate as normative text in a specification. That format needs to be explicitly defined. Caveat types (e.g., expiry, source IP, client TLS certificate, etc.) need to be defined, probably with an IANA registry. Processing instructions need to be written (e.g., what happens when caveats conflict?). Security considerations around third-party caveats need to be written.

> HMAC-SHA256 is very widely implemented (and usually securely). That’s all you need.
That’s what people said about SHA-1. Cryptographic agility is a feature, not a bug.

Again, I’m not saying we shouldn’t use macaroons, but I think you are underselling the amount of work required and overselling their value.

Annabelle Richard Backman
AWS Identity

From: Neil Madden <>
Date: Tuesday, November 26, 2019 at 12:02 AM
To: "Richard Backman, Annabelle" <>
Cc: Brian Campbell <>, oauth <>
Subject: Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt

On 26 Nov 2019, at 00:10, Richard Backman, Annabelle <> wrote:

> A client can receive a macaroon and use it like a pure bearer token if they want.
In which case it’s not sender constrained, and no different than any other symmetrically encrypted or HMAC’d bearer token.

Yes, that’s what I said. But if they want to they can attach contextual caveats. For example, they can attach htu/htm/jti claims just like in DPoP. Or they can attach a caveat that is a hash of the message and headers and get something equivalent (almost identical) to AWS HMAC signatures.

In your previous message you argued that macaroons were just PoP tokens where the key is inlined.

My position is that they can be either.

> Many ASes issue HMAC-signed access tokens already without the client doing any kind of proof of possession.
And how does the AS validate those tokens? By checking that the HMAC was generated using a key that the AS possesses and trusts.

That’s not proof of possession, that’s just verifying a MAC. PoP requires the other party (client) to provide a fresh proof that they control a key. The client isn’t using any key in this case.

In the case of macaroons, the AS checks that the chained HMAC was generated from a key that the AS issued to the client (in the form of the HMAC on the original macaroon).

Yes. You see the difference there, right?

> the attenuations (caveats) are attached directly to the access token and are verified by the AS.
This is not unique to macaroons. An RS could just as easily send the access token + DPoP proof to the AS for verification.

That’s not directly attached to the access token. This means that every RS has to know about DPoP.

> macaroon caveats can be layered.
All your other examples are just examples of this, which is not at all unique to macaroons. Sign(Key, Token + Something) is not a new concept. Macaroons are a nice pattern for doing this provided you can live with the dependency on HMAC, but they’re not the only way.

Please explain how to achieve the examples I gave of layered attenuation without using macaroons.

You elided those examples, so here they are again:

1. The client adds caveats (eg exp = now+5s) to an access token and sends it to the RS. The RS creates four copies of the token with different scope constraints and sends them to four individual microservices.

2. A gateway adds additional caveats to access tokens issued to external clients (eg limiting the expiry time or scope). These caveats are enforced even if the clients don’t go via the gateway when talking to RSes.

3. The mTLS/PoP transfer of ownership pattern I described.

Bonus points for demonstrating those things without token exchange and without the RS being able to make arbitrary token forgeries.

I’m not trying to knock macaroons here. I legitimately think they’re a neat pattern. But they are incompatible with a stated requirement<> by the DPoP authors (use an asymmetric digital signature algorithm),

That’s not a requirement, it’s a technology choice.

require validation at the AS or distribution of symmetric keys to RSes (not necessarily a problem if you’re issuing RS-specific tokens)

Validation at the AS is an advantage in most cases. The AS is more likely to get it right and this is often more scalable - an RS can typically send many more token introspection requests in parallel than they can validate public key signatures because the latter require hot CPU time. A network roundtrip within the same datacentre also typically takes less time than validating a public key sig. Validating at the AS is also the easiest way to ensure timely token revocation.

But you don’t *need* to use purely symmetric keys with macaroons. If the AS knows the RS(es) then it can encrypt a fresh symmetric key using a public key registered for that RS and add it to the token identifier.

There’s even a variant of macaroons using public key signatures (see ref in original macaroon paper).

, require additional non-trivial work to use (since they’re a pattern, not a format), and require developers to learn a new token format.

As I argued, this is incremental. The AS can start issuing macaroons without either clients or RS being aware (so long as the RSes are doing token introspection already). When the client wants to start taking advantage of macaroons they just use one of the many existing macaroon libraries (libmacaroons, jmacaroons, etc) to append caveats. The RS still doesn’t need to do anything.

If you want DPoP to use macaroons, you need to make the argument that:

  1.  The asymmetric digital signature algorithm requirement is unnecessary.

I’ve argued that multiple times in this thread.

  2.  DPoP should only address use cases where centralized validation at the AS is viable, or where RSes can be trusted with symmetric keys.

See above.

  2.  The value provided by macaroons (e.g., sender-constrained tokens without client key negotiation/registration/distribution) is worth the cost of defining the format of a DPoP macaroon, specification of algorithms used, etc., and the cognitive load on developers who now have to learn a new token format (instead of JWT, which they might already work with).

There are plenty of existing interoperable macaroon libraries - see links from . HMAC-SHA256 is very widely implemented (and usually securely). That’s all you need.

And as I said before, one of the key advantages is that clients and RSes only need to care about the format when they want to take advantage of it. They can happily treat them as pure bearer tokens until then.

Contrast with DPoP where the RS needs to potentially support 10 different public key JWS algorithms, or otherwise have some way of negotiating algorithm support with the client and/or AS. (In which case they can negotiate a key). And the client, AS, and *every* RS needs to be simultaneously upgraded to support it. (Otherwise a rogue RS can replay the access token at an RS that hasn’t been upgraded yet. Not possible with macaroons).


Annabelle Richard Backman
AWS Identity

From: Neil Madden <>
Date: Sunday, November 24, 2019 at 12:56 AM
To: "Richard Backman, Annabelle" <>
Cc: Brian Campbell <>, oauth <>
Subject: Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt

On 22 Nov 2019, at 12:26, Richard Backman, Annabelle <> wrote:
> Yes of course. But this is the HMAC *tag* not the original key.
Sure. And if the client attenuates the macaroon, it is used as a key that the client proves possession of by presenting the chained HMAC. Clients doing DPoP aren’t proving possession of the “original key” (i.e., a key used to generate the access token) either.
A way to think of this is that macaroons bridge the gap between bearer tokens and proof of possession tokens. A client can receive a macaroon and use it like a pure bearer token if they want. On the other hand they can append contextual caveats that tightly constrain a token at the point of use, like a PoP token. You can even do a full challenge-response protocol where the RS sends a challenge and the client appends it as a caveat.

> Well, you don’t have to return a key from the token endpoint for a start.
Yes, that’s what I meant by saying that it eliminates key negotiation. Though I suppose it’s more correct to say that it inlines it. The AS still provides a key, it just happens to be part of the access token.
Which helps a lot with backwards compat.
Macaroons are an interesting pattern, but not because they’re not doing PoP. Proof of possession is pretty core to the whole idea of digital signatures and HMACs.
I would argue that third party verifiability and non-repudiation are also core to digital signatures, but aren’t required or used by DPoP (and actually cause problems).

I also don’t think PoP is core to HMAC. Many ASes issue HMAC-signed access tokens already without the client doing any kind of proof of possession. They are a convenient way of minting bearer tokens.
What makes them interesting is the way they inline key distribution. Whether or not they’re applicable to DPoP depends, ultimately, on the use cases DPoP is targeting and the threats it is trying to mitigate.
There are many more interesting things than the key being inline for macaroons. For example:

- the attenuations (caveats) are attached directly to the access token and are verified by the AS. Contrast this to DPoP where every RS has to correctly validate the proof token - if any don’t then the security is significantly reduced. The AS is responsible for all security-critical checks with macaroons.

- macaroon caveats can be layered. The initial client can add some restrictions and then pass the token to an RS. That RS can then add its own restrictions when passing the token to backend services. This is a big deal for microservice architectures.

- you can add caveats at a gateway or proxy and know these will be enforced without having to inspect incoming traffic.

Even when used in combination with PoP, macaroons add unique capabilities. For example, a client can retrieve a plain bearer token from the AS and then after-the-fact bind it to its TLS client certificate by appending a x5t#S256 caveat and use that new access token for all API calls. But that client still has the original access token so they can get the certificate for a different client (eg another microservice) and create a new copy of the access token bound to that client’s certificate. It can then safely send this access token to the other client, even over a completely insecure connection. It can do this for every microservice it needs to talk to, effectively providing transfer of ownership for PoP tokens without needing to call a central token exchange service.

All this and I haven’t even begun talking about 3rd party caveats.

So the really interesting thing about macaroons is that they enable all kinds of new authorization patterns to be built without requiring a new spec for each one.


From: Neil Madden <>
Date: Friday, November 22, 2019 at 3:09 PM
To: "Richard Backman, Annabelle" <>
Cc: Brian Campbell <>, oauth <>
Subject: Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt

On 22 Nov 2019, at 01:42, Richard Backman, Annabelle <> wrote:

Macaroons are built on proof of possession. In order to add a caveat to a macaroon, the sender has to have the HMAC of the macaroon without their caveat.

Yes of course. But this is the HMAC *tag* not the original key. They can’t change anything the AS originally signed.

The distinctive property of macaroons as I see it is that they eliminate the need for key negotiation with the bearer. How much value this has over the AS just returning a symmetric key alongside the access token in the token request, I’m not sure.

Well, you don’t have to return a key from the token endpoint for a start. The client doesn’t need to create and send any additional token. The whole thing works with existing standards and technologies and can be incrementally adopted as required. If RSes do token introspection already then they need zero changes to support this.

There are key distribution challenges with that if you are doing validation at the RS, but validation at the RS using either approach means you’ve lost protection against replay by the RS. This brings us back to a core question: what threats are in scope for DPoP, and in what contexts?

Agreed, but validation at the RS is premature optimisation in many cases. And if you do need protection against that the client can even append a confirmation key as a caveat and retrospectively upgrade a bearer token to a pop token. They can even do transfer of ownership by creating copies of the original token bound to other certificates/public keys.


Annabelle Richard Backman
AWS Identity

From: OAuth <> on behalf of Neil Madden <>
Date: Friday, November 22, 2019 at 4:40 AM
To: Brian Campbell <>
Cc: oauth <>
Subject: Re: [OAUTH-WG] New Version Notification for draft-fett-oauth-dpop-03.txt

At the end of my previous email I mentioned that you can achieve some of the same aims as DPoP without needing a PoP mechanism at all. This email is that follow-up.

OAuth is agnostic about the format of access tokens and many vendors support either random string database tokens or JWTs. But there are other choices for access token format, some of which have more interesting properties. In particular, Google proposed Macaroons a few years ago as a "better cookie" [1] and I think they systematically address many of these issues when used as an access token format.

For those who aren't familiar with them, Macaroons are a bit like a HS256 JWT. They have a location (a bit like the audience in a JWT) and an identifier (an arbitrary string) and then are signed with HMAC-SHA256 using a secret key. (There's no claims set or headers - they are very minimal). In this case the secret key would be owned by the AS and used to sign macaroon-based access tokens. Validating the token would be done via token introspection at the AS.

The clever bit is that anybody at all can append "caveats" to a macaroon at any time, but nobody can remove one once added. Caveats are restrictions on the use of a token - they only ever reduce the authority granted by the token, never expand it. The AS can validate the token and all the caveats with its secret key. So, for example, if an access token was a macaroon then the client could append a caveat to reduce the scope, or reduce the expiry time, or reduce the audience, and so on.

The really clever bit is that the client can keep a copy of the original token and create restricted versions to send to different resource servers. Because HMAC is very cheap, the client can even do this before each and every request. (This is what the original paper refers to as "contextual caveats"). This means that a client can be issued a single access token from the AS with broad scope and applicable to many different RS and can then locally create restricted copies for each individual RS.

The relevance to DPoP is that the client could even append caveats equivalent to "htm" and "htu" just before sending the access token to the RS, and maybe add an "exp" for 5 seconds in the future, reduce the scope, and so on:

  newAccessToken = accessToken.withCaveats({
    exp: now + 5seconds,
    scope: "a b",
    htm: "POST",
  });, Authorization: Bearer newAccessToken);

Note that the client doesn't need anything extra here - no keys, extra tokens etc. They just have the access token and a macaroon library.

The RS will see an opaque access token, send it to the AS for introspection. The AS however, will see and validate the new caveats on the token and return an introspection response with the restricted scope and expiry time, and return the htm/htu restrictions that the RS can then enforce.

For clients this is transparent until they want to take advantage of it and then they can just use an off-the-shelf macaroon library. For the RS it is also completely transparent. All the (relatively small) complexity lives in the AS, which just has to be able to produce and verify macaroons and take caveats into account when performing token introspection - e.g. the returned scope should be the intersection of the original token scope and any scope caveats. But I don't think this would be too much effort.


-- Neil

On 21 Nov 2019, at 06:23, Brian Campbell <<>> wrote:

Yeah, suggestions and/or an MTI about algorithm support would probably be worthwhile. Perhaps also some defined means of signaling when an unsupported algorithm is used along with any other reason a DPoP is invalid or rejected.

There are a lot of tradeoffs in what claims are required and what protections are provided etc. The aim of what was chosen was to do just enough to provide some reasonable protections against reuse or use in a different context while being simple to implement and deploy.

On Wed, Nov 20, 2019 at 6:34 AM Neil Madden <<>> wrote:
Thanks for the reply, Brian.

Collecting my thoughts up here rather than responding blow by blow.

Public key signatures are simpler in some respects, more complex in others. There are currently 10 public key JWS signature schemes defined (ES256/384/512, RS256/384/512, PS256/384/512, EdDSA) - does an RS potentially have to support them all? If not, how do they negotiate algorithm support with the client?

On the other hand, the ECDH scheme I proposed can be implemented by adapting an existing ECDH-ES encryption support in a JWT library. For example, I discovered while playing with this that our own internal library can implement the full flow I described entirely via the existing public API [1], so it's not necessarily as complex as it first looks. I even knocked up a from-scratch implementation in WebCrypto (JavaScript) without too much code [2].

But I admit that using an existing JWT library to sign a JWT with an existing algorithm is even easier, and that counts for a lot. Perhaps we can make concrete suggestions/requirements about algorithm support? e.g. "The RS MUST support RS256 and SHOULD support EdDSA. Other algorithms MAY be supported."

With regards to replay protection, I think there are at least two reasonable positions:

1. We assume that TLS is secure and don't try to defend against any compromise at that level. (Clearly none of the TLS-based PoP mechanisms survive if TLS is compromised, by definition). In this case the main attack to defend against is a malicious RS replaying the access token elsewhere. Simply signing the origin of the RS would be enough to prevent this attack, while letting the client reuse the same JWT for many requests (and the RS to cache the JWT validation). None of "jti", "htu", or "htm" seem relevant to this model.

2. We don't assume that TLS is secure (or it's not fully end-to-end) and try to provide some defense in depth against a MitM attacker replaying a token against the same RS. There is a graduated series of steps you can take here, depending on how much you want to prevent this:
   a. The DPoP token can be replayed for arbitrary requests to the same RS but has a short time limit (e.g., exp claim or RS-enforced max lifetime from iat)
   b. The DPoP token can be replayed for the same request (htu/htm claims)
   c. The DPoP token can't be replayed at all - either because of jti blacklisting on the RS or a challenge-response protocol on each request.

(There are also variants such as including a hash of the request body/headers, or encoding an ETag into the JWT).

I think either are reasonable design goals, but aiming for 2 adds more value. I think aiming for 2a is a reasonable default baseline that allows the client to reuse a DPoP token for a few requests, reducing the cost of the signature (and the RS can cache the validated JWT). Support for 2b or 2c can then be listed as optional additions.

PS - 2a/2b can be achieved without PoP. I'll save that for another email in the next few days though.


-- Neil

On 19 Nov 2019, at 07:43, Brian Campbell <<>> wrote:

On Thu, Nov 14, 2019 at 7:20 PM Neil Madden <<>> 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.

Thanks Neil. And sorry to hear that you won't be in Singapore. This kind of stuff is definitely more easily discussed in person (for me anyway). But I'll try and comment on your comments here as best I can. I also plan to also mention them in the Wednesday and/or Thursday presentation.

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.

It is admittedly a bit loose and I agree it'd be good to tighten it up. But part of why it's loose is that it tries to offer some protections for all those scenarios and more such as a general lost/stolen token. It's effectively trying to provide as many of the same types of protections/assurances that you'd get with TLS based PoP mechanisms (like OAuth MTLS or Token binding) to the extent that can be done at the HTTP application layer. Which can't realistically be exactly the same but can maybe be kinda close while actually being accessible and implementable because it's all done at the application layer. There are trade-offs, of course, and the document writers have endeavored to find a good balance in the trade-off decisions we've made. But that doesn't mean they are necessarily the right decisions or are closed to discussion. To the casual reader I would say that it turns out that getting an appropriate simple audience claim into an access token isn't nearly as simple as it might seem. And while it will prevent RS to RS replay (as long as both RSs aren't legit audiences) it doesn't help with preventing the use of tokens stolen or leaked by other means (including for refresh tokens issued to public clients).

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.

It's maybe not stated in the draft but this kind of thing is among the objectives (in my mind anyway).

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

Yes, asymmetric is more processing intensive than symmetric. But if you take away the distributed replay check (see next response), it will scale out just fine. I'm not so sure latency is a real issue here - while these operations are an order of magnitude slower we're still talking about times that are not perceptible to a human. CPU usage/cost is a part of a trade-off for the simplicity afforded by public/private keys.  And it is significantly simpler. The design you sketched out is admittedly quite clever but it's not even in the same ballpark with respect to complexity. And, as you pointed out, the other suggestion around symmetric keys has rather different security properties while still adding complexity. Adding symmetric key support isn't something that can just be added on easily.

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.

The actual value of replay checking on jti is somewhat questionable. The DPoP JWT only transits between client and server so a TLS MITM is likely needed to steal a DPoP JWT. But we are assuming TLS works here. And an active MITM could thwart this check by just being first to present DPoP JWT. I think the jti check made its way into the draft mostly because it seemed like something was needed to try and bring it closer to the TLS PoP models. Being aware of the scalability concerns, I did endeavor to write the text in such a way so as to leave some wiggle room in implementations/deployments with text like '"jti" SHOULD be used by the server for replay detection and prevention` and [ensure that] 'within a reasonable consideration of accuracy and resource utilization, a JWT with the same "jti" value has not been received previously'. The idea being that using something eventually consistent or even local only to the runtime instance would be permissible. Perhaps that allowance and the rational could be made more clear? Or would you suggest to do away with the jti replay stuff al? Or something else?

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.

Feels really minor. I mean, we could try to roll everything up under one header. But it does seem unwarranted and would complicate things - at least in the model we've got now where the proof is sent the same way ono all types of requests.

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. "<>"). 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 <<>> 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.


   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: <<>>
Date: Thu, Oct 31, 2019 at 11:53 AM
Subject: New Version Notification for draft-fett-oauth-dpop-03.txt
To: Torsten Lodderstedt <<>>, Michael Jones <<>>, John Bradley <<>>, Brian Campbell <<>>, David Waite <<>>, Daniel Fett <<>>

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

   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<>.

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<>

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.

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.