HOWTO: Implementing a Smart Card Authentication Pattern with ASP.NET

UPDATE: I've completely overhauled my approach. See this article instead (or as well as).

Part 1

Typically when developing ASP.NET authentication architectures, developers can usually rely on a straightforward implementation of one of the following authentication scenarios:

  • Active Directory Authentication
  • Using integrated or basic authentication, (Kerberos, NTLM, Digest, Basic)
  • Forms authentication
  • Lookup users and authenticate against a custom data repository (SQL Server, LDAP).
  • Passport authentication
  • Use a third party (Microsoft live/passport logon) to authenticate users for you.
  • Smart Card Authentication with AD Domain Integration

While working on a particular ASP.NET project I came across an odd combination of requirements for user authentication.

The AAA requirements for this project are as follows:

  • Authentication (Who you are): All users must authenticate using Smart Cards
  • Use existing enterprise Public Key Infrastructure (PKI).
  • Use client certificates (from the smart card) to create secure channel (SSL) with client certificates using asymmetric encryption
  • Users of the system are not necessarily in Active Directory.
  • Only users with Smart Cards signed by our specific internal trusted Certificate Authorities (CA’s) can gain access
  • Revocation of certificate remove right to access the site
  • Authorization (What you are allowed and not allowed to do): Use nondiscretionary access controls or Role Based Access Controls (RBAC) for handling authorization to different resources within the site.
  • Accounting (keeping track of what you do): Ability to log/audit who does what within the system – Once we handle the authentication and authorization, the accounting is straightforward. I will implement a Global Application Logging Singleton that will track important security events within the system.

The particular AAA requirements stated above do not fit the common scenarios that IIS and .NET support out of the box.

Hopefully, you find yourself requiring a more straight-forward AAA Smart Card scenario, like one of the following:

  • All users of the system are users in Active Directory: Map client certificates to user accounts.
  • IIS will automatically associate the client certificate with the proper domain account if you have a PKI enabled Domain.
  • Using this methodology, when the user accesses the web site, they will provide their credentials (smartcard + pin) and IIS will then map the client certificate to the active directory user.
  • Then in ASP.NET, we can derive the users’ roles from the WindowsPrincipal stored in the HttpContext.User of the users mapped from the Client Certification from IIS.
  • Allow all users into the site who have a Smart Card signed by the internal CA (this will only work if we are NOT concerned about mapping users to roles with-in the system):
  • Configure IIS to work with the enterprise PKI solution – IIS alone will handle authentication.
  • Additionally we can add a “Many-to-1” rule in the IIS client certificate mapping – create a rule will check the issuer field of the client certificate and makes sure it matches our trusted CA and we can map all client certificates to one users or several users in different groups.
  • More simply, enable the Certificate Trust List at the site level in IIS and add the certificates to trust there.

Since Smart Cards are not that widely deployed and I have found that using Smart Cards for Authentication and Authorization in ASP.NET is not a broadly covered topic. The documentation on configuring IIS to work with Smart Cards (a type of Client Certificate) is adequate and not too complicated. However, marrying the IIS Smart Card architecture and ASP.NET is not discussed much at all. When IIS authenticates a user with a smart card that is not configured to map back to a domain account, ASP.NET does not map the Smart Card user to an IPrincipal object and store it in the HttpConext.User object as it does when using Integrated Authentication. This is because there is no such thing as a X509 Identity in .NET, only Windows Identity or Generic Identity. Windows Identities map to Machine or Domain Accounts (and can be derived from the Smart Card in a PKI enabled domain). Generic Identities map to a generic user of a web application (i.e. perhaps for Forms Authentication).

I will extend Forms Authentication in ASP.NET add X509 certificate support to allow both authentication and authorization in ASP.NET. I’ve accomplish this by creating a new IPrincipal object that handles more of the common tasks of Smart Card authentication, while combining it with Principal Permissions. My current implementation targets .NET 1.1.

The Solution
For us to implement a solution we need IIS to authenticate the Smart Card User and then hand off the X509 certificate to ASP.NET so we can map the users’ client certificate to a row in the users table in the database.

