Using client certificates in .NET part 5: working with client certificates in a web project

In the previous post we looked at a couple pf examples on how to work with digital certificates in C# code. In particular we saw how to load certificates from a certificate store, how to search for and how to validate one.

In this post we’ll go through how to attach a client certificate to a web request and how to extract it in a .NET Web API 2 project.

Web API 2 project preparations

Open Visual Studio 2012 or higher. You’ll need to create a Web API 2 project and there are a number of different ways. It depends on the version of Visual Studio you have and the templates that are installed. You can create an ASP.NET Web Application in Visual Studio 2013 and select the Web API template in the “New ASP.NET Project” dialog. I’ll go for the empty Web API 2 project type in Visual Studio 2012:

However, it doesn’t really make a difference how you create a Web API 2 project. Note that the template type shown above may not be available for you. You can download the necessary extension from MSDN here.

As promised the template creates an empty Web API 2 project:

There’s one change I’d like to make already now however. WebApiConfig.cs in the App_Start defines the route template with the “api” prefix:

routeTemplate: "api/{controller}/{id}"

That may be necessary if you have a mixed Web API and MVC project with web and API controllers. In this case however it has no extra value so I’ll remove the “api” bit:

Run the application and call the /customers extension in the browser. In Chrome you should see the list of customers in XML format:

Nice, we’ve completed the preparation phase. You can set a breakpoint in the beginning of the Get method already now for the next step.

Calling the Web API project from an external caller

We’ll call the GET customers action from a console application. Right-click the solution and select Add, New Project and then search for the Console Application project type. Give it some name, e.g. ClientCaller. We’ll need to reference the following libraries in the console app:

You’ll need to adjust the port number of course. You can read it from the address you see in the browser when starting the Web API project. I trust that you understand the usage of the HttpClient object.

Run the web project first as normal. Then right-click the console application, select Debug, Start New Instance. You should see that the web api endpoint is indeed called and the list of customers is returned:

Great, we now have the necessary components to build upon.

Attaching the client certificate to the web request

First let’s extend Program.cs of the console application with a function that locates our test client certificate:

The next logical step is to read the client certificate from the web request in our Web API controller. Let’s say that only those callers with a client certificate are allowed to view the customers’ list. The Request and the RequestContext properties that are available within a controller both have suitable extensions. The following code shows both but one of them is commented out:

We don’t perform any certificate validation yet, we’ll do that later. For the time being we want to make sure that we can read the incoming client certificate. You can place a breakpoint within the above Get method for easier debugging.

Run the web app and the console like we did before. You’ll see that clientCertInRequest is …err… null. What happened? Where did our client certificate go?

Let’s see. We mentioned a couple of things in the first post of this series that make more sense now. First this thing with IIS:

We run the web application in IIS Express of Visual Studio which is obviously not the same as a “normal” IIS installation. So we cannot just simply open IIS and modify this setting for our local demo. However, the above above picture suggests that by default client certificates are ignored. The client certificate is unfortunately ignored when we send it to the customers controller.

Oh well, let’s try something different then. That first post also mentioned an extension to the config file. Open web.config and add the following bit of XML within the system.webServer node:

<security>
<access sslFlags="SslNegotiateCert" />
</security>

Run the web application now. What do we have now? HTTP Error 500.19 – Internal Server Error with the following config error:

This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault=”Deny”), or set explicitly by a location tag with overrideMode=”Deny” or the legacy allowOverride=”false”.

Setting the access flag like we did is obviously not the right way either.

There seems to be no easy way to configure client certificates for local tests unfortunately. You can search for “iis express client certificate” and similar terms on the Internet and you’ll find a couple of possible workarounds with varying complexity. I think they are all too involved to achieve a simple purpose so we’ll try something different in the next post.