* * *

Author Topic: TFPHttpClient with SSL client side certificate  (Read 600 times)

yn.coder

  • Newbie
  • Posts: 2
TFPHttpClient with SSL client side certificate
« on: June 14, 2017, 11:19:08 pm »
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]
  1.  
  2. uses  fphttpclient, ssockets, sslsockets, SysUtils;
  3.  
  4. var FClientCertificate : string;
  5.  
  6. type TSSLHelper = class helper for TObject
  7.        procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);      
  8.       end;
  9.  
  10. // Callback for setting up SSL client certificate
  11. procedure TSSLHelper.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;
  12.   out AHandler: TSocketHandler);
  13. begin
  14.   AHandler:=nil;
  15.   if UseSSL and (FClientCertificate<>'') then
  16.   begin
  17.     // Only set up client certificate if needed.
  18.     // If not, let normal fphttpclient flow create
  19.     // required socket handler
  20.     AHandler:=TSSLSocketHandler.Create;
  21.     // Example: use your own client certificate when communicating with the server:
  22.     ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;
  23.     writeln( ( AHandler as TSSLSocketHandler ).Certificate.FileName );
  24.     //( AHandler as TSSLSocketHandler ).PFX.FileName := FClientCertificate;
  25.    
  26.   end;
  27. end;
  28.  
  29. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  30. var ssl_helper : TObject;
  31. begin
  32.   Result := False;
  33.   out_Str := '';
  34.   out_Err_Msg := '';
  35.  
  36.   with TFPHttpClient.Create( nil ) do
  37.     begin
  38.       AllowRedirect := True;
  39.       FClientCertificate := Arg_Cert_Path;
  40.       if Arg_Cert_Path <> ''
  41.         then
  42.           OnGetSocketHandler:=@ssl_helper.SSLClientCertSetup;
  43.  
  44.       try
  45.         out_Str := Get( Arg_URL );
  46.         Result := True;
  47.       except
  48.         on E: Exception do
  49.           begin
  50.             out_Err_Msg := E.ClassName + '/' + E.Message;
  51.           end;
  52.       end;
  53.       Free;
  54.     end;
  55. end;
  56.  

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

  • Newbie
  • Posts: 2
Re: TFPHttpClient with SSL client side certificate
« Reply #1 on: July 01, 2017, 12:38:39 am »
After some study - it's working now.

Here is a working code
Code: Pascal  [Select]
  1.  
  2. uses fphttpclient, ssockets;
  3.  
  4. (* Get page by Arg_URL via http get.
  5.    If success then function return True, out_Str contain downloaded data, and out_Err_Msg is empty
  6.    If fail the function return False, out_Str is empty, and out_Err_Msg contain error message
  7. *)
  8. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  9.  
  10. type T_FP_HTTPS_Client = Class(TFPHTTPClient)
  11.      public
  12.       FClientCertificate : string;
  13.       procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);      
  14.     end;
  15.  
  16. uses
  17.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  18.   cthreads,
  19.   {$ENDIF}{$ENDIF}
  20.  
  21.   classes, fpopenssl, SysUtils;
  22.  
  23. // Callback for setting up SSL client certificate
  24. procedure T_FP_HTTPS_Client.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;
  25.   out AHandler: TSocketHandler);
  26. begin
  27.   AHandler:=nil;
  28.   if UseSSL and (FClientCertificate<>'') then
  29.   begin
  30.     AHandler := TSSLSocketHandler.Create;
  31.     ( AHandler as TSSLSocketHandler ).SSLType := stTLSv1;
  32.     // Example: use your own client certificate when communicating with the server:
  33.     // PEM format
  34.     ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;
  35.     ( AHandler as TSSLSocketHandler ).PrivateKey.FileName := FClientCertificate;    
  36.    
  37.   end;
  38. end;
  39.  
  40. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  41. begin
  42.   Result := False;
  43.   out_Str := '';
  44.   out_Err_Msg := '';
  45.  
  46.   with T_FP_HTTPS_Client.Create( nil ) do
  47.     begin
  48.       FClientCertificate := Arg_Cert_Path;
  49.       if Arg_Cert_Path <> ''
  50.         then
  51.           OnGetSocketHandler:=@SSLClientCertSetup;
  52.       try
  53.         out_Str := Get( Arg_URL );
  54.         Result := True;
  55.       except
  56.         on E: Exception do
  57.           begin
  58.             out_Err_Msg := E.ClassName + '/' + E.Message;
  59.           end;
  60.       end;
  61.       Free;
  62.     end;
  63. end;
  64.  
  65.  

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus