Http web request SSL validation

You may need to communicate with external web service in Nav, such as API for Ecommerce, Logistic tracking or whatever.
To do that, you can inspire from codeunit 1297 for Rest API and codeunit 1290 for Soap API.

I find out that Http Web request component from Microsoft .Net do not allow any communications with web service using SSL self-signed certificat, for security concern, un like eg PostMan (if you’re having an error in Nav containing something like “certificate is invalid” when trying to send http request, that’s it).

Certificat can be considered as self-signed in some case such as DNS issue on localhost, low cost emetor, but can also be falsified certificate. But in case you do trust or own the certificate, you should of course able to bypass this verification.

Microsoft explain how to intercept the certificate validation in HttpWebRequest component in following video  :

https://www.youtube.com/watch?v=NW_ZiW6J790

I’ve created the .Net DLL to force all SSL validation on System.Net.HttpWebRequest, as they show :

HttpCertificateValidator.dll.zip
HttpCertificateValidator Source.zip

Please use with needed requests and if you trust the endpoint.

SSL certificat validation are important and should not be ignored when you connect with external source. It is easy to falsify a certificate, the attacker can then redirect all the data feed to himself poofing original destination.

How to use it :

1.Copy HttpCerticiateValidator.dll in the Nav service Add-in folder (will be used server side).

2.Restart Nav service

2.In C/AL declare a DotNet variable Assembly in “Dynamic NAV” then “HttpCertificateValidator” and pick the class “HttpCerticiateValidator.RequestValidator”

Before sending the request (HttpWebRequest.Getresponse) call the Request validator constructor with HttpWebRequest in parameter.
This will simply overide the .Net ssl verification function to accept all certificate.

3. Bellow example send a Rest request with json content and read the response content, handling utf8 encoding and multi chunk response :

// Http request header
DotNetGHttpWebRequest := DotNetGHttpWebRequest.Create('http://...');
DotNetGHttpWebRequest.Method := 'GET';
DotNetGHttpWebRequest.KeepAlive := FALSE;
DotNetGHttpWebRequest.Accept := '*/*';
DotNetGHttpWebRequest.Timeout := 60000;
DotNetGHttpWebRequest.ContentType := 'application/json;charset=utf-8';

// Http request body exemple for Rest API :
// Convert text to bigtext to handle encoding
BigTextL.ADDTEXT('{ "name": "json example" }');

// Generate encoded stream containing request body content
RecLBlob.INIT;
RecLBlob.Blob.CREATEOUTSTREAM(OutStreamL, TEXTENCODING::UTF8);
BigTextL.WRITE(OutStreamL);
RecLBlob.Blob.CREATEINSTREAM(InStreamL);
DotNetLRequestStream := DotNetGHttpWebRequest.GetRequestStream;
COPYSTREAM(DotNetLRequestStream, InStreamL);
DotNetLRequestStream.Flush;
DotNetLRequestStream.Close;
DotNetLRequestStream.Dispose;

// Force SSL Certificat validation
HttpCertificateValidator := HttpCertificateValidator.RequestValidator(DotNetGHttpWebRequest);

// Try to send request and get response :
DotNetGHttpWebResponse := DotNetGHttpWebRequest.GetResponse;

// Read response :
TempBlob.INIT;
TempBlob.Blob.CREATEINSTREAM(InStreamL);
DotNetGHttpWebResponse.GetResponseStream.CopyTo(InStreamL);

// Read response until last chunk
IntLRead := 1;
WHILE IntLRead > 0 DO BEGIN
  IntLRead := InStreamL.READTEXT(TxtLChunkRead); 
  IF IntLRead > 0 THEN
    TxtGResponse := TxtLChunkRead;
END;

// Close Http web request 
DotNetGHttpWebResponse.Close;

// Handle response
IF TxtGResponse [...]

Variables needed :
DotNetGHttpWebRequest – DotNet – System.Net.HttpWebRequest
DotNetLEncoding – DotNet – System.Text.Encoding
DotNetLRequestStream – DotNet – System.IO.Stream
BigTextL  – BigText
RecLBlob – Record – TempBlob
TempBlob – Record – TempBlob
TxtLChunkRead – Text
TxtGResponse – Text
IntLRead – Integer

8 Comments

  1. Hi Maxime,

    Many thanks for the example. I have tried running it but keep running into this error:

    “A call to System.Net.HttpWebRequest.GetResponse failed with this message: The request was aborted: Could not create SSL/TLS secure channel.”

    I am trying to send a http request to Zendesk from NAV (2017).

    Any help would be greatly appreciated!

    Many thanks,

    Anant

    • Hello anant and sorry for the response time.
      If you keep getting this error after implementing this DLL it’s problably because you are facing a TLS only protocol.
      You can force the httprequest to use TLS manually in Nav and try different tLs version (1.0, 1.1, 1.2) :

      Declare :
      ServicePointManager=System.Net.ServicePointManager
      SecurityProtocolType=System.Net.SecurityProtocolType

      Then code before request send:
      ServicePointManager.SecurityProtocol := SecurityProtocolType.Tls12;

      https://www.hougaard.com/let-nav-use-tls1-2-when-talking-to-webservices/

  2. Thank you for sharing the information. I am using NAV 2013 and am having this problem. But I have not overcome it.
    Can you share your information with the NAV version 2013?

    Thanks very much

    • I can’t help you without any information on your problem, what error message did you got which function are you using within Nav 2013 to send the request ect
      You can also try to disable to option “Enable Certificate Validation” on the Nav service but this should not be a proble if you implement this solution.
      If you implement the DLL and keep getting an error the problem should not be throw by the certificate type but from the security protocol or some other http parameters.

  3. Hi Maxime,

    Thanks for your tip but I do not not see any class in the HttpCertificateValidator assembly.

    Another point, I disabled the “Enable Certificate Validation” option but still get the error.

    I am working on NAV 2017

    Can you help me please ?

    Thanks,
    Michael

    • Hi Michael and sorry for the long answer time I’m not very active here
      The provided DLL contain a public class called “RequestValidator” a two other that are not used. Can you please right click and go to property on the DLL file copied in the service folder and check if there is any “Unblock” checkbox. Sometime assembly files are disabled by system when copied on a server according to security setup.
      assembly

  4. Thanks so much – this has solved my problem for now.
    For some reason since change of provider, although PostMan can call the REST api fine, in C/AL it was failing with “certificate is invalid according the validation procedure”.

    This got it working again, until we can work out why certificate validation fails in C/AL (.net).

Leave a Reply

Your email address will not be published. Required fields are marked *