0

using : .net 4.0, VS2010 and webapi1.0 I followed this link http://southworks.com/blog/2014/06/16/enabling-ssl-client-certificates-in-asp-net-web-api/

to enforce clients to send certificate to Authenticate

On the server side the code looks like below

 public class RequireCertificateFilter : ActionFilterAttribute
        {
            public override void OnActionExecuting(HttpActionContext actionContext)
            {


                var request = actionContext.Request;

                if (!this.AuthorizeRequest(request.GetClientCertificate()))
                {
                    throw new HttpResponseException(HttpStatusCode.Forbidden);
                }

            }

            private bool AuthorizeRequest(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2)
            {
                bool result = false;
                if (x509Certificate2 != null)
                {
                    string issuer = x509Certificate2.Issuer;
                    string subject = x509Certificate2.Subject;
                    result = true;
                }
                return result;
            }

request.GetClientCertificate() Always return null am i missing any other settings? not sure why client certificate is not coming through?

Client code looks like below

      X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
            var cert = store.Certificates.Find(X509FindType.FindBySubjectName, "ClientCertificatesTest", true)[0];


  // Build HTTP Request
            HttpWebRequest wrStatus = (HttpWebRequest)WebRequest.Create("https://localhost/TestAPI/api/Home");          
            wrStatus.KeepAlive = true;
            wrStatus.Method = WebRequestMethods.Http.Get;
            wrStatus.Accept = "text/xml";
            wrStatus.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)";
            wrStatus.ClientCertificates.Clear();
            wrStatus.ClientCertificates.Add(cert);


            string result = null;
            using (HttpWebResponse resp = (HttpWebResponse)wrStatus.GetResponse())
            {
            StreamReader reader = new StreamReader(resp.GetResponseStream());
            result = reader.ReadToEnd();
            }

            }

Update :

I tried using fiddler and debugged through the code where it calls getResponse and here's what i get back

enter image description here

Gauls
  • 1,955
  • 6
  • 28
  • 44
  • Might be the same issue as http://stackoverflow.com/questions/22817965/httprequestmessage-getclientcertificate-returns-null-in-web-api - unfortunately there is no accepted answer there as well. – Lucero Nov 24 '15 at 09:33
  • I'd try and use Fiddler to intercept and analyze the SSL traffic, in order to see if the client cert is actually sent to the server side or not. Also, you have to make sure (e.g. using MMC) that the client uses a cert with private key, just the public cert part will not work. – Lucero Nov 24 '15 at 09:37
  • @ Lucero : How to ensure the both parts are used in MMC? All i refer to ClientCertificatesTest is that wrong? – Gauls Nov 24 '15 at 12:37
  • in MMC add/remove snapins, add Certificates for the store you're interested in (e.g. current user). Open Personal -> Certificates and double-click the certificate in question. On the General tab it should inform you "You have a private key that corresponds to this certificate.". – Lucero Nov 24 '15 at 15:01
  • @Lucero: Yes that's correct it is. – Gauls Nov 24 '15 at 15:04
  • 1
    Regarding Fiddler, the message tells you that the name of the cert received does not match the host you're connecting to. By default, browsers will terminate the SSL connection in this case. The certificate can be used for "localhost" (e.g. IP 127.0.0.1), for other connections I suggest using a real cert. One way to do that if you have control over the domain e-mails is to get a free one from StartSSL.com. – Lucero Nov 24 '15 at 15:05
  • @Lucero : I used makecert as mentioned in the link and this is just a test app The update was required in client code (https://{IP}/TestAPI/api/Home)so that fiddler could intercept it but that gives an error that is not related to the actual problem. – Gauls Nov 24 '15 at 15:11
  • By default, proxies are not used for local requests. This can be configured through, as noted in the Fiddler help as well: http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureDotNETApp - that shouly allow you to use local IP again (but you might still want to use something different than localhost) and therefore avoid the certificate name error you currently get. – Lucero Nov 24 '15 at 15:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/96047/discussion-between-gauls-and-lucero). – Gauls Nov 24 '15 at 15:50

1 Answers1

0

Your client certificate is not trusted because the chain of trust fails and as a result it is rejected. I believe the southworks.com link you posted is making the assumption that the client and server code are running on the same box. If you are using a separate server for your server code, it will not be able to validate your client certificate unless you install your self-made CA cert (DevelopmentCA.cer) into the server's Trusted Root Certification Authorities.

Richard Brightwell
  • 3,012
  • 2
  • 20
  • 22