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

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

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

–
Annabelle Richard Backman
AWS Identity


From: Neil Madden <neil.mad...@forgerock.com>
Date: Friday, November 22, 2019 at 3:09 PM
To: "Richard Backman, Annabelle" <richa...@amazon.com>
Cc: Brian Campbell <bcampb...@pingidentity.com>, oauth <oauth@ietf.org>
Subject: Re: [OAUTH-WG] New Version Notification for 
draft-fett-oauth-dpop-03.txt

On 22 Nov 2019, at 01:42, Richard Backman, Annabelle <richa...@amazon.com> 
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.

Neil




–
Annabelle Richard Backman
AWS Identity


From: OAuth <oauth-boun...@ietf.org> on behalf of Neil Madden 
<neil.mad...@forgerock.com>
Date: Friday, November 22, 2019 at 4:40 AM
To: Brian Campbell <bcampb...@pingidentity.com>
Cc: oauth <oauth@ietf.org>
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",
    ....
  });
  httpClient.post(data, 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.

[1]: https://ai.google/research/pubs/pub41892

-- Neil



On 21 Nov 2019, at 06:23, Brian Campbell 
<bcampb...@pingidentity.com<mailto:bcampb...@pingidentity.com>> 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 
<neil.mad...@forgerock.com<mailto:neil.mad...@forgerock.com>> 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.

[1]: https://gist.github.com/NeilMadden/685ea66fb79d37a50c2310f853bd9496
[2]: https://gist.github.com/NeilMadden/70e1b232a3b273de02ed731eb36ec4a7


-- Neil



On 19 Nov 2019, at 07:43, Brian Campbell 
<bcampb...@pingidentity.com<mailto:bcampb...@pingidentity.com>> wrote:


On Thu, Nov 14, 2019 at 7:20 PM Neil Madden 
<neil.mad...@forgerock.com<mailto: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.

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. "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<mailto: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
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<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<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth


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.

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

Reply via email to