HTTP Client Certificates in Sparkle/XDataClient

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.

This is on Windows for now.

Hi @Olaf_Monien,

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.

1 Like