Connecting to Web API using https
Secure connection to Web API
Web API is hosted within the SharePoint application pool by an appropriate factory. This means that the whether the connection is made using the secure https or the standard http is imposed by the settings of the SharePoint app pool.
If the SharePoint application pool is exposed via https, then it is necessary to reference the Web API web service in the same way. Analogously, the same applies to SharePoint apps exposed over http.
The example below details how to connect to the BPS Web API web service using https. The connection process is analogous to the normal connecting to Web API, only the settings are different. Here is how to connect with BPS Web API from a .NET application, and how to create such a reference using Visual Studio.
First add a web service (available via https) reference to the project:
On the screenshot above, the address of my site is https://dev20.webcon.pl. Adding this reference will cause Visual Studio to generate the necessary classes and make appropriate configuration entries to the app.config file.
The app.config file should contain endpoints which allow for a connection over https. Find the one which starts with https and is a web service address (.svc) without any additional suffix like “/ntlm” or “/anonymous”
<client>
<endpoint address="http://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice" />
<endpoint address="http://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc/anonymous"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice1"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice1" />
<endpoint address="http://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc/ntlm"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice2"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice2" />
<endpoint address="https://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice3"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice3" />
<endpoint address="https://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc/anonymous"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice4"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice4" />
<endpoint address="https://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc/ntlm"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice5"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice5" />
</client>
Finding the relevant endpoint (in the example above, it is this particular node):
<endpoint address="https://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice3"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice3" />
Find the binding configuration name (in the example, it is: BasicHttpBinding_BPSWebservice3), and then search for this configuration in the app.config file.
By default, this node may only contain security settings:
<binding name="BasicHttpBinding_BPSWebservice3">
<security mode="Transport" />
</binding>
Add information about the preferred method of authentication. It is done like so:
<binding name="BasicHttpBinding_BPSWebservice3">
<security mode="Transport">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
With these settings, invoking the Web API web service via https protocol should be possible.
Troubleshooting
The most common problem which occurs when trying to connect to BPS Web API through https, is caused by SharePoint server security blocking the https connections due to an untrusted certificate.
When trying to connect to the web service, this error message will appear: ”Could not establish trust relationship for the SSL/TLS secure channel with authority (…)”
To verify that the problem is indeed caused by an untrusted certificate, conduct a simple browser test. From the same machine (from which the app was launched), open any internet browser and go to the SharePoint site. If the certificate is to blame, the browser will display an appropriate message:
After viewing the site, it is possible to check the details of the certificate error and the information about it being untrusted.
If the untrusted certificate is the cause of the problem, inspect its details and make sure that it has been issued for the correct host. Click the “View certificates” option to view the certificate’s details.
The “Subject” field is of significant importance, since it specifies the subject for whom the certificate was issued. If the name of the host (e.g. localhost) does not match the address used to connect to the Web API web service (e.g. https://dev20), then such a certificate will always appear to be untrusted.
If the host names are indeed correct, then the error is caused by the fact that on machine from which the connection (to Web API) is made, neither the certificate validating the connection nor any of its parent certificates are on the ”trusted certificates” list.
There are two ways to force the application using Web API with such a certificate to work (through a https connection).
Solution 1 – Overwrite method: ServerCertificateValidationCallback
The first option is to implement your own method of validating the certificate. The validating method can be registered in the following way:
System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidateCertificate;
Where method ValidateCertificate must have the following definition:
bool ValidateCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
The method must contain a boolean data type for deciding whether to accept the connection via the provided certificate (certificate parameter). For testing purposes, you can return a true value directly in the validating method or just accept all certificates issued for a given company. Here is an example of calling a BPS Web API application via https using your own certificate validation:
public void WebAPICallExample()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidateCertificate;
var client = new BPS2017Secured.BPSWebserviceClient("BasicHttpBinding_BPSWebservice3");
client.ClientCredentials.Windows.ClientCredential =
System.Net.CredentialCache.DefaultNetworkCredentials;
client.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
var element = client.GetElementById(new BPS2017Secured.GetElementByIdParams() { ElementId = 6 });
}
public bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return (sslPolicyErrors == SslPolicyErrors.None) &&
certificate.Subject.Contains("CN=MyCompany.com");
}
Solution 2 – Adding the certificate as trusted
The second option is to add the certificate securing the https connection (or one of this certificate’s parents) to the list of trusted certificates. This has to be done on the machine from which the connection to the BPS Web API web service is established. First of all, the certificate which we would like to trust has to be copied (saved) to a file. This is done from the certificate properties details tab by clicking “Copy to File…”.
To add the certificate to the trusted list, run the mmc.exe tool as an administrator. From the File menu select “Add/Remove Snap-in” and add a snap-in named “Certificates”. Then find the “Trusted Root Certificate Authorities” node, expand it and select “Certificates”. Right click the “Certificates” node to expand the context menu, select “All tasks” and then “Import”.
Locate the file with the saved certificate, then in the “Certificate Import Wizard” specify the appropriate certificate store to which the certificate should be imported.
After this operation, the certificate should be visible on the list of trusted certificates
It will now be possible to connect to Web API via https. Keep in mind however, that the name of the host in the web service address must match the name in the trusted certificate.
In the example below, the certificate is issued for the host with an address of “dev20.webcon.pl”, as such it is the only way to connect to the site using a browser without a certificate error.
Analogously, when invoking the Web API web service, only a connection through that address will be valid. If the web service reference was added through a different address, it must be corrected in the app.config file by modifying the node corresponding to the endpoint address. For example – if a reference to Web API was added through https://dev20, then it is this site that will appear in the file instead of the correctly working https://dev20.webcon.pl. This must be changed in the app.config file. Before:
<endpoint address="https://dev20/_vti_bin/WEBCON/Webservice_2017_1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice3"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice3" />
After:
<endpoint address="https://dev20.webcon.pl/_vti_bin/WEBCON/Webservice_2017_1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_BPSWebservice3"
contract="BPS2017Secured.BPSWebservice" name="BasicHttpBinding_BPSWebservice3" />
This will make sure that web service methods can be invoked via https connection without a certificate error.