Wednesday, September 10, 2008

Tags in web.config (Part-1)

Tags in web.config
This blog covers some of the commonly used tags in web.config. In simple term web.configs are ASP.NET configurations maintained in XML format. All the configuration are maintained in the form of XML tags. The first tag which I would like to explain is the one related to the different authentication which can be enabled using web.config. There are many types of authentication which can be used in a web application. They are Anonymous, Windows, Forms, Passport, basic, Certificate, Kerberos and digest. The ones which we are going to enable using web.config are anonymous, windows and forms.

Authentication Tags
Anonymous authentication: Anonymous authentication can be enabled using the following tag

 <authentication mode="none" >

With anonymous authentication enabled anyone can access the website. Most of the websites have anonymous enabled for the pages which can be browsed by all without restriction. Recently I heard a comment from a techie saying that anonymous authentication cannot be enabled through web.config it can be enabled only through IIS. This is not true. With the above tag one can very well enable anonymous authentication.

Now you have given anonymous authentication, what about giving access to people having their login details in your domain network or your company' network. Then you can make use of windows authentication. The tag for the same is as follows

 <authentication mode="Windows" />
Further if you want to restrict some users from accessing you can do the same by extending the authentication tag like the one shown below.
 
 <authentication mode="Windows" />
<authorization>     <allow user=* />
     <deny user="sand" />
</authorization>
 
From the above tag what I mean is all the users except sand should be given unrestricted access. Now say if you want to impersonate the user who has logged in i.e. suppose you have a user named "sandeep" registered in your domain and you want the threads accessing resources in your ASP.NET application take the identity of sandeep and freely access resources then you can use the below tag in conjunction with windows authentication.
 
 <authentication type="Windows" />
<identity impersonate="true"/>
Normally the threads running in Asp.Net have the least privileges and they take the identity of the default Asp.Net account and because of this they may be restricted from accessing the resources on the server. By impersonating the logged in users identity the thread will have more access privileges.

How about giving access to your customers who don't fall in your domain or customers created dynamically?

The answer is making use of forms authentication. By making use of forms authentication you can redirect all unauthenticated requests to your website or to some resources in your website to a page say "login.aspx" and get the user id and password and authenticate user against a database of your choice and give authenticated access to the resources in your website. Forms authentication is a cookie based based authentication system. The tag for the same is given below.

<authentication mode="Forms">
<forms name="FormCookie" loginUrl="Login.aspx" protection="None" timeout="20" requireSSL="false" slidingExpiration="true" defaultUrl="home.aspx">
</forms>
</authentication >
The mode attribute tells that the authentication is forms. Once you specify the mode of authentication is forms then you should provide further details in the "form" tag as shown above. The various attributes used in the form tag are explained below.
 
Attributes Explanation
name Attribute in the form tag tells the system the name of the authentication cookie in which the authentication details will be stored. The default value is ".ASPXAUTH"
loginUrl Is the name of the login/authentication page with path. The default value taken by the system is "login.aspx"
protection Specifies the type of encryption used for storing the authentication cookie details. Default value is All. The allowed values are Encryption, None and Validation.
requireSSL Specifies whether the cookie needs ssl connection to be transmitted. If the property is set to true then the cookies are not returned unless the connection being used is ssl enabled. By default the value is set to false.
timeout Is the time specified in minutes after which the cookie expires. Please refer sliding expiration also.
slidingExpiration The default value is true which means the cookie needs to be refreshed on each and every request and also the cookie expiration time is also reset. All this happens for a single session. Confused? Lets understand with an e.g. If sliding expiration attribute is set to true then the cookie timeout is calculated after the last request i.e. for e.g. suppose a user "A" logs in and he is authenticated at around 8:20 am and the timeout attribute is set to 20 minutes then his cookie will expire by 8:40 am thereby his session. If the user accesses some resource/page in the website say at about 8:30 am then his cookie timeout is reset to 8:50 am. This goes on for further request till his session is closed or timed out or the user logs out. If the slidingExpiration attribute is set to false then the logged in user' session will expire by 8:40 even if he access any number resources/pages in the site. So if slidingExpiration is set to true then the session will be increased by the number of minutes specified in the timeout property after each and every request. The default timeout is 30 minutes.
defaultUrl The url of the page to which the user needs to be redirected after he is successfully authenticated.
 
Above mentioned attribute are some of the commonly used attributes of forms tag.

A small C# sample code showing authentication procedure.
 
 bool authenticated = Authenticate(userName.Text.Trim(),
password.Text.Trim());//Method which will connect to the
database and return true if the user exists.

