http-extensions icon indicating copy to clipboard operation
http-extensions copied to clipboard

No defined client cert error mechanism for the origin

Open davidben opened this issue 3 years ago • 5 comments

From https://github.com/httpwg/http-extensions/issues/1927#issuecomment-1030299479, it sounds like the intent with the client certs draft is that the proxy does little to no certificate validation and punts all of it to the origin. In that case, we need to sort out how errors work...

Client cert UX is bad in part due to an impedance mismatch. In a user-facing client (like a browser), presenting a client certificate with a user-facing identity, we typically need to prompt the user to select an identity, reprompt on bad selection, etc. However, a single user-facing "session" covers multiple HTTP requests, which may then create or reuse connections depending on many factors. That means we cannot surface auth to the user at the connection- or request-. TLS session resumption and single-use sessions further complicate this.

The consequence is clients cache client certificate decisions. (Non user-facing clients tend to have credentials preconfigured, which effectively also remembers the decision.) With a cache, clients need to know when to invalidate it. Otherwise the user can never recover from selecting the wrong identity. As this is TLS-level auth, today this is done by reacting to TLS-level alerts.

draft-ietf-httpbis-client-cert-field breaks this correspondence by introducing a way to move half of TLS-level auth to HTTP. That is incompatible with today's client cert deployment assumptions, so we need to define something here. This is further complicated because the draft is shifting connection-level auth to a per-request scheme. I can see two options, but neither is very satisfying.

Proxy translates HTTP error to TLS alert

The most compatible option would be to define an HTTP error that the proxy must translate to a TLS alert on the client. The problem is TLS alerts tear down the connection, so this would be very disruptive in HTTP/2, where we may have other requests multiplexed. (The TLS-level mechanism does not have this problem because it happens in connection setup.)

Modify clients to interpret HTTP error as TLS error

The other option is to define an HTTP error and pass it through to the client. However, that means this draft is not only a proxy <-> server protocol, but also changes HTTP clients. We would need to discuss the compatibility implications.

Additionally, by introducing a brand new way to do client cert errors, we introduce some awkward quirks. Suppose the server sends a text/html resource with subresources on the same origin. Unlike HTTP auth, client cert auth applies to the whole connection. There would be no way to fetch those subresources without re-triggering the auth prompt. Perhaps we include lots of warnings that the server need to keep all its error page resources inline or on a different origin? Perhaps we say the client should ignore the response and map the HTTP error to some network-level error page?

davidben avatar Feb 04 '22 20:02 davidben

The use of post-handshake authentication is similarly fraught. I assume that you are looking to have a connection torn down if any certificate is not fit for purpose. Isn't that a bit of a blunt instrument? It makes the use of multiple certificates an interesting game: get one wrong and you lose. More so because the TLS-terminating proxy is the one that plays the game with the client the one that pays the price.

My assumption was a far more narrowly scope scenario:

  1. The proxy asks for a certificate based on some condition it arranges with the origin server (this is proprietary and not our problem).
  2. The client provides a certificate with a signature.
  3. The proxy validates the signature and passes certificate information to the origin server with any requests (again, deciding which requests to annotate thus is proprietary).
  4. The origin server takes this information and authorizes requests, or not.

That's it. The scope of the draft starts and ends at step 3 here.

The holistic problem is that clients tend to stick to their choice of client certificate in the face of these HTTP errors, only changing their mind if TLS fails (with a specific subset of possible alerts). That seems like a poor design choice; a legacy of how HTTP/1.1 works and not suited to modern uses. For starters, the provision of the certificate was successful, it's just that it was not the one that the server wanted. Tearing the connection down is too strong a response when you consider that HTTP/2 and HTTP/3 have multiple concurrent requests, some of which might be affected by a TLS alert that brings the whole session down.

I really do think that client changes are the right choice here. Clients can treat 401 (Unauthorized) as a signal that the credentials offered (zero or more certificates) are not adequate. At that point, it's probably safe to treat the cached choice of certificate as not useful for the next certificate request that comes along. Post-handshake authentication allows them to add to the pile of certificates, not jeopardizing credentials that are working.

For the proxy, if it decides that it needs to ask for more credentials from a client that doesn't do post-handshake auth'n, then a TLS alert is an option. It's probably the only realistic option as things stand today. I'd prefer GOAWAY with a code that indicates that a new connection with different credentials is appropriate.

For @b---c's benefit, I don't see any of this as affecting the client-cert-field work as long as it makes its scope clear. That work can probably just note that a proxy probably has to tear down the connection to the client after a 401 response so that the client won't fixate on the wrong certificate. Pick an appropriate alert. I don't think we need to go into defining new signaling arrangements.

I don't think that it is worth the effort of doing more to improve client certificate-based authentication, unless there is some general trend toward enabling post-handshake auth, at which point we can talk about choosing a better solution.

martinthomson avatar Feb 06 '22 23:02 martinthomson

While acknowledging that impedance mismatch and associated issues, the scope of the draft is only about conveying the client cert info and not any new error signaling or attempts at addressing the larger problems.

bc-pi avatar Feb 08 '22 21:02 bc-pi

It might be nice to still have some text to still mention that server can send back 403 status codes, etc, if they don't like the client certs. Don't add any new mechanisms, but explain that errors can happen, and there are ways to express them today.

tfpauly avatar May 31 '22 22:05 tfpauly

If the server sends back a 403 mechanism, would you expect clients to act on this? I'm not aware of any client today that uses HTTP error codes to inform client certificate selection.

davidben avatar Jun 01 '22 18:06 davidben

If a client without a client cert would see a 403, then I think it makes sense to mention that sending a 403 is what would reasonably happen here. I don't know if clients would do something automatically, but presenting the 403 error at least indicates that authentication was the problem.

tfpauly avatar Jun 01 '22 20:06 tfpauly

PR #2257 basically adds this sentence, "Access control decisions based on the client certificate (or lack thereof) can be conveyed by selecting response content as appropriate or with an HTTP 403 response, if the certificate is deemed unacceptable for the given context."

bc-pi avatar Oct 03 '22 20:10 bc-pi