Lately, I’ve been working on a project that involved retrofitting authentication via client certificates, similar to CAC/PIV smart card authentication, into an existing set of Windows Communication Foundation (WCF) web services and a desktop (yes, desktop) client application that was designed to interact with them. The first part was pretty easy to figure out; the second part was less so.
The truth is that the code needed for the client application is not onerous. The trick was finding any documentation/examples that pointed the way. If I had ever doubted that desktop applications are second-class citizens (I didn’t), this task confirmed it.
If you’ve accessed a web site that required smart card or certificate authentication (which are really the same thing), the dialog above is probably very familiar to you. With a web application, the browser is the actual client, and it detects that the back-end site or service needs a certificate. The browser then prompts you to provide a certificate and, assuming you do, passes you through to the site. With a desktop application, you need to build all of that interaction in. (In case you’re wondering why all of the certificates above say “DO NOT TRUST,” it’s because I applied a filter to show only Fiddler dummy certificates for the screen shot.)
In researching this, I found lots of examples of building bootstraps intended to debug services that require a certificate. These usually involved creating dummy server and client certificates, registering them in the appropriate certificate stores, and then embedding the single dummy client certificate into the app.config file. This works great for debugging, but it doesn’t meet the need for a production desktop application.
By now, you’ve figured out that I’m working on Windows. In many situations, the certificate is required to log into Windows itself. This certificate is mapped to a Windows identity which becomes the identity used by the desktop application. In my case, I needed to ask for a certificate and pass it through to a service for user mapping via some custom logic.
Suffice it to say that I found out how to do what I needed to do. I decided to encapsulate the approach into a good, old-fashioned Windows forms component, which I’ve posted here, along with a stupid simple example of how to use it. Hopefully, this post and the code will give a little bump to the concept for anyone else in my situation and trying to sort through the search-engine noise of web-app examples..