ASP.NET WebForms : Implementing PKI Authentication

Written by John DeVight on 2011-May-18

rating: 0+x

Download Source Code

Overview

Last year I needed to implement PKI authentication on a project. Initially I was worried that this would be a major task to accomplish, but was pleased to discover how easy it was to do. I created an HttpModule called AuthenticationModule that subscribed to the HttpApplication.AuthenticationRequest event. The event handler checked to see if the client certificate is present, validate the certificate's Distinguished Name (DN) and allow access to the website. If the certificate was missing or invalid, then I redirected the user to an unauthorized page.

Implementing the AuthenticationModule

In the sample application, the verification of the certificate DN is simply checking a hard-coded DN in the source code. Normally I would query the database to see if the certificate DN is registered, return the user information and set the HttpContext.Current.User to an instance of a model that implements the IPrincipal interface. Also, to keep the sample application simple and straight forward, I throw an HttpException in the sample application if the certificate DN is invalid or if the client certificate is missing (which shouldn't happen if IIS is configured to require client certificates.

Here is the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography.X509Certificates;

namespace WebFormApp.HttpModules
{
    public class AuthenticationModule : IHttpModule
    {
        private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(typeof(AuthenticationModule));

        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            if (_logger.IsInfoEnabled) _logger.Info("Init");

            // Add handler for the Authenticate event
            context.AuthenticateRequest += AuthenticateRequestHandler;
        }

        void AuthenticateRequestHandler(object sender, EventArgs e)
        {
            if (_logger.IsInfoEnabled) _logger.Info("AuthenticateRequestHandler");

            HttpApplication app = (HttpApplication)sender;
            HttpContext context = app.Context;

            X509Certificate2 userCert = null;

            // If client certificate is presented...
            if (context.Request.ClientCertificate.IsPresent)
            {
                userCert = new X509Certificate2(context.Request.ClientCertificate.Certificate);
                X500DistinguishedName dn = userCert.SubjectName;
                string userDn = dn.Name.Trim().ToUpper();

                if (_logger.IsInfoEnabled) _logger.Info(string.Format("OnAuthorization : UserDn = {0}", userDn));

                if (userDn != "CN=JOHN DOE")
                {
                    throw new HttpException(401, "Invalid Client Certificate");
                }
            }
            else
            {
                throw new HttpException(401, "Client Certificate Missing");
            }
        }
    }
}

Web.config Configuration to Register the HttpModule

Now that we have our AuthenticationModule, it needs to be registered in the web.config. Settings are added in two places in the web.config file, /configuration/system.web/httpModules and /configuration/system.webServer/modules.

Here are excerpts from the web.config:

<configuration>
    <system.web>
        <httpModules>
            <add name="PkiAuthentication" type="WebFormApp.HttpModules.AuthenticationModule, WebFormApp" />
        </httpModules>
    </system.web>

    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true">
            <add name="PkiAuthentication" type="WebFormApp.HttpModules.AuthenticationModule, WebFormApp" />
        </modules>
    </system.webServer>

References

Support ASP.NET Wiki

If you like this page, click on the "Share on" links in the wikidot toolbar at the top of the page to share it with your friends.

Comments

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License