cpprestsdk icon indicating copy to clipboard operation
cpprestsdk copied to clipboard

Support for client certificates

Open PBRCW opened this issue 6 years ago • 6 comments

Years ago(!) there already was a discussion on Casablanca supporting client certificates for mutual SSL connections. See here: client side certificates

Unfortunately this seems not to have changed meanwhile, Apparently Casablanca still doesn't support client certificates! :-/ AT least I can see no code inside that acts upon ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED and sets some certificate context via WINHTTP_OPTION_CLIENT_CERT_CONTEXT in the Windows flavour (dunno how to do that on POSIX but never mind).

Is there any plan to implement that any time soon or will we never see it? For my current application this is a real showstopper, as the customer demands client side certificates and mutual SSL. I could of course try to patch in something but I would feel much more comfortable if things are build in!

PBRCW avatar Jul 16 '18 16:07 PBRCW

I agree that this should be better supported by cpprest. In the meantime, there is a rather simple way to do that using web::http::client::http_client_config::set_nativehandle_options(). We use this in a productive application successfully since a while.

I didn't compile the below code, please just take it as a guideline. Also this (obviously) only works on windows. For macOS/Linux you need to do a similar trick with the ::native_handle treated as a boost::asio::ssl::context. This provides a bit higher-level ::use_certificate() and ::use_private_key() methods.

#include <Wincrypt.h>

std::vector<uint8_t>  pkcs12_data; // "... your client certificate PKCS#12 with private key goes here ...";
utility::string_t     password = "pkcs12_password"; 

web::http::client::http_client_config cfg;
cfg.set_nativehandle_options([=] (web::http::client::native_handle h) {
    CRYPT_DATA_BLOB data;
    data.cbData           = pkcs12_data.size();
    data.pbData           = reinterpret_cast<BYTE *>(pkcs12_data.data());
    HCERTSTORE hCertStore = PFXImportCertStore(&data, password.c_str(), 0);

    PCCERT_CONTEXT hContext = CertFindCertificateInStore(
        hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY,
        NULL, NULL);

    WinHttpSetOption(h, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, 
                     (LPVOID)hContext, sizeof(CERT_CONTEXT));
});

web::http::client::http_client http_client(PS("https://secure.com"), cfg);

reneme avatar Jul 31 '18 06:07 reneme

THX for replying and sorry for commenting late!

This sounds like a good approach, I will test this ASAP (but will take some time, my schedule as usual is full). The Windows-Only point is currently not an issue for me, I'm also on Windows. So if I get this working this will be OK for me and could avoid me a lot of work/research. Thums up.

PBRCW avatar Sep 17 '18 09:09 PBRCW

Cf. #199

garethsb avatar May 11 '20 11:05 garethsb

Any news on this ? Would love to see this happen...

pussinboots1992 avatar May 12 '20 19:05 pussinboots1992

Has there been any progress on this, please? I'd like to be able to have my cpprestsdk REST server authenticate a client. Any way to use the example given by @reneme in Linux? I didn't quite get the method described here.

AngmarLord avatar Jun 12 '20 12:06 AngmarLord

I would like to know how did you achieve that ? I am in the same situation. cpprestsdk does not support HTTPS seems

sahnnu avatar Aug 05 '23 18:08 sahnnu