0

I have written an ASP.NET MVC application. Within the application, I have written a rather simple method entitled GetClientCertificateCollection(). This method is supposed to simply return the current user's client certificates. When I execute this code in VisualStudio 2013 / IIS Express [debug mode], the logic works perfectly and I can process the user's X509 certificates without issue [I also retrieve the server's certificates, but I've written could to ignore them and only process through valid user certificates].

Unfortunately, when I deploy my solution to an instance of IIS on a web server, the method returns nothing; literally 0 certificates.

I have researched and tried a number of suggestions, but I have been unsuccessful in finding the smoking gun.

My IIS configuration is as follows: 1. Site is hosted as a sub-directory to the "Default Web Site". 2. Bindings - Port 443 enabled with an SSL certificate. 2. Authentication - All Disabled. 3. SSL Settings - Require SSL / Require.

I'm hopeful that someone can help point me in the right direction. Thanks in advance for your help.

public static X509Certificate2Collection GetClientCertificateCollection()
{
    X509Store UserStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)
    try
    {
        UserStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
        X509Certficate2Colllection certificatesInStore = UserStore.Certificates;
        return certificatesInStore;
    }
    catch (Exception ex)
    {
        throw;
    }
    finally
    {
        UserStore.Close
    }
}
  • If you're trying to get the client certs from the user's machine (the machine that is running the browser), this won't work-- the server doesn't have access to the client. If you're trying to get the client certs that the server will use to call other services, you are probably storing the certs in the wrong cert store (see Wiktor's answer). – John Wu Oct 16 '17 at 18:11
  • The application has to retrieve the client certificates from the user's machine via the browser, allowing the application to authenticate the user based on an identity established by the PKI cert. I am looking at other options. Unfortunately, I've been unable to pull the certificate from the request using context.Request.ClientCertificate.IsPresent. Any other ideas? – Anonymous3521 Oct 16 '17 at 21:18
  • Using `Request.ClientCertificate` is the correct approach. If it's not working, see [this question](https://stackoverflow.com/questions/6361738/asp-net-request-clientcertificate-returning-empty-on-iis-7) or perhaps post a different question providing details. Some setup is required and you could easily have missed some. – John Wu Oct 16 '17 at 21:24

2 Answers2

3

I am almost 100% sure you just don't have any certificates as you don't put them into the app pool's identity profile.

In other words, you mistakenly assume your app works on IIS under the very same profile (your profile) while in fact the application pool has another, different identity set.

You have to inspect the settings of your application pool, locate the identity the pool runs under, log as this identity, access its cert store and put certificates there. This can be problematic if your app pool uses the APP POOL identity pool, you can't just log as an identity from this pool. In such case, you have to switch to the shared cert store (machine store) which is a single cert store accessed by any identity.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • Agreed. Please check if there are any certificates. – Isham Mohamed Oct 16 '17 at 18:09
  • My application must be able to identify personal certificates installed within the user's browser of choice. When I run my application in debug mode using IE, Firefox, or Chrome; I'm able to pull these certificates (my certificates) directly via the code above. However, when I run the same application using any of the browser's above via IIS, no certificates are returned. – Anonymous3521 Oct 16 '17 at 18:20
  • If I'm understanding you correctly, my code in debug mode is working because I'm working with my user store while running the application as me. However, when I move the same code to IIS, I return nothing because there are no certificates installed under the identity of the application pool user. – Anonymous3521 Oct 16 '17 at 18:22
  • Taken that a step further, it seems that I need a completely different approach to truly evaluate a user's certificates installed on the client browser. Would you agree? – Anonymous3521 Oct 16 '17 at 18:23
  • By the way, I have confirmed that the server certs are present using MMC.exe and the certificate snap-in. I have also confirmed that the user certs are present using the respective "Options" in the respective browser. – Anonymous3521 Oct 16 '17 at 20:34
  • Yes, you need a completely different approach to be able to get client certificates. Frankly, you'll have hard time finding a way to do so. C# code that runs at the server side will never be able to touch anything at the client side. – Wiktor Zychla Oct 17 '17 at 07:20
0

I have learned a lot since posting this question originally. I was overlooking some rather simple obstacles when I originally posted this question and I'm hoping that my answer can help those who may struggling with the same problems I was struggling with.

  1. The correct way to pull a browser certificate is to utilize the HttpContext.Current.Request.ClientCertificate. It was an incorrect approach to use the X509Store.
  2. If you are receiving a certificate not present when using HttpContext, investigate where you are making the call. If using an MVC application, this call cannot be made from Application_Start within global.asax.cs. Instead, add an Application_BeginRequest method to your global.asax.cs class and call HttpContext from this location.