Once the user is authenticated, we will create an IPrincipal object based on this user so we can use Principal Permission Demands (imperative or declarative) and Explicit Role Checks available in the .NET framework.

To accomplish this I decided to modify one of the current patterns and implement a custom authentication model building upon similar principals. Since Forms Authentication provides the most flexibility, it is probably the best way to roll our own authentication while still building on the underlying Forms Authentication architecture that Microsoft has already provided. One of my goals here is not to re-invent anything, but build upon existing .NET architecture and technology. Forms Authentication allows the flexibility we need to customize the authorization mechanism (as stated above).

ASP.NET does have an object that stores the Client Certificate from the Smart Card. The Page class exposes the Request.ClientCertificate property, but oddly, it is not of type System.Security.Cryptography.X509Certificates.X509Certificate, but instead it is a System.Web.HttpClientCertificate. One would wonder why we need two classes in the framework that are very similar; one more limited then the other? I suspect it is because there were two different development teams working on different parts of the .NET Framework.

Setup IIS for SSL and to Require Client Certificate Authentication
In IIS, open the Site (or Application) - click on Properties – choose Directory Security

  • Install a SSL Certificate
  • Allow only Anonymous authentication (disable Integrated and Basic auth)
  • Under Secure Communications – Click Edit
  • Require Secure Channel (SSL)
  • Require 128-bit encryption
  • Choose "Require Client Certificates"
  • Check Enable Certificate Trust Lists and configure appropriate certificate.

Implementing Smart Card Authentication using ASP.NET
Once IIS is setup and configured properly, the next step is to implement Forms Authentication. I start with the Patterns/Practices book from Microsoft called Building Secure Microsoft ASP.NET Applications – Microsoft has an online version of this book here. It has several HOWTO articles in the Appendix. I would recommend reading “How To: Use Forms Authentication with SQL Server 2000”, “How To: Create GenericPrincipal Objects with Forms Authentication”, and “How To: Implement IPrincipal.”

Implementing Authorization in ASP.NET
There are several ways to implement authorization using Code Access Security (CAS) for authorization within ASP.NET code once we have the IPrincipal setup properly:

<PrincipalPermission(SecurityAction.Demand, Role:=”Administrators”)> _
Public Function DeleteUser( _
ByVal userId As Integer _
) As Boolean
' ...
End Function

Dim permCheck As New PrincipalPermission(Nothing, "Administrators")

Or we can check if the IPrincipal is in the role we require (which is exactly what the PrincipalPermission class does by using the IPrincipal stored in the Thread.CurrentPrincipal):
If MyPrincipal.IsInRole(“Administrators”) Then
nd If

Specify access permissions to files and/or folders in the web.config.


<?xml version="1.0" encoding="utf-8"?>
<authentication mode="Forms">
<!-- loginUrl="Authenticate.aspx": Authenticate.aspx provides Smart Card login and role assignments -->
<!-- requireSSL="true": require cookie to pass over SSL connection only -->
<!-- protection="All": Perform encryption and validation of session cookie -->
<forms name="SmartCardCookie" loginurl="Authenticate.aspx" timeout="60" path="/" requiressl="true" protection="All">
<!-- Deny all anonymous users unless specifically granted below -->
<deny users="?">
<!-- Users who have a Smart Card are automatically put into the User Role -->
<!-- All who are in the Users, Sales, and Administrator group can view Default.aspx -->
<location path="Default.aspx">
<allow roles="Administrator">
<allow roles="Sales">
<allow roles="Users">
<deny users="*">
<!-- Only the Administrators and Sales roles should be allowed in the Sales folder -->
<location path="Sales">
<allow roles="Administrator">
<allow roles="Sales">
<deny users="*">

In part one I have discussed the concepts behind the solution for implementing a Smart Card authentication pattern with ASP.NET. In part two, I will provide a sample implementation of the Forms Authentication code with custom IPrincipal object that maps the smart card client certificate to roles and then applies role-based access controls to provide authorization to different parts of the web site.

If you find this article helpful:
kick it on