A way to ask for a client's certificate
Hello,
I'd like to implement a HTTPS server with webid-based authentication, as described here: https://www.w3.org/2005/Incubator/webid/spec/tls/#the-webid-authentication-protocol
In this protocol, when a request is received by the server for a protected resource, the server asks the client browser for a certificate which contains a webid, which can be used in ACLs of protected resources.
So I'm looking for a way to ask such a certificate to the client. This is possible with the TLS protocol: https://www.w3.org/2005/Incubator/webid/spec/tls/#requesting-the-client-certificate with a CertificateRequest message .
Is there a way to make such a request to the client and retrieve the certificate ? I guess this requires having access to the underlying TLS connection. It would also be useful to be able to access the client certificate of the underlying tls connection if it was provided at connection time, since command-line client may do this.
cc @hannesm .
Thanks!
I cannot speak about cohttp since I don't know the codebase. OCaml-TLS supports client authentication:
You'll have to use the accept_ext function to pass a Tls.Config.server (instantiation via server), which receives an X509.Authenticator.a (there are some constructors in the X509_lwt module.
Once a session is established, you can retrieve the epoch (epoch_data type), which contains the peer_certificate and peer_certificate_chain.
An example which requests a client certificate, but neither validates it, nor use any information of the received client certificate is here.
Thanks for the pointers. Let's suppose we have a way to get the SSL connection (channels) from the HTTP request handler, and this connection was created with no authentication from the client (no peer_certificate provided at connection time). Is there a way for the server to ask the client to authenticate, i.e. send peer certificate or update epoch data ?
You can reconfigure the server (to have an Authenticator.a) and renegotiate to receive a client certificate. When doing this, keep in mind that reneg is by default false. I guess a missing piece in the puzzle is how to exchange the config in the current session t (in Tls_lwt). I'll keep that in mind and implement it soon (I somewhere have a branch with this feature).
Ok, thanks, I'm waiting for this feature, then :)
@zoggy I suspect there's more code to be written in cohttp and conduit to support client auth... you can pretend that this hook exists, which replaces the authenticator within a given t, and push forward with required cohttp&conduit changes...
Indeed supporting client auth in conduit and cohttp is not that simple, so by now I just copy-pasted code from conduit and cohttp to instanciate a lwt unix cohttp server where IO.conn is not a conduit flow anymore but a Tls_lwt.Unix.t . This is just for some tests right now (implementing a SOLID server) so I keep waiting :)
I think this is similar/relatable to https://github.com/mirage/ocaml-cohttp/issues/479