87

I am trying to call a service with mutual TLS using the Curl command.

Curl command used:

curl -k -vvvv \
  --request POST \
  --header "Content-Type: application/json" \
  --cert client.pem:password \
  --key key.pem \
  "https://test.com:8443/testing"

I am trying to find out the following:

  1. What is the HTTP request header that I should be looking at the server-side to pull out the client certificate from the HTTP request?

  2. If I cannot pull out the client certificate on the server side from the HTTP request, can I add a custom request header in the HTTP request and send the client certificate as a value of that custom header? It would be great if someone could provide an example of this approach.

Akshay Hiremath
  • 950
  • 2
  • 12
  • 34
sunsin1985
  • 2,437
  • 5
  • 22
  • 27

2 Answers2

202

This is how I did it:

curl -v \
  --key ./admin-key.pem \
  --cert ./admin.pem \
  https://xxxx/api/v1/
falsePockets
  • 3,826
  • 4
  • 18
  • 37
reachlin
  • 4,516
  • 7
  • 18
  • 23
  • 3
    Is the `cacert` required here? That doesn't really help a server authenticate the client's `cert/key` pair; the server must already have the relevant `cacert` (otherwise, providing the key, cert, and cacert is no different than a self-signed cert, which isn't providing any authentication, right?). My guess is that it's required for _server_ authentication though? Mainly asking because I'm not sure I understand it all and wanna know if I've misunderstood something! – dwanderson Nov 18 '19 at 19:06
  • 2
    The cacert might be required if there are CA's in between the CA the webserver uses and the client certificate. if for example there is a company X Ltd that has their "X Ltd CA", which has signed CA's for "X - IT Dept" and "X - IT Dept" has signed 10 certificates using the underlying CA for "X Ltd CA", the client needs to send the "X - IT Dept" CA if the server doesn't have it. – Rudy Broersma Jan 16 '20 at 15:43
  • 4
    I used this answer to curl an API that requires Mutual TLS authentication to connect and it worked like a charm. I didn't need the `cacert` parameter in my case. – Rob Carpenter Apr 07 '20 at 04:49
  • The author has already worked this out (`--cert` and `--key` options are present in the question). The question is clear: how to read the certificate data *on the server side*. This response does not address the question. – frasertweedale Jul 12 '21 at 03:55
35

A client sends a TLS certificate when mutual TLS is used.

In the mutual TLS handshake, the TLS client certificates are not sent in HTTP headers. They are transmitted by the client as part of the TLS messages exchanged during the handshake, and the server validates the client certificate during the handshake. Broadly there are two parts to the mTLS handshake, the client validates and accepts the server certificate and the server validates and accepts the client certificate.

If the client certificate is accepted, most web servers can be configured to add headers for transmitting the certificate or information contained on the certificate to the application. Environment variables are populated with certificate information in Apache and Nginx which can be used in other directives for setting headers.

As an example of this approach, the following Nginx config snippet will validate a client certificate, and then set the SSL_CLIENT_CERT header to pass the entire certificate to the application. This will only be set when then certificate was successfully validated, so the application can then parse the certificate and rely on the information it bears.

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/chainedcert.pem;  # server certificate
    ssl_certificate_key /path/to/key;          # server key

    ssl_client_certificate /path/to/ca.pem;    # client CA
    ssl_verify_client on;
    proxy_set_header SSL_CLIENT_CERT $ssl_client_cert;

    location / {
        proxy_pass http://localhost:3000;
    }
}
Akshay Hiremath
  • 950
  • 2
  • 12
  • 34
frasertweedale
  • 5,424
  • 3
  • 26
  • 38
  • 19
    he is trying to send the certificate and asking for how to. Answer is explaining how server processes it. Where is the part that explains what is the right way? – Akshay Hiremath Oct 07 '20 at 16:57
  • 1
    The author asked how to read the certificate *on the server side*. My answer explains that the certificate is not transmitted (from client to server) via HTTP header, but that the HTTP server can expose it to the application. And I gave an example nginx configuration to do that. – frasertweedale Jul 12 '21 at 03:51
  • I rephrased and cleaned up the question, now this answer is more suitable. I rephrased the question because the person who asked the question has accepted your answer. – Akshay Hiremath Jul 12 '21 at 20:59