Search code examples
okhttpmutual-authentication

OkHttp client certificate without intermediaries


I'm trying to use okhttp to authenticate to a server.

With curl it would be done this way:

curl \
--cert certificate.cer \
--key private-key.pkcs8 \
"https://some-url"

Unfortunately, okhttp-tls appears to always expect a chain of certificates in addition to the held certificate, which isn't something I have.

heldCertificate expects the chain of certificates, in addition to the clientCertificate, contrary to the example provided in the reame:

HandshakeCertificates clientCertificates = new HandshakeCertificates.Builder()
    .addTrustedCertificate(rootCertificate.certificate())
    .heldCertificate(clientCertificate) // <--------------------
    .build();

How can I use okhttp with a single certificate and my private key?


Solution

  • heldCertificates expects a chain of intermediates that may exist between the client certificate (matching the private key) and up to but not including the root CA that the server is known to trust. So this could be left out if no other certificates are required.

    See https://square.github.io/okhttp/4.x/okhttp-tls/okhttp3.tls/-handshake-certificates/-builder/held-certificate/

    Configure the certificate chain to use when being authenticated. The first certificate is the held certificate, further certificates are included in the handshake so the peer can build a trusted path to a trusted root certificate.

    The chain should include all intermediate certificates but does not need the root certificate that we expect to be known by the remote peer. The peer already has that certificate so transmitting it is unnecessary.

    Here are some examples for using a self-signed certificate if known to be trusted already by the server, and also for switching the key used based on the host being connected to. You will need to adapt these based on your exact setup, but they should give you a starting point to test with.

    https://github.com/square/okhttp/pull/6470/files