21

Can't solve the problem with certificate validation.

There's Web API server, that uses HTTPS to handle requests. Server's certificate has this certification path: RCA (root) -> ICA (intermediate) -> Web API server. RCA, ICA and Web API server are members of the same Active Directory domain.

Client application (desktop, computer is joined to the same domain) uses HttpClient to communicate with server and supports two scenarios:

  • connected to corporate network;
  • disconnected from corporate network (Internet access).

Both scenarios use basic authentication.
RCA and ICA certificates are placed in "Trusted Root Certification Authorities" and "Intermediate Certification Authorities" respectively for local computer account. RCA certificate is self-signed.

Now, when client is connected to corporate network, certificate validation works as expected, and user can "talk" to Web API.

When client is disconnected (only Internet connection is available), certificate validation fails with AuthenticationException ("The remote certificate is invalid according to the validation procedure").

I don't want to turn off certificate validation completely, but just need a way to tell validation system, that this particular certificate is valid. Also, client application uses SignalR, which by default uses it's own transport. Hence, this and this are not options.

Why placing RCA an ICA certificates to "Trusted..." and "Intermediate..." folders doesn't help?

Is there any workaround?

Community
  • 1
  • 1
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • Perhaps when you are connecting from the internet there is not longer a match between the Uri hostname and the certificate subject? – Mihai Caracostea Dec 18 '15 at 11:27
  • Both scenarios use the same connection string: " https://host.domain.zone ". Certificate subjects are: 1) RCA: "RCA, domain, zone"; 2) ICA: "ICA1, domain, zone"; 3) Web server: "HOST.domain.zone". I don't know, is different format of subject plays role or not... – Dennis Dec 18 '15 at 11:37
  • Perhaps you could post the public URL of your site so we can have a look at it? – Mihai Caracostea Dec 18 '15 at 11:42
  • Also, if I try to connect Web API via IE, I get this message: "The security certificate presented by this website was issued for a different website's address". – Dennis Dec 18 '15 at 11:42
  • "The security certificate presented by this website was issued for a different website's address" basically means what I've said in the first comment. – Mihai Caracostea Dec 18 '15 at 11:43
  • @MihaiCaracostea: hmm... can uppercase in host name cause this error? – Dennis Dec 18 '15 at 11:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/98341/discussion-between-mihai-caracostea-and-dennis). – Mihai Caracostea Dec 18 '15 at 11:54

3 Answers3

17

The issue you are experiencing is because the subject CN presented by the certificate does not match the host name in the Uri.

Make sure that the certificate bound to the public IP address of the host does have a matching CN with the host name you are using to access the resource.

To easily verify, open the Url in a browser and view the certificate. The Issued to field should contain a FQDN and match the host name part in the Uri. In your case, it does not.

Mihai Caracostea
  • 8,336
  • 4
  • 27
  • 46
  • Would a wildcard cert be a problem? In my case (an Azure DevOps 2020 server) they do match but I am getting this error anyway. – tnk479 Oct 20 '22 at 13:57
14

Insert this piece of code on procedure body:

static void Main(string[] args)   
{
     ServicePointManager.ServerCertificateValidationCallback =
                delegate (object sender, X509Certificate certificate, X509Chain 
     chain, SslPolicyErrors sslPolicyErrors)
                {
                    return true;
                };
     ....
}
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
  • This worked for me when running in a dev environment when I needed to test an api that was serving up a self-signed dev certificate. – Nathan Fisher Mar 05 '19 at 22:15
  • 16
    This actually disables the certificate validation entirely. Highly not recommended. – Mihai Caracostea Aug 21 '19 at 09:24
  • Also, the callback is not triggered when using client certificate. See: https://github.com/dotnet/corefx/issues/17226 – Jari Turkia Aug 22 '19 at 08:32
  • This is handy for using self-signed certificates when unit or SIT testing a web service. It should be noted that it does not disable authentication, it just disables client-side validation of the certificate. – rrreee Nov 11 '20 at 14:53
  • 1
    Obviously not recommended for production code but VERY much recommended for proof of concept or unit testing. Having to write a workaround for a specific cert would require building that infrastructure which would then be completely discarded in production code anyway. So I believe there is merit in this solution for that particular situation. – AsPas Jan 05 '21 at 13:08
9

The answer from @Qosai was unfortunately not enough for me, at least in a SignalR 3.1 client, as the websocket part also validates SSL certificates. ClientCertificateOptions needs to be set to Manual as well.

I found a post by a SignalR contributor that got me working:

_connection = new HubConnectionBuilder()
            .WithUrl(new Uri(hub_uri), options => {
                options
                    .Cookies
                    .Add(http_helper.loginCookie);

                var handler = new HttpClientHandler
                {
                    ClientCertificateOptions = ClientCertificateOption.Manual,
                    ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
                };
                options.HttpMessageHandlerFactory = _ => handler;
                options.WebSocketConfiguration = sockets =>
                {
                    sockets.RemoteCertificateValidationCallback = (sender, certificate, chain, policyErrors) => true;
                };
            })
            .Build();

PS: If you still have issues, have a look at this article on how to enable logging properly. For my case it was a bit tricky because xUnit does not show console output. Therefore i enabled debugging logging to a file (not in the snippet)

Paulo Neves
  • 1,096
  • 14
  • 22