SSL with a financial company lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Douglas Medeiros · 2017-12-13 12:12 Hello, We are developing a solution that needs consume an REST API from a Brazilian credit card company. I tried connect to this rest api with FPHttpClient and now with HttpSend (Synapse package) with no success. Every request return http error 403 (Access Denied), but I'm sending the correct information. I think . Bellow is my code with synapse: 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 // This method prepare HTTPSend object to be usedfunction TRedeBO.ReturnHttpClient(AContent: Boolean): THTTPSend;var  HttpClient : THTTPSend;begin  HttpClient := THTTPSend.Create;   if AContent then    HttpClient.MimeType := 'Application/json'  else    HttpClient.MimeType := EmptyStr;   HttpClient.KeepAlive := False;   HttpClient.UserName := FPVNumber;  HttpClient.Password := FToken;  HttpClient.Protocol := '1.1';   Result := HttpClient;end;   function TRedeBO.Pay(AValue: Double; out ATransactionID: String; out ARequestJSON: String; out AResponseJSON: String): Boolean;var  JSON        : String        ;  CreditCardDTO : TCreditCardDTO;  Response    : String        ;  HttpClient    : THTTPSend     ;  ID            : String        ;  Serializer    : ISerializer   ;  ReturnIO      : TRedeReturnIO ;begin  try    Result        := False;    ReturnIO      := nil;    Serializer    := GetAnObject(ISerializer) as ISerializer;    HttpClient    := ReturnHttpClient(True);    CreditCardDTO := LoadCreditCard;     ID := 'c201709011647';     JSON := '{'+          '"reference": "' + ID + '",'+            '"amount": "' + FormatValue(AValue) + '",'+            '"cardNumber": "' + CreditCardDTO.Card_Number + '",'+            '"expirationMonth": "' + FormatMonth(CreditCardDTO.Card_Expiration) + '",'+            '"expirationYear": "' + FormatYear(CreditCardDTO.Card_Expiration) + '",'+            '"cardHolderName": "' + CreditCardDTO.Holder_Name + '",'+            '"securityCode" : "' + CreditCardDTO.CVV +  '"}';   WriteStrToStream(HttpClient.Document, JSON);    HttpClient.HTTPMethod('POST', REDE_URL + 'transactions');     ATransactionID := EmptyStr;    ARequestJSON   := JSON    ;    AResponseJSON  := ReadStrFromStream(HttpClient.Document, HttpClient.Document.Size);     if HttpClient.ResultCode <> 200 then;    Exit;       // When response code is 200, other codes are executed below here, but is no importante for this caseend; But if I make a test with curl is OK . curl -u user:password --request POST   --url https://api.userede.com.br/desenvolvedores/v1/transactions  --header 'Content-Type: application/json'   --data '{ "reference": "c201709011644","amount": "100", "cardNumber": "5448280000000007", "expirationMonth": "12", "expirationYear": "2018" }' I have used web api's with free pascal during a long time with no problem and because this I made this test with other webapi that I use every day and found this diferences on curl verbose output: // Send Grid API with no problems with freepascal. (curl verbose output) curl --request POST   --url https://api.sendgrid.com/v3/mail/send    --header 'Content-Type: application/json'   --data '{"personalizations": [{"to": [{"email": "rodrigo@vocepede.com.br"}]}],"from": {"email": "douglas@vocepede.com.br"},"subject": "Sending with SendGrid is Fun","content": [{"type": "text/plain", "value": "and easy to do anywhere, even with cURL"}]}' -v Note: Unnecessary use of -X or --request, POST is already inferred. *   Trying 108.168.183.162... * TCP_NODELAY set * Connected to api.sendgrid.com (108.168.183.162) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: *   CAfile: /etc/ssl/cert.pem   CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * NPN, negotiated HTTP1.1 * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Unknown (67): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Client hello (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 * ALPN, server did not agree to a protocol * Server certificate: *  subject: OU=Domain Control Validated; CN=*.sendgrid.com *  start date: Feb 28 17:29:00 2017 GMT *  expire date: Feb 28 17:29:00 2019 GMT *  subjectAltName: host "api.sendgrid.com" matched cert's "*.sendgrid.com" *  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2 *  SSL certificate verify ok. > POST /v3/mail/send HTTP/1.1 > Host: api.sendgrid.com > User-Agent: curl/7.54.0 > Accept: */* > Authorization: Bearer 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 > Content-Type: application/json > Content-Length: 245 > * upload completely sent off: 245 out of 245 bytes < HTTP/1.1 202 Accepted < Server: nginx < Date: Wed, 13 Dec 2017 12:03:43 GMT < Content-Type: text/plain; charset=utf-8 < Content-Length: 0 < Connection: keep-alive < X-Message-Id: oNaIgidISuWS2OO3YNCXFw < Access-Control-Allow-Origin: https://sendgrid.api-docs.io < Access-Control-Allow-Methods: POST < Access-Control-Allow-Headers: Authorization, Content-Type, On- behalf-of, x-sg-elas-acl < Access-Control-Max-Age: 600 < X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html Financial company with problems on freepascal (curl output) curl --request POST -u username:password  --url https://api.userede.com.br/desenvolvedores/v1/transactions  --header 'Content-Type: application/json' -v --data '{ "reference": "c201709011649","amount": "100", "cardNumber": "5448280000000007", "expirationMonth": "12", "expirationYear": "2018" }' -v Note: Unnecessary use of -X or --request, POST is already inferred. *   Trying 23.77.114.253... * TCP_NODELAY set * Connected to api.userede.com.br (23.77.114.253) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: *   CAfile: /etc/ssl/cert.pem   CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Client hello (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: *  subject: C=BR; ST=Sao Paulo; L=Barueri; O=Redecard S/A; CN=ecommerce.userede.com.br *  start date: Sep 15 00:00:00 2017 GMT *  expire date: Sep 15 23:59:59 2018 GMT *  subjectAltName: host "api.userede.com.br" matched cert's "*.userede.com.br" *  issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 Secure Server CA - G4 *  SSL certificate verify ok. > POST /desenvolvedores/v1/transactions HTTP/1.1 > Host: api.userede.com.br > User-Agent: curl/7.54.0 > Accept: */* > Authorization: Basic MTAwMDAwOTQ6ZmY0MDJkNTVkYjBiNDhlNWIyZDQzNjIwNzM5NTM4ZDg= > Content-Type: application/json > Content-Length: 133 > * upload completely sent off: 133 out of 133 bytes < HTTP/1.1 422 Unprocessable Entity < Content-Type: application/json; charset=utf-8 < Max-Forwards: 19 < Server: Microsoft-IIS/7.5 < Server: Microsoft-IIS/7.5 < X-AspNet-Version: 4.0.30319 < X-CorrelationID: Id-ee17315a212c8cb132662c7e 0; Id- ee17315a95a083a97cc8c66e 0 < X-Powered-By: ASP.NET < X-Powered-By: ASP.NET < Content-Length: 77 < Expires: Wed, 13 Dec 2017 12:07:11 GMT < Cache-Control: max-age=0, no-cache, no-store < Pragma: no-cache < Date: Wed, 13 Dec 2017 12:07:11 GMT < Connection: close < * Closing connection 0 * TLSv1.2 (OUT), TLS alert, Client hello (1): {"returnCode":"42","returnMessage":"Reference: Order number already exists."} In my opinion the diference is SSL cipher. There is no support for this on free pascal? There are any option for me? I'm using Lazarus 1.6.4 with FPC 3.0.2 (all on 64 bits version). SO: Windows 10, I didn't try on Linux yet. Sorry for my poor english. Thanks ---------------------------------------------------------------------- Almir.Bispo · 2017-12-13 12:24 Hi Medeiros.I'm brazilian too. You must use Synapse lib and need you use the ssl unit. Http request does'n work without ssl unit class. To know my projeto: http://adltecnologia.blogspot.com.br ---------------------------------------------------------------------- Douglas Medeiros · 2017-12-13 12:36 Quote from: Almir.Bispo on December 13, 2017, 01:24:09 pmHi Medeiros.I'm brazilian too. You must use Synapse lib and need you use the ssl unit. Http request does'n work without ssl unit class. To know my projeto: http://adltecnologia.blogspot.com.br Hi, thanks for your help, I'm a pascal lover and try make all with pascal I put this units on my uses clause: httpsend, ssl_openssl, ssl_openssl_lib, sslsockets. But the answer of server still the same. Are this the correct units? ---------------------------------------------------------------------- turrican · 2017-12-13 12:59 403 is an HTTP error not a certificate error. Can be an UserAgent restriction on the server. Switch UserAgent header on the client to a generic one : http://www.useragentstring.com/pages/useragentstring.php ---------------------------------------------------------------------- Zoran · 2017-12-13 13:15 Quote from: Almir.Bispo on December 13, 2017, 01:24:09 pmYou must use Synapse lib and need you use the ssl unit. But according to wiki, FPHttpclient also supports ssl, see http://wiki.freepascal.org/fphttpclient#HTTPS_.28TLS.2FSSL.29. ---------------------------------------------------------------------- tudi_x · 2017-12-13 13:38 are you using the libraries from the below? https://indy.fulgan.com/SSL/openssl-1.0.2l-x64_86-win64.zip ---------------------------------------------------------------------- Thaddy · 2017-12-13 13:49 Note that current openssl for FPC can be configured to use TLS1.2 as a minimum, but the code is not - yet - configured to ignore anything below TLS1.2. SSL 2.0, SSL 3.0, TLS 1.0 and TLS 1.1 are deprecated in modern browsers. You should force TSL 1.2. Some browsers, but not all, allow a fall-back to just SSL 2.0. Everything in between is deemed insecure. For a banking application you should force TLS 1.2 and do not allow fall-backs. Current OpenSSL does not even have the insecure protocols, unless you compile it yourself. ---------------------------------------------------------------------- Douglas Medeiros · 2017-12-13 14:21 Hello I discovered the problem, I just change de header of content-type from: HttpClient.MimeType := 'Application/json' to HttpClient.MimeType := 'application/json' ---------------------------------------------------------------------- Douglas Medeiros · 2017-12-13 14:23 Quote from: Thaddy on December 13, 2017, 02:49:20 pmNote that current openssl for FPC can be configured to use TLS1.2 as a minimum, but the code is not - yet - configured to ignore anything below TLS1.2. SSL 2.0, SSL 3.0, TLS 1.0 and TLS 1.1 are deprecated in modern browsers. You should force TSL 1.2. Some browsers, but not all, allow a fall-back to just SSL 2.0. Everything in between is deemed insecure. For a banking application you should force TLS 1.2 and do not allow fall-backs. Current OpenSSL does not even have the insecure protocols, unless you compile it yourself. Could you help-me to change it? I don't know how to do it. ---------------------------------------------------------------------- turrican · 2017-12-13 14:30 Quote from: Douglas Medeiros on December 13, 2017, 03:21:31 pmHello I discovered the problem, I just change de header of content-type from: HttpClient.MimeType := 'Application/json' to HttpClient.MimeType := 'application/json' Same thing as THTTPSend.Useragent . You have to watch invalid headers on your request.