TFPHttpClient with SSL client side certificate lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- yn.coder · 2017-06-14 21:19 Hello! I've use TFPHttpClient for https requests. It's working good, except I can't run it with SSL client side certificates. I follow this sample http://wiki.lazarus.freepascal.org/fphttpclient#HTTPS_.28TLS.2FSSL.29 and wrote my code. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  uses  fphttpclient, ssockets, sslsockets, SysUtils; var FClientCertificate : string;  type TSSLHelper = class helper for TObject       procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);            end; // Callback for setting up SSL client certificateprocedure TSSLHelper.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;  out AHandler: TSocketHandler);begin  AHandler:=nil;  if UseSSL and (FClientCertificate<>'') then  begin    // Only set up client certificate if needed.    // If not, let normal fphttpclient flow create    // required socket handler    AHandler:=TSSLSocketHandler.Create;    // Example: use your own client certificate when communicating with the server:    ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;    writeln( ( AHandler as TSSLSocketHandler ).Certificate.FileName );    //( AHandler as TSSLSocketHandler ).PFX.FileName := FClientCertificate;      end;end;  function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;var ssl_helper : TObject;begin  Result := False;  out_Str := '';  out_Err_Msg := '';    with TFPHttpClient.Create( nil ) do    begin      AllowRedirect := True;    FClientCertificate := Arg_Cert_Path;      if Arg_Cert_Path <> ''       then          OnGetSocketHandler:=@ssl_helper.SSLClientCertSetup;       try        out_Str := Get( Arg_URL );        Result := True;      except        on E: Exception do          begin             out_Err_Msg := E.ClassName + '/' + E.Message;          end;      end;      Free;    end;end;  I've test it with scriptjunkie site https://www.scriptjunkie.us/2013/11/adding-easy-ssl-client- authentication-to-any-webapp/#Instructions, where anybody could generate a ssl certificate and test the auth. If I generate a certificate for browser and go to test page https://www.scriptjunkie.us/auth/verifycert - it's working. If I export a certificate from browser to crt, pem or p12 certificate file and use it with my code - I've got only Uh oh! You don't seem to be using a cert.. How to use cert file? What format of cert to use? ---------------------------------------------------------------------- yn.coder · 2017-06-30 22:38 After some study - it's working now. Here is a working code Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  uses fphttpclient, ssockets; (* Get page by Arg_URL via http get.   If success then function return True, out_Str contain downloaded data, and out_Err_Msg is empty   If fail the function return False, out_Str is empty, and out_Err_Msg contain error message*)function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean; type T_FP_HTTPS_Client = Class(TFPHTTPClient)     public      FClientCertificate : string;    procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);          end; uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}    classes, fpopenssl, SysUtils;  // Callback for setting up SSL client certificateprocedure T_FP_HTTPS_Client.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;  out AHandler: TSocketHandler);begin  AHandler:=nil;  if UseSSL and (FClientCertificate<>'') then  begin    AHandler := TSSLSocketHandler.Create;    ( AHandler as TSSLSocketHandler ).SSLType := stTLSv1;    // Example: use your own client certificate when communicating with the server:    // PEM format    ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;    ( AHandler as TSSLSocketHandler ).PrivateKey.FileName := FClientCertificate;          end;end;  function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;begin  Result := False;  out_Str := '';  out_Err_Msg := '';    with T_FP_HTTPS_Client.Create( nil ) do    begin      FClientCertificate := Arg_Cert_Path;      if Arg_Cert_Path <> ''         then          OnGetSocketHandler:=@SSLClientCertSetup;      try        out_Str := Get( Arg_URL );        Result := True;      except        on E: Exception do          begin             out_Err_Msg := E.ClassName + '/' + E.Message;          end;      end;      Free;    end;end; ---------------------------------------------------------------------- andersonscinfo · 2021-02-26 13:17 I have a very similar problem, but I can't even create the socket, the message "Cannot create a X509 certificate without SLL support" appears. Could you give me any tips on openssl versions, I'm using lazarus 2.0.10 with fpc 3.2 on windows, lazarus 32bits. ---------------------------------------------------------------------- Thaddy · 2021-02-26 13:33 Looks to me that it is just a case of a deprecated protocol. You need to specify TLS1.1 or higher. Better still 1.3 or higher. Don't get fooled by the SSL name of the libraries. SSL as a protocol is unsafe and removed from OpenSsl.  You need to use TLS 1.1 or higher which are supported by most libraries including openssl. ---------------------------------------------------------------------- andersonscinfo · 2021-02-26 13:43 before I can inform you the protocol the error is already showing up, I will send an example, maybe you can help me. exemple: http://activelinux.info/tmp/lazarus.zip ---------------------------------------------------------------------- PascalDragon · 2021-02-26 14:09 You need to use unit OpenSSLSockets as well. The unit SSLSockets only provides the general SSL support independent of the SSL provider (OpenSSL, GNU SSL, etc.). ---------------------------------------------------------------------- andersonscinfo · 2021-02-26 16:33 cool, I changed        AHandler := TSSLSocketHandler.Create; that's why     AHandler :=TOpenSSLSocketHandler.create;  now it's giving other errors, but I think it involves the webservice, thanks for now, I'll be back here to post the complete example working as soon as I can. thanks ---------------------------------------------------------------------- andersonscinfo · 2021-02-26 16:41 thank you very much guys, it worked here, I had to make only one adjustment to work according to my need, this is in the image attached the two changes, one is the certificate that needed to be a ".crt" and the other was not to set the type. ---------------------------------------------------------------------- vicvegax · 2021-11-23 23:22 tnks... worked great... I used the changes o make a correction on LazAutoUpdate