Are there any recommendations about how to supply a client certificate to an HTTP request?
I am trying to implement a TXDataClient, which internally uses Sparkle's HTTPClient, that connects to an XData server, which is behind a proxy that requires a client certificate for authentication.
Here is a starting code you can use to accomplish that:
var
httpClient: THttpClient;
httpEngine: TWinHttpEngine;
httpRequest: THttpRequest;
httpResponse: THttpResponse;
Store: HCERTSTORE;
Cert: PCERT_CONTEXT;
begin
httpClient := THttpClient.Create;
// Open the ''Personal'' SSL certificate store for the local machine and locate the required client-side certificate
Cert := nil;
Store := CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, PChar(''MY''));
if (Store <> nil) then
Cert := CertFindCertificateInStore(Store, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, PChar(''mycertsubject''), nil);
// If a valid certificate was found then OK to create and send the HTTP request
if (Cert <> nil) then
begin
// Setup HTTP request properties
httpRequest := httpClient.CreateRequest;
...
// Use ''BeforeWinHttpSendRequest'' event to set any HTTP request properties such as client-side SSL certificate
httpEngine := TWinHttpEngine(httpClient.Engine);
httpEngine.BeforeWinHttpSendRequest :=
procedure (Req: HINTERNET)
begin
WinHttpCheck(WinHttpSetOption(Req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, Cert, SizeOf(CERT_CONTEXT)));
end;
// Execute HTTP request
httpResponse := httpClient.Send(httpRequest);
end;
Thanks, Wagner, much appreciated!
I already noticed the "Engine abstraction", but didn't dig through the code to fully understand it. Your example code makes this clear!
I will probably test this tomorrow, and will report back.