Hi Warren,
For (1), I will try to be more concrete using a variation of Microsoft's system 
on mobile for public clients - but it is a bit of a long explanation. Microsoft 
OAuth applications are assigned a random ID (for example, we'll use 1-2-3-4). 
If they use iOS, they add a redirect_uri=microsoft-ios-1-2-3-4://sign-in - that 
is a URI whose scheme consists of a prefix and the OAuth application ID. 
They'll also update their app registration to indicate that their app handles 
that scheme. For sign-in, instead of opening a normal web browser with the 
OAuth parameters, the application opens a specific Microsoft-owned native 
application (which we call "broker"), with the standard OAuth parameters. The 
broker application uses Apple native APIs to verify the native application 
identity, and then makes the requested OAuth request, augmented with the user's 
SSO state, and then returns the OAuth result to the original application on the 
registered scheme using IPC. For the OAuth request, this broker application 
supports the standard transport (query / form post url encoded, cookies for 
user SSO), but it also supports an enhanced (MITM-resistant) transport, modeled 
after OpenID Connect's "request" parameter, where the OAuth parameters are 
instead sent as a JWS, using a user key (which is generated at first sign-in), 
and the user's SSO state is similar put inside the JWS (instead of, e.g. a 
browser cookie). From a user perspective, the way this works out is that the 
user signs into that special broker application once, the first time they use 
the device, and it provides SSO to other applications. If the user is MITMed, 
the MITM can't interfere in the communication between the end-application and 
the broker application (as that's on-box) which includes the dpop_jwk, and the 
request from the broker application to the identity server is signed over in a 
JWS, so it can't change the dpop_jwk. The MITM can tell the broker that the 
user's credentials are expired (in an attempt to force the user to re-bootstrap 
- note that the bootstrap moment is inherently MITM-able), but then the user 
has to be physically present at the device and willing to enter credentials, 
and it would even be possible for the broker to indicate to the server that it 
is a re-bootstrap rather than an initial bootstrap (unless the user uninstalls 
and re-installs the broker). From my perspective then, in summary, as long as 
we are talking about off-box threats, the _earlier_ you can bind the user to a 
cryptographic binding and the more uncommon and intrusive (prompts, 
notifications, etc.) you can make true cryptographic bootstrap moments, the 
more types of these threats you can prevent. "dpop_jwk" is general purpose glue 
to connect _whatever_ binding the SSO state already has with DPoP.

This is all proprietary, but 1) we're working fixing that 2) I do think you can 
construct similar MITM-resistant profiles from things that are standard.

Re distributed systems - not sure if it's impossible, but it's certainly hard. 
My comment is more about complexity - distributed systems for single-use auth 
codes are much more complex (e.g. by lines of code, number of configurations) 
as cryptography for the same purpose. More complexity means more bugs, harder 
auditing, etc.

I'm not 100% sure I follow the comment w.r.t confidential clients. The way I 
had envisioned DPoP working on a confidential client was for e.g. an ASP.NET 
website. On first (unauthenticated request), the website would generate a CSRF 
cookie, OpenID Connect nonce, and DPoP key, store all of these in the session 
store (encrypted cookie or backend session store with session id cookie) 
together, and then communicate them all to the AS on a 302 redirect (in the 
"state", "nonce", and "dpop_jkt" parameters, respectively). When the 
authorization code response comes from the OAuth provider, the website would 
use state to locate the correct session from the store, and redeem the 
authorization code using a DPoP header signed with the DPoP key from that 
session, check the nonce in the resulting id_token, and then persist the RT and 
id_token to the session store. You mention "more than one entity" - can you get 
a bit more concrete here? Similarly, I think this should work for native 
clients as well as SPAs, except that that all this data is kept in memory 
rather than in a session store. I do take your point that dpop_jkt should be 
optional for clients - no pushback there. I worry a bit about the language you 
suggest "the dpop_jwk MUST NOT be required by AS". At Microsoft, app 
registrations have rather a lot of properties - it's possible that we might 
expose a property like "bool requiresDpopJwk" and allow the app developer to 
configure it - we do this in rather a lot of places (e.g. disabling the 
implicit flow). DPoP being an optional extension in the first place - I'm not 
sure what meaning such a statement would really have. It seems desirable in 
general for implementation to support converting bearer RTs to bound RTs on the 
fly - we'd probably always allow a DPoP proof to be provided on token if the 
incoming credential (AC or RT) is unbound.

I'm usure about generalizing the parameter. I might have proposed calling the 
parameter "dpop" and making its value exactly the "DPoP" header sent to /token 
- i.e. this is really just DPoP - but browsers with 2k URL length limits never 
quite seem to vanish entirely. So, DPoP coupling - expected, JWK coupling - 
already present in DPoP, lack of multiple - already present in DPoP, other 
needs - non-goal, lack of consistency - agree this is a shortcoming, but 
couldn't solve it. FWIW, I'm not strongly opposed to generalizing, just worried 
about adding complexity.

I don't follow w.r.t DPoP signature on the AS without assuming that AS and RS 
will adopt DPoP at the same time, which I would prefer to avoid. DPoP describes 
a downgrade path so DPoP-unaware RS can work with DPoP-aware AS under 
"Compatibility with the Bearer Authentication Scheme". If the AS doesn't check 
the DPoP signature, then a user gains no protection with a DPoP-aware AS and 
DPoP-unaware RS, instead of gaining partial protection (protection for refresh 
tokens but not access tokens). I think that partial protection is worthwhile - 
90 day refresh tokens, 1 hour / 1 day access tokens, 5 minute DPoP proofs - 1 
hour or 1 day is still a substantial gain on 90 days, even if it doesn't get 
all the way to 5 minutes.

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

Reply via email to