1. Introduction
Application Security has an important role in information management. Distributing the right information to the right people at the right time is the key to information management.
In addition to making sure that information reaches the right people, it also has to make sure that it should never reach unauthorized hands. Here is the role of information security.
Providing application security is an important aspect of ensuring information security. The main purpose of application security is to protect the application and data from unauthorized access.
The purpose of this case study is to explain how to implement application security for ASP.NET web applications using ‘Integrated Windows Authentication’.
2. How to secure web applications
Authentication and Authorization are the two factors of ensuring application security.
2.1. Authentication
Authentication is the process of deciding who can access the application. User name and password are the most common mechanisms for authentication.
2.2. Authorization
Authorization is the process of deciding what an authenticated user can do with the application. An application may provide different functionalities
for the access of different users. Access to various functionalities can be restricted based on the type of the user. This is called
role based authorization. For example, an ‘administrator’ will have a lot more access rights than a ‘guest user’.
3. What is ‘Integrated Windows Authentication’?
In integrated Windows authentication, the application makes use of the credentials of Windows users. IIS supplies the client credentials to ASP.NET.
Based on the application specific security architecture, the application can validate these credentials against the ‘access rights information’ configured for the application.
Only if the validation is successful, the user is allowed to access the application.
3.1. Single Sign on
This technology allows the user to use the same credentials for accessing multiple applications. Once the user has successfully logged on to the Operating system,
other applications can make use of these credentials from the Operating System. ‘Single Sign on’ can be implemented in ASP.NET applications by using ‘Integrated Windows Authentication’.
Once a user has logged on to the Windows Operating System, he/she is able to freely access the application as if no more sign on is required (provided the user has been given access rights
to the application). However, during application startup, it silently checks for the credentials of the user against ‘access rights information’ configured for the application.
Only if the credentials are matching, the user is allowed to access the application.
4. Where is ‘Windows Authentication’ applicable?
Since ‘Windows Authentication’ uses the credentials of Windows users, it can be used only for an intranet application. In an intra-net application, the administrator
has full control over the network users. The application can be designed in such a way that it can display all the ‘Active Directory’ users so that the administrator of the application
can configure the users authenticated for the application. Integrated Windows authentication is best suited for an intranet environment, where both user and Web server computers
are in the same domain, and where administrators can ensure that every user has Microsoft Internet Explorer, version 2.0 or later.
5. Windows Authentication and Authorization schemes
Using the WindowsAuthenticationModule provider, it is possible to provide web application security with a minimum of ASP.NET coding. The provider module constructs
a WindowsIdentity
object. The default implementation constructs a WindowsPrincipal
object and attaches it to the application context.
The WindowsPrincipal
object maps identities to Windows groups. Using the authorization
tag of the web.config file, it is possible to restrict users/groups
from accessing various application folders.
It is also possible to implement a custom Windows authorization scheme. For this purpose, you can use the WindowsAuthentication_OnAuthenticate
event handler to create
a WindowsPrincipal
or a GenericPrincipal
object from a WindowsIdentity
object. You can then use one of the new objects to implement your own custom authentication scheme.
6. How ‘Windows Authentication’ works - A case study
Here is a case study showing how to implement Windows Authentication and Role based security in ASP.NET. It starts with a detailed problem definition followed by the solution
architecture. It also gives step by step details of the solution-implementation.
6.1. Problem definition
Here is a web application for preparing business plans for a multinational company ABC. All the users are registered in the Active Directory of its intranet domain
and need to access the application from this intranet. The application offers the following functionality to users:
- Prepare master data
- Create business plans
- Approve or reject plans
- Prepare reports
Access for the Master Data (MD) users should be strictly restricted to ‘Prepare master data function’ where as Central Support Team (CST) can access all the functionality except
‘Approve or Reject Plans’. The Area Managers (AM) can only access ‘Approve or Reject Plans’ and ‘Prepare Reports’. Based on this requirement, we need to implement role based,
single sign on security for this application.
6.2. Solution architecture
We can use ‘Windows Authentication’ to provide role-based, single sign on security to this application. In order to enable Windows Authentication, we need to configure IIS directory settings
to ‘Integrated Windows Authentication’. This will enable IIS to get the client credentials and pass it on to the ASP.NET application.
In this case study, we use custom Windows authorization. Using the WindowsAuthentication_OnAuthenticate
event handler, we create
a GenericPrincipal
object
from a WindowsIdentity
object. The reasons for choosing a custom authorization are listed below:
- The application roles are not related to Windows groups, and
- The application files are not physically grouped based on the roles.
The application also requires a few additional ‘administrative’ screens to manage the user-roles and authentication information. The user screen should display all the user names
from ‘Active Directory’ so that the administrator can select only those users who need to access the application. This screen should also allow the admin to assign any
of the following three roles to the user – ‘MD’, ‘CST’, or ‘AM’. This information is stored in a separate ‘Users’ table in the database.
On session startup, the application has to check the client credentials sent by IIS against that stored in the database. If it does not find a match, it has to report
an attempt for unauthorized access and exit the application. If the client credentials match, then it constructs a client cookie which stores the user credentials and the role information.
For subsequent requests, instead of hitting the database for validating the client-credentials, the application makes use of this client-cookie. In order
to secure the client cookie, using the ‘user identity’ and ‘role’ information, we create a FormsAuthenticationTicket
. This FormsAuthenticationTicket
is then passed as the parameter to the Encrypt
method of the FormsAuthentication
class to get an encrypted string
of FormsAuthenticationTicket
. This string is then stored in a client cookie.
On each request, if the user is authenticated, the application creates a security Principal
object and stores the user-role information in it.
Then this Principal
object is put in HttpContext.Current.User
. On each Page_Load
event, the application can access the
Principal
object from HttpContext.Current.User
and validate whether the user role is authorized to access the page.
6.3. Implementation details
6.3.1. Configure IIS security settings for the application
In the IIS security settings for the application, check ‘Integrated Windows Authentication’ and uncheck all other options.
6.3.2. Web.Config entries for Windows Authentication
In Web.config, under the System.Web
tag, put the following entries:
<authenticationmode="Windows"/>
<authorization>
< allow users ="*" />
</authorization>
If you want to make sub processes (e.g.: Web Services), use the same credentials of the main thread using the following entry:
<identityimpersonate="true"/>
6.3.3. User management screens
As already stated in the ‘Solution Architecture’ section, the application should have screens for ‘user management’. Using this screen, the administrator
can map AD-user names against application roles. In this application, the user-roles are predefined hard-coded values - ‘MD’, ‘CST’, and ‘AM’. The application-administrator
can either directly type in the AD-user name or the application may display all the AD-user names so that the administrator can select the user names. In order to display
the AD-usernames, the application can query the Windows Active Directory using the .NET base class System.DirectoryServices
.
6.3.4. Security Principal object
Create a class which implements the System.Security.Principal.IPrincipal
interface.
using System;
using System.Security.Principal;
public class myAppPrincipal:IPrincipal
{
private IIdentity m_identity;
private string [] m_roles;
private string m_userId;
public MyAppPrincipal(IIdentity identity, string [] roles)
{
m_identity = identity;
m_roles = new string[roles.Length];
roles.CopyTo(m_roles, 0);
Array.Sort(m_roles);
m_userId = identity.Name;
}
public IIdentity Identity
{
get
{
return m_identity;
}
}
public string UserId
{
get
{
return m_userId;
}
set
{
m_userId = value;
}
}
public bool IsInRole(string role)
{
return Array.BinarySearch(m_roles, role) >=0 ? true : false;
}
}
6.3.5. Checking Authentication and identifying roles
The most important part of implementing security is to ensure that on each request, the application verifies the authentication and resolves the user role.
For this purpose, we make use of the following global application level events:
WindowsAuthentication_OnAuthenticate(Object source, WindowsAuthenticationEventArgs e)
Application_AuthenticateRequest(Object sender, EventArgs e)
These events are raised automatically on each request.
WindowsAuthentication_OnAuthenticate
is raised first. In the corresponding method, we implement the following logic:
- Check whether
authenticationCookie
for the application exists. If so, return from the method. If it does not exist, continue with the next steps.
- Extract the AD-user name sent by IIS. It is available in the event argument as
e.Identity.Name
.
- Query the database for application-roles against this user-name.
- Create a Forms Authentication ticket and embed a string of user roles in it.
- Create a new
applicationauthenticationCookie
and store the encrypted Forms Authentication ticket in it.
Inside the method for the Application_AuthenticateRequest
event, do the following.
- Read
applicationauthenticationCookie
and re-create the Forms Authentication ticket.
- Read the user roles from the Forms Authentication ticket and create an object of the
Principal
object which contains these user-roles.
- Store this
Principal
object in HttpContext.Current.User
.
The following code shows the implementation of these tasks:
protected void WindowsAuthentication_OnAuthenticate(Object source,
WindowsAuthenticationEventArgs e)
{
if(Request.Cookies.Get("authCookie") != null)
return;
string strUserIdentity;
string strUserRoles;
FormsAuthenticationTicket formsAuthTicket;
HttpCookie httpCook;
String strEncryptedTicket;
strUserIdentity = e.Identity.Name;
strUserRoles = GetUserRoles(strUserIdentity); formsAuthTicket = new FormsAuthenticationTicket(1, strUserIdentity, DateTime.Now,
DateTime.Now.AddMinutes(60), false, strUserRoles);
strEncryptedTicket = FormsAuthentication.Encrypt(formsAuthTicket);
httpCook = new HttpCookie("authCookie", strEncryptedTicket);
Response.Cookies.Add(httpCook);
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
FormsAuthenticationTicket formsAuthTicket;
HttpCookie httpCook;
GenericIdentity objGenericIdentity;
myAppPrincipal objMyAppPrincipal;
string[] strRoles;
httpCook = Context.Request.Cookies.Get("authCookie");
formsAuthTicket = FormsAuthentication.Decrypt(httpCook.Value);
objGenericIdentity = new GenericIdentity(formsAuthTicket.Name);
strRoles = formsAuthTicket.UserData.Split('|');
objMyAppPrincipal = new myAppPrincipal(objGenericIdentity, strRoles);
HttpContext.Current.User = objMyAppPrincipal;
}
6.3.6. Checking role based Authorization
On the Page_Load
of each web page, check whether the user current-role available in HttpContext.Current.User
is allowed to access the page. If not, then redirect
to a common page showing the message ‘You are not authorized to view this page’.
7. Summary
- Providing application security is an important aspect of ensuring information security.
- Authentication helps to verify that the user is, in fact, who the user claims to be. The application obtains credentials (various forms of identification,
such as name and password) from a user and validates those credentials against some authority. If the credentials are valid, the entity that submitted the credentials
is considered an authenticated identity. Authorization limits access rights by granting or denying specific permissions to an authenticated identity.
- ASP.NET uses Windows authentication in conjunction with Microsoft Internet Information Services (IIS) authentication. When IIS authentication is complete,
ASP.NET uses the authenticated identity to authorize access.
- In ASP.NET, Windows Authentication can be used along with either ‘Windows role’ based authorization or ‘Custom authorization’. In ‘Windows role’ based authorization,
access to the application folder for Windows users/groups is granted/denied as per the setting in web.config. Whereas in ‘custom authorization’,
this logic is implemented programmatically.
8. Abbreviations
Abbreviation |
Expansion |
AD |
Active Directory |
IIS |
Internet Information Services |
MD |
Master Data |
CST |
Central Support Team |
AM |
Area Manager |
9. Reference