AlexH
AlexH

Reputation: 125

How to configure IIS/Asp.Net to use a client Certificate for TLS connection to a server

A feature of the website I'm working on is being able to POST data to a remote server using a client certificate and TLS.

I have been given a p12 Client Certificate, and installed/added it to the system. The certificate is used in code as follows, (but only seems to work if installed to the system too):

using (var client = new CertificateWebClient("~/ccert.p12"))
{
   client.UploadFile(endpoint, filepath);
}

public class CertificateWebClient : WebClient
{
    private readonly string _certificateUri;

    public CertificateWebClient(string certificateUri)
    {
        _certificateUri = certificateUri;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        var clientCertificate = new X509Certificate(HostingEnvironment.MapPath(_certificateUri));
        request.ClientCertificates.Add(clientCertificate);
        return request;
    }
}

When debugging the application locally, I get the option to allow use of the certificate:

Request for permission

After installing the certificate on the server, I managed to run a small test program outside of IIS and it can use the certificate without any prompt.

I can't figure out how to get the site to use the certificate when running under an app pool in IIS.

Everything I have found so far has been about adding bindings so that certificates can be used for clients connecting to an application, rather than using client certificates to connect to other servers.

In case it makes any difference, this is for IIS7 on Server 2008 R2.

Upvotes: 0

Views: 1517

Answers (2)

AlexH
AlexH

Reputation: 125

It seems that using X509Certificate2 instead of X509Certificate works without requiring authentication - I think the authentication is due to the certificate being loaded from the certificate store, not from the local path.

The class below will allow for an Asp.Net site to use a self signed client certificate using a file path.

public class CertificateWebClient : WebClient
{
    private readonly string _certificateUri;

    public CertificateWebClient(string certificateUri)
    {
        _certificateUri = certificateUri;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        var clientCertificate = new X509Certificate2(HostingEnvironment.MapPath(_certificateUri), "", X509KeyStorageFlags.MachineKeySet);
        request.ClientCertificates.Add(clientCertificate);
        return request;
    }
}

Upvotes: 0

ganesh
ganesh

Reputation: 220

Try to extend WebClient and add the certificate to WebRequest as below:

   class MyWebClient : WebClient
   {
      protected override WebRequest GetWebRequest(Uri address)
      {
          HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
          request.ClientCertificates.Add(new X509Certificate("~/ccert.p12", "password_if_any_or_empty"));
          return request;
      }
  }

Upvotes: 1

Related Questions