if (authenticated)
{
    //Getting the authentication section of the web.config file.
    AuthenticationSection authenticationSection =
     (AuthenticationSection)WebConfigurationManager.
    GetSection("system.web/authentication"); 

    /*Retrieving the minutes from the timeout attribute of forms tag of web.config. */
    int timeOut = authenticationSection.Forms.Timeout.Minutes;

    //Creating the authentication ticket.
    FormsAuthenticationTicket authenticationTicket = new
      FormsAuthenticationTicket(1, userName, DateTime.Now,
      DateTime.Now.AddMinutes(timeOut), false, roles);

    //Encrypting the content.
     string encryptedTicket = FormsAuthentication.Encrypt
       (authenticationTicket); 

     /*Creating the cookie with the name retrieved from the web.config name attribute. */ 
     HttpCookie authenticationCookie = new HttpCookie
      (FormsAuthentication.FormsCookieName, encryptedTicket);

     /* Adding the cookie to the response and authenticating the user. */
     Response.Cookies.Add(authenticationCookie);
}
 
Note: The web.config authentication works in conjunction with the authentication set in the IIS and it works on the least privilege concept i.e. the authentication which has the least privilege will take into effect. E.g. the least privileged authentication is the anonymous authentication and if you set anonymous in IIS and windows in web.config the thread will take anonymous as the identity. The below matrix table shows the combination. The table is taken from msdn, the original link can be found here.

Table 1. IIS anonymous authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

-
MACHINE\IUSR_MACHINE
-

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

-
MACHINE\ASPNET
-

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\IUSR_MACHINE
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 2. IIS basic authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 3. IIS digest authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 4: IIS integrated Windows

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext. WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Location Tag
You have enabled forms authentication, now you want some files or folders to have free access or some restriction based on user or their roles, in such a scenario you can make use of the location tag. The syntax is as given below.

<location path="graph">
     <system.web>
          <authorization>
               <allow users="user1, user2"/>
               <deny users="user5"/>
               <allow roles="admin"/>
               <deny roles="normaluser"/>
          </authorization>
     </system.web>
</location>
Using the above tag one can restrict or allow access to pages/resources in a folder. The above e.g. gives access rights to a folder specified in the path attribute of the location tag, similar to this you can give restriction to a file also. Just substitute the path attribute with the file name, suppose you have a file named "restrict.aspx" inside "secret" folder then in the path attribute you can substitute this "secret/restrict.aspx". You can restrict any kind of file and it need not be a aspx page. From the above tag we can infer that we have given some restriction to "graph" folder. We are giving access to users with user ids "user1" and "user2" at the same time if a user with identity "user5" is trying to access some resource in "graph" folder then deny access. You can use * which means all and ? which means unauthenticated users or anonymous users. Also you can restrict users based on their roles also. The roles can be mentioned in the role tags. When one is using * in allow tag care should be taken to put the deny tag before the allow tag else the denial will not work as you want. E.g.
 <location path="graph">
     <system.web>
          <authorization>
               <allow users="*"/>
               <deny users="user5"/>
          </authorization>
     </system.web>
</location>
The above statement will allow user with identity "user5" to access the resources within graph folder. The reason which I think why this is happening is once ASP.NET comes across * symbol it is by default allowing everyone whether the user is in the denied list. If the above restriction has to work correctly then one has to put the deny tag before the allow tag as shown below.
 <location path="graph">
     <system.web>
          <authorization>
               <deny users="user5"/>
               <allow users="*"/>
          </authorization>
     </system.web>
</location>
Restricting access based on roles
Sometimes you would like to allow access to resources based on user’s roles. To allow access based on an user’s roles put the following tag in web.config.
 

<location path="AdminFolder">
     <system.web>
          <authorization>               
               <allow roles="admin, superadmin"/>
          </authorization>
     </system.web>
</location>

The above tag will allow access to the “AdminFolder” to users who belong to either the “admin” or “superadmin” role. To add roles to a logged in user, place the following code in authentication routine of your system.
 

//After validating the user create an authentication ticket. 
FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1, "[USERNAME]", DateTime.Now, DateTime.Now.AddMinutes(15), false, "[ROLE]"); 
FormsIdentity fi = new FormsIdentity(fat); 
/*get the roles from the database and assign the string values to the GenericPrincipal.The second argument of GenericPrincipal takes a string array of roles.  */
System.Security.Principal.GenericPrincipal gp = new System.Security.Principal.GenericPrincipal(fi, new  string [] {"Manager", "admin"}); 
HttpContext.Current.User = gp;

In the above code once the user is successfully validated against a database we are creating a FormsIdentity object using the FormsAuthentication ticket object. Once that is done we are creating a GenericPrincipal object and passing the FormsIdentity and the roles of the user as a string array. One can retrieve the roles from the database and populate the same in a string array and can pass the same as argument.
To be Continued.....

Know more.

Sandeep