PDF version of SmartCard article

12:50 PM j. montgomery 6 Comments

UPDATE: An updated version is out. Read more about it here.

http://securitythroughabsurdity.com/2010/05/smart-card-authentication-module-update.html

I've posted a PDF version of Implementing Smart Card Authentication and Authorization using ASP.NET.

You can download it here.

6 comments:

Implementing SmartCard Authentication with ASP.NET

9:19 PM j. montgomery 45 Comments

UPDATE: An updated version is out. Read more about it here.

http://securitythroughabsurdity.com/2010/05/smart-card-authentication-module-update.html

Table of Contents

This is a more complete follow-up article on how to implement Smart Card Authentication in ASP.NET using Http Modules. Sample code in C# is now available here. VB.Net Projects to be posted soon.
You can also download a PDF version of this article here.
I. Introduction
II. Building and Installing the Smart Card HttpModule
III. IIS Configuration
IV. Implementing SmartCardAuthenticationModule
V. SmartCardAuthenticationEventArgs Implementation
VI. SmartCardIdentity Implementation
VII. SmartCardPrincipal Implementation
VIII. Additional Implementation Details
IX. Implementing Authorization in ASP.NET
X. Further Reading

45 comments:

Further Reading on HTTP Modules and IIS Configuration

9:16 PM j. montgomery 0 Comments

Back to Table of Contents: Implementing SmartCard Authentication with ASP.NET

1. http://support.microsoft.com/kb/307985

INFO: ASP.NET HTTP Modules and HTTP Handlers Overview

This article introduces the ASP.NET HTTP modules and HTTP handlers

2. http://msdn.microsoft.com/msdnmag/issues/02/09/HTTPPipelines/

This article introduces the architecture of the pipeline and shows how you can use it to add sophisticated functionality to an ASP.NET-based app.

3. http://msdn.microsoft.com/msdnmag/issues/02/05/asp/default.aspx

A (brief) look at HTTP modules in ASP.NET.

4. http://support.microsoft.com/kb/887289

HTTP module to check for canonicalization issues with ASP.NET

To aid customers in protecting their ASP.NET applications, Microsoft has made available an HTTP module that implements canonicalization best practices.

5. http://msdn2.microsoft.com/en-us/library/aa479332.aspx

Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components

In this article, Scott Mitchell and Atif Aziz show how you can use HTTP modules and handlers to add error logging to your ASP.NET applications. (22 printed pages)

6. http://msdn2.microsoft.com/en-us/library/ms972974.aspx

URL Rewriting in ASP.NET (using HTTP Handlers)

Examines how to perform dynamic URL rewriting with Microsoft ASP.NET. URL rewriting is the process of intercepting an incoming Web request and automatically redirecting it to a different URL. Discusses the various techniques for implementing URL rewriting, and examines real-world scenarios of URL rewriting. (31 printed pages)

7. http://support.microsoft.com/kb/313070

HOW TO: Configure Client Certificate Mappings in Internet Information Services (IIS) 5.0

8. http://support.microsoft.com/kb/272175/EN-US/

HOW TO: Configure Active Directory Certificate Mapping

9. http://support.microsoft.com/kb/216906/EN-US/

Comparing IIS 5.0 Certificate Mapping and Native Windows 2000 Active Directory Certificate Mapping

10. http://www.google.com/microsoft?q=HTTP+modules+&hq=microsoft&btnG=Google+Search

Back to Table of Contents: Implementing SmartCard Authentication with ASP.NET

0 comments:

Implementing Authorization in ASP.NET

9:13 PM j. montgomery 0 Comments

Page 9 of 9

Previous Page: Additional Implementation Details | Next Page: Further Reading

Once you have your SmartCardPrincipal setup, there are several ways to implement authorization with the IPrincipal using Code Access Security (CAS) for authorization within ASP.NET.

We can configure Role base authorization using the web.config file, using PrincipalPermission Demands, or IPrincipal.IsInRole() checks in code.

Declarative

  • Principal Permissions can be used to decorate methods that will demand upstream callers in the stack have a particular Role.

C#

using System.Security.Permissions;
...
[PrincipalPermission(SecurityAction.Demand, Role
="Administrator"),
PrincipalPermission(SecurityAction.Demand, Role
="Auditors")]
public void DoSomethingImportant()
{
...
}


VB.Net


Imports System.Security.Permissions
...
<PrincipalPermission(SecurityAction.Demand, Role:="Administrator"), _
PrincipalPermission(SecurityAction.Demand, Role:
="Auditors")> _
Public Sub DoSomethingImportant()
...
End Sub

Imperative


  • Principal Permissions can be used to make demands programmatically to upstream callers in the stack have a particular Role.

C#


using System.Security.Permissions;
...
public void DoSomethingImportant()
{
PrincipalPermission permCheck
= new PrincipalPermission(Nothing, "Administrators");
permCheck.Demand();
}


VB.Net

Imports System.Security.Permissions
...
Public Sub DoSomethingImportant()
Dim permCheck As New PrincipalPermission(Nothing, "Administrators")
permCheck.Demand()
End Sub


IPrincipal.IsInRole() Check


  • 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):

C#


if (myPrincipal.IsInRole("Administrators")
{
...
}


VB.Net

If myPrincipal.IsInRole("Administrators") Then
...
End If


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


  • To allow all Administrators and deny everyone else to a folder called ‘Admin’, and to allow only Auditors into a folder called ‘Reports’, we’d add the following to the web.config:

<configuration>
<system.web>
...
</system.web>
<location path="Admin">
<system.web>
<authorization>
<allow roles="Administrator" />
<deny users="*" />
</authorization>
</system.web>
</location>
<location path="Reports">
<system.web>
<authorization>
<allow roles="Auditor" />
<deny users="*" />
</authorization>
</system.web>
</location>
</configuration>


Conclusion


ASP.NET provides a powerful, yet simple way to implement custom authentication functionality in the HTTP Pipeline using HTTP Modules. IIS also has robust support for Client Certificates and when combined, Http Modules in ASP.NET and IIS make a great platform for developing sites that need to use Smart Cards for authentication and authorization.


Previous Page: Additional Implementation Details | Next Page: Further Reading


Page 9 of 9

0 comments:

Additional Implementation Details

9:10 PM j. montgomery 0 Comments

Page 8 of 9
Previous Page: SmartCardPrincipal Implementation | Next Page: Implementing Authorization in ASP.NET

There are several more classes involved in this implementation, but they go beyond the scope of the HttpModule. If you download the sample code, you can take a look at my particular implementation. They are barely implemented so I’d recommend you use them at your own risk.
The Configuration Class
The Configuration class resolves some things like 401 error page, the database connection string, and the database connection timeout. The class had the following structure:

These values are retrieved from the web.config file:
1 <configuration> 2 <system.web> 3 4 </system.web> 5 <appSettings> 6 <add key="SmartCardAuthentication_UnauthorizedPage" 7 value="C:\WINNT\help\iisHelp\common\401-1.htm"/> 8 <add key="SmartCardAuthentication_ConnectionString" 9 value="integrated security=SSPI;data source=Server;initial catalog=Database"/> 10 <add key="SmartCardAuthentication_ConnectionTimeout" 11 value="180" /> 12 </appSettings> 13 </configuration>

The DataAccess Class

The DataAccess class had some methods for quickly retrieving data from the database.


The CryptoUtility Class
This class performed operations (hash compare, BinToHex() / HexToBin() conversions, etc.) on the X509 certificates. It also generates the Public Key hash used to retrieve users out of the database, and validates some simple properties on the X509 certificate for an internal sanity check. IIS should already be catching these problems before it gets to our code, but it can’t hurt to check again.

Some Final Tests


Once you have the SmartCardAuthenticationModule code up and running, a simple way to test it is as follows:

1 private void Page_Load(object sender, EventArgs e) 2 { 3 SmartCardIdentity smartCardIdentity = (SmartCardIdentity)Me.User.Identity; 4 SmartCardPrincipal smartCardPrincipal = (SmartCardPrincipal)Me.User; 5 6 Response.Write("Name: " + smartCardIdentity.Name + "<br>"); 7 Response.Write("Is Authenticated: " + smartCardIdentity.IsAuthenticated + "<br>"); 8 Response.Write("Authentication Type: " + smartCardIdentity.AuthenticationType + "<br>"); 9 Response.Write("Elevated User: " & SmartCardPrincipal.IsElevatedUser + "<br>");10 Response.Write("Is in role Administrator: " + this.User.IsInRole("Administrator"));11 }12

VB.Net

1 Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 2 Handles MyBase.Load 3 4 Dim smartCardIdentity As SmartCardIdentity = DirectCast(Me.User.Identity, SmartCardIdentity) 5 Dim smartCardPrincipal As SmartCardPrincipal = DirectCast (Me.User, SmartCardPrincipal) 6 7 Response.Write("Name: " & smartCardIdentity.Name & "<br>") 8 Response.Write("Is Authenticated: " & smartCardIdentity.IsAuthenticated & "<br>") 9 Response.Write("Authentication Type: " & smartCardIdentity.AuthenticationType & "<br>")10 Response.Write("Elevated User: " & SmartCardPrincipal.IsElevatedUser & "<br>")11 Response.Write("Is in role Administrator: " & Me.User.IsInRole("Administrator"))12 End Sub 13

Previous Page: SmartCardPrincipal Implementation | Next Page: Implementing Authorization in ASP.NET
Page 8 of 9









0 comments:

SmartCardPrincipal Implementation

9:08 PM j. montgomery 1 Comments

Page 7 of 9
Previous Page: SmartCardIdentity Implementation | Next Page: Additional Implementation Details

The SmartCardPrincipal Class – Inherits from System.Security.Principal.IPrincipal
From the MSDN documentation, a principal object represents the security context of the user on whose behalf the code is running, including that user's identity (IIdentity) and any roles to which they belong. The Principal is the object that gets interrogated when a PrincipalPermission Demand is made to make sure it is in the proper role to perform the requested operation.
When SmartCardPrincipal.IsInRole() is called, our Smart Card aware object will return whether or not the Principal is in the requested role. On first run, this class will populate a Hashtable with the roles for the current user from the database. The key to lookup the Users’ Roles in the database will be a SHA256 hash of the Users’ public key.
Also notice that both IsElevatedUser and IsInRole() is virtual/Overridable – This allows for custom role resolution if you have a different methodology to resolve roles other then the database role resolution provided.

C#
1 using System;
2 using System.Configuration;
3 using System.Web;
4 using System.Web.Security;
5 using System.Collections;
6 using System.Security.Principal;
7 8 namespace SmartCardAuthentication
9 {
10 public class SmartCardPrincipal : IPrincipal
11 {
12 private SmartCardIdentity _identity;
13 private Hashtable _roles;
14 private bool _isElevatedUser;
15 private bool _rolesLoaded;
16 private bool _isElevatedLoaded;
17 18 public IIdentity Identity
19 {
20 get
21 {
22 return this._identity;
23 }
24 }
25 26 public SmartCardPrincipal(SmartCardIdentity identity)
27 {
28 this._identity = identity; 
29 this._rolesLoaded = false;
30 this._isElevatedLoaded = false;
31 }
32  
33  
34 public virtual bool IsElevatedUser
35 {
36 get {
37 if (!_isElevatedLoaded)
38 {
39 lock (this)
40 {
41 // Evaluate the user against the database
42 // to see if they have an elevated account 43 DataAccess dAccess = new DataAccess();
44 this._isElevatedUser =
45 dAccess.AuthenticateUser(_identity.PublicKeyHash);
46 }
47 this._isElevatedLoaded = true;
48 }
49 return this._isElevatedUser;
50 }
51 }
52 53 public virtual bool IsInRole(string role)
54 {
55 if (!_rolesLoaded)
56 {
57 lock (this)
58 {
59 if (this.IsElevatedUser)
60 {
61 DataAccess dAccess = new DataAccess();
62 _roles = dAccess.GetPrincipalRoles(_identity.PublicKeyHash);
63 _roles.Add("User", "User");
64 }
65 else
66 {
67 _roles = new Hashtable(1);
68 _roles.Add("User", "User");
69 }
70 _rolesLoaded = true;
71 }
72 }
73 return _roles.Contains(role);
74 }
75 }
76 }

VB.Net
1 Imports System.Configuration
2 Imports System.Web
3 Imports System.Web.Security
4 Imports System.Collections
5 Imports System.Security.Principal
6 7 Public Class SmartCardPrincipal
8 Implements IPrincipal
9 10 Private _identity As SmartCardIdentity
11 Private _roles As Hashtable
12 Private _rolesLoaded As Boolean 13 Private _isElevatedLoaded As Boolean 14 15 Public ReadOnly Property Identity() As IIdentity _
16 Implements IPrincipal.Identity
17 Get 18 Return Me._identity
19 End Get 20 End Property 21 22 Public Sub New( _
23 ByVal identity As SmartCardIdentity _
24 )
25 Me._identity = identity
26 Me._rolesLoaded = False 27 Me._isElevatedLoaded = False 28 End Sub 29 30 Public Overridable ReadOnly Property IsElevatedUser() As Boolean 31 Get 32 If (Not _isElevatedLoaded) Then 33 SyncLock (Me)
34 ' Authenticate the user against the database 35 Dim dAccess As New DataAccess
36 _isElevatedUser = dAccess.AuthenticateUser(Me._identity.PublicKeyHash)
37 38 _isElevatedLoaded = True 39 End SyncLock 40 End If 41 42 Return _isElevatedUser43 End Get 44 End Property 45 46 Public Overridable Function IsInRole(ByVal role As String) As Boolean _
47 Implements IPrincipal.IsInRole
48 If (Not _rolesLoaded) Then 49 SyncLock (Me) 50 If _identity.IsElevatedUser Then 51 ' If the user is elevated, retrieve roles from the database 52 Dim dAccess As New DataAccess
53 _roles = dAccess.GetPrincipalRoles(_identity.PublicKeyHash)
54 ' Finally add the Default Role 55 _roles.Add("User", "User")
56 Else 57 _roles = New Hashtable(1)
58 ' Regular user 59 _roles.Add("User", "User")
60 End If 61 _rolesLoaded = True 62 End SyncLock 63 End If 64 Return _roles.Contains(role)
65 End Function 66 End Class

Previous Page: SmartCardIdentity Implementation | Next Page: Additional Implementation Details

Page 7 of 9


1 comments:

SmartCardIdentity Implementation

9:04 PM j. montgomery 0 Comments

Page 6 of 9

Previous Page: SmartCardAuthenticationEventArgs| Next Page: SmartCardPrincipal Implementation

SmartCardIdentity Class – Inherits from System.Security.Principal.IIdentity

The IIdentity Interface defines the basic functionality of an identity and is used to encapsulate information about the user or entity being validated (MSDN Documentation).

 

 C#

1 using System;
2 using System.Web;
3 using System.Security.Cryptography.X509Certificates;
4 using System.Security.Principal;
5
6 namespace SmartCardAuthentication
7 {
8 public class SmartCardIdentity : IIdentity
9 {
10 private string _subject;
11 private string _email;
12 private string _publicKeyHash;
13 private X509Certificate _certificate;
14
15 public string AuthenticationType
16 {
17 get { return "SmartCard"; }
18 }
19
20 public bool IsAuthenticated
21 {
22 get { return true; }
23 }
24
25 public string Name
26 {
27 get { return _subject; }
28 }
29
30 public string PublicKeyHash
31 {
32 get { return _publicKeyHash; }
33 }
34
35 public string EmailAddress
36 {
37 get { return this._email; }
38 set { this._email = value; }
39 }
40 public X509Certificate Certificate
41 {
42 get { return this._certificate; }
43 }
44
45
46
47 public DateTime ExpirationDate
48 {
49 get
50 {
51 return DateTime.Parse(
52 this._certificate.GetExpirationDateString()
53 );
54 }
55 }
56
57 public string Subject
58 {
59 get { return this._subject; }
60 }
61
62 public SmartCardIdentity(HttpClientCertificate certificate)
63 {
64 this._certificate = new X509Certificate(certificate.Certificate);
65 this._publicKeyHash = CryptoUtility.GetPublicKeyHash(certificate);
66 this._subject = certificate.Subject;
67 }
68
69 public SmartCardIdentity(X509Certificate certificate)
70 {
71 this._certificate = certificate;
72 this._publicKeyHash = CryptoUtility.GetPublicKeyHash(certificate);
73 this._subject = certificate.GetName();
74 }
75 }
76 }

VB.Net


1 Imports System.Web
2 Imports System.Security.Cryptography.X509Certificates
3 Imports System.Security.Principal
4
5 Public Class SmartCardIdentity
6 Implements IIdentity
7
8 Private _subject As String
9 Private _email As String
10 Private _publicKeyHash As String
11 Private _certificate As X509Certificate
12
13 Public ReadOnly Property PublicKeyHash() As String
14 Get
15 Return _publicKeyHash
16 End Get
17 End Property
18
19 Public ReadOnly Property AuthenticationType() As String _
20 Implements IIdentity.AuthenticationType
21 Get
22 Return "SmartCard"
23 End Get
24 End Property
25
26 Public ReadOnly Property IsAuthenticated() As Boolean _
27 Implements IIdentity.IsAuthenticated
28 Get
29 ' The fact that this identity object exists means that
30 ' the user was Authenticated
31 Return True
32 End Get
33 End Property
34
35 Public ReadOnly Property Name() As String _
36 Implements IIdentity.Name
37 Get
38 Return _subject
39 End Get
40 End Property
41
42 Public Property EmailAddress() As String
43 Get
44 Return Me._email
45 End Get
46 Set(ByVal Value As String)
47 Me._email = Value
48 End Set
49 End Property
50
51 Public ReadOnly Property Certificate() As X509Certificate
52 Get
53 Return Me._certificate
54 End Get
55 End Property
56
57 Public ReadOnly Property ExpirationDate() As DateTime
58 Get
59 Return DateTime.Parse(Me._certificate.GetExpirationDateString())
60 End Get
61 End Property
62
63 Public ReadOnly Property Subject() As String
64 Get
65 Return Me._subject
66 End Get
67 End Property
68
69 Public Sub New(ByVal certificate As HttpClientCertificate)
70 Me._certificate = New X509Certificate(certificate.Certificate)
71 Me._publicKeyHash = CryptoUtility.GetPublicKeyHash(certificate)
72 Me._subject = certificate.Subject
73 End Sub
74
75 Public Sub New(ByVal certificate As X509Certificate)
76 Me._certificate = certificate
77 Me._publicKeyHash = CryptoUtility.GetPublicKeyHash(certificate)
78 Me._subject = certificate.GetName()
79 End Sub
80
81 End Class
82

Previous Page: SmartCardAuthenticationEventArgs| Next Page: SmartCardPrincipal Implementation

Page 6 of 9

0 comments: