Forms Authentication


Forms-based authentication is an ASP.NET authentication service that facilitates Web applications to offer their individual logon user identification and do their own credential verification. It is widely used in Web sites to accomplish customized logic for authenticating the users. When a user logs in by means of forms authentication, a cookie is created, allowing you to track the user all through the site.

In this mechanism unauthenticated users are automatically redirected to a login page where they have to provide suitable credentials (e.g., username/password). The application code verifies the submitted credentials. Once the user provides proper credentials and is successfully authenticated, the ASP.NET issues the cookie or token to the user and redirects the user to the actual resource that was formerly requested . Otherwise, the user is redirected back to the login page and informed that the username/password is invalid. This sort of authentication is a popular technique used by many Web sites. Forms authentication is often used for personalization, where content is customized for a known user.

Initially, the server issues a cookie, [9] a small piece of data, to the client. In the consecutive HTTP request the client sends back the cookie to the server, illustrating that the client has previously been authenticated. In the following example we show how to create a simple ASP.NET application that implements ASP.NET Forms authentication. There are three files involved: default.aspx, login.aspx , and Web.config . Initially, the user requests the secured default.aspx page. Since the user is not authenticated, he or she is redirected to the login.aspx page, where the user has to submit the suitable username and password. If the user is authenticated, then he or she is redirected to the original default page. Forms authentication uses the classes found in the System.Web.Security namespace. Therefore, you should add the System.Web.Security namespace to your code.

[9] ASP.NET provides sophisticated hashing and encryption algorithms, which prevents cookie spoofing.

To implement Forms authentication, follow these steps.

  1. Set the authentication mode in the Web.config file.

  2. Develop a Web form to collect the user's credentials.

  3. Store the user's credentials in a file or database.

  4. Authenticate the user against the user's file or database.

In Forms authentication mechanism you can store credentials in any of the following.

  • Web.config

  • XML file

  • Database

Method 1: Storing Credentials in the Web.config File

In this method all the user information is stored in the <credentials> part of the Web.config file that resides in the application root directory. Storing credentials in the Web.config file is suitable and convenient only for simple authentication. This method is not suitable if you allow users to create and maintain their own accounts. In those cases you have to store the username and encrypted password in a separate database or XML file. Develop an ASP.NET Web application using Visual Studio .NET, rename the Web page default.aspx , and add another Web page named login.aspx . Then, configure the Web.config file as shown in the next section.

CONFIGURE <AUTHENTICATION> AND <AUTHORIZATION> SECTION IN WEB.CONFIG FILE

You have to configure the Web.config configuration file as follows and place it in the application root directory (the directory in which default.aspx resides).

 <configuration>   <system.web> //Set the authentication mode to  Forms  .       <authentication mode="Forms"> //Set the form's authentication attributes.          <forms name=".ASPXFormAuth" loginUrl="login.aspx"             protection="All" timeout="15" path ="/"> //Storing the UserID and Password in the credential //section.            <credentials passwordFormat="Clear">                 <user name="Arun"   password="Spiritual" />                 <user name="Ganesh" password="Divine" />            </credentials>          </forms>       </authentication>       <authorization> //Discard the unauthenticated users.         <deny users="?" />       </authorization>     <globalization requestEncoding="UTF-8"        responseEncoding="UTF-8" />   </system.web> </configuration> 

In the credential section we stored the valid usernames and passwords. Within 15 minutes the authentication cookie will expire because we set the timeout to 15 minutes. The cookie will be regenerated after every 15 minutes so that we can lessen the possibility of another user stealing the cookie.

THE LOGIN.ASPX FILE

If the user is unauthenticated, the request is redirected to this login.aspx file. This Web form is identified by name in the <forms> element of Web.config . Import the namespace System.Web.Security . In the design view add two text boxes ( Userid and Passid ) and a Submit button, as shown in Figure 9-2. The login.aspx code is as follows:

 private void Button1_Click(object sender, System.EventArgs e) { /* public static bool Authenticate( string name, string password );   Authenticate Userid and Passid against <credentials> */ if (FormsAuthentication.Authenticate( Userid.Text,    Passid.Text) ) { FormsAuthentication.RedirectFromLoginPage(Userid.Text,    false); } else   {   // Clear the Password text. Passid.Text = ""; Label3.Text = "Invalid User ID and/or Password!"; } } 
Figure 9-2. Login.aspx page where the user has to submit valid username and password.

graphics/09fig02.gif

Here, the code FormsAuthentication.Authenticate(Userid.Text, Pass-id.Text) ensures the username and password provided by the user and returns a boolean value of true if the credentials are valid. It returns false if the credentials are not valid. Then, it creates an authentication cookie, appends it to the outgoing response, and redirects the request to the initial requested page using the code FormsAuthentication.RedirectFromLoginPage(Userid.Text, false) . In this code the second parameter specifies whether the authentication should be a session cookie (false) or a persistent cookie (true). Here we provide it as a session cookie.

THE DEFAULT.ASPX FILE

The default.aspx file is the requested, confined resource. In the default.aspx page we simply display the welcome message and a Sign out button, as shown in Figure 9-3. By employing the FormsAuthentication.SignOut method, you can easily eliminate or invalidate the authentication cookies. The default.aspx code is as follows:

[View full width]
 
[View full width]
private void Page_Load(object sender, System.EventArgs e) { /* Note that in the below code this is chance of a cross site scripting attack unless the graphics/ccc.gif data has been validated before creating the ticket. So the data entered by the user has to graphics/ccc.gif be validated.*/ Label1.Text= "Welcome, "+ User.Identity.Name+"!"+ "You have successfully logged in."; } private void SignOut_Click(object sender, System.EventArgs e) { FormsAuthentication.SignOut(); Response.Redirect("login.aspx"); }
Figure 9-3. Welcome message displayed in the default.aspx page after the user is authenticated.

graphics/09fig03.gif

PROTECTING PASSWORDS WITH ENCRYPTION

It is not recommended to store the password in clear text due to security risks. Even though a user cannot directly access a Web.config file, if the server is accessible over a local network, then there is a possibility of accessing a Web.config file. Therefore, when storing usernames and passwords in a Web.config file or database, you have to encrypt them using the FormsAuthentication class's HashPasswordForStoringInConfigFile method. This utilizes the SHA-1 or MD5 algorithms to encrypt data, as follows:

 Passid = FormsAuthentication.HashPasswordForStoringInConfigFile    Passid.Text,"SHA1"); 

For example, the hash value for the password "Divine" using SHA-1 algorithm is C1FF7FB589DDC7CECD412F515709D8DC2B2B2C22.

You can also protect the sensitive information in Web.config files by using the Data Protection API (DPAPI). For more information on how to use DPAPI from an ASP.NET Web application or Web service to encrypt sensitive data, visit http://msdn.microsoft.com/architecture/application/default.aspx?pull=/library/en-us/dnnetsec/html/SecNetHT08.asp.

Method 2: Storing Credentials in the XML File

In this method all the user information is stored in the XML file. It is impractical to store huge numbers of usernames and passwords in the Web.config file. Storing usernames and passwords in the XML or in a database is preferable. In this method there is no credential part in the Web.config file. The Web.config file is as follows.

 //Set the authentication mode to  Forms  . <authentication mode="Forms"> //Set the form's authentication attributes. <forms name=".ASPXFormAuthxml" loginUrl="login.aspx"    protection="All" timeout="60" /> </authentication> <authorization> //Discard the unauthenticated users. <deny users="?"/> </authorization> 

As we discussed earlier, ASP.NET verifies whether the request is authenticated. If the request is not authenticated, it redirects the request to the login.aspx page. There, the client has to submit the suitable credentials for authentication. The login.aspx page evaluates the submitted credentials to a list of credentials in the Users.xml file. The user is redirected to the original requested default.aspx page if the submitted credentials are found in the Users.xml file. If not, the request is redirected to another page, where the submitted username and password are added in the XML file.

The Users.xml File

The Users.xml file, which encloses the user credentials, is as follows. The UserPassword is encrypted using the FormsAuthentication class's HashPasswordForStoringInConfigFile method (SHA-1 algorithm).

 <Users>     <Users> <UserID>G.A.Gnanavel</UserID>         <UserPassword> 44DD5C3AA9E4E693A9E394DAA5D3F3A449DC25CA</UserPassword>     </Users>     <Users> <UserID>G.N.Vadivambal</UserID>         <UserPassword> FE71C5444F9327DDA2F1D69B7510ABF59B80672F</UserPassword>     </Users>     <Users>         <UserID>G.G.Saratha</UserID>         <UserPassword> CF77B1B76919D5D2B8B79D63FCA5E70383A3D7E5</UserPassword>     </Users> </Users> 

The login.aspx File

 using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Data.OleDb; using System.Web.Security; using System.Web; using System.IO; using System.Web.SessionState; using System.Web.UI; namespace Formsauthenticationxml {   public class login : System.Web.UI.Page   {   protected System.Web.UI.WebControls.TextBox Passid;   protected System.Web.UI.WebControls.Button Button1;   protected System.Web.UI.WebControls.Label Label1;   protected System.Web.UI.WebControls.Label Label2;   protected System.Web.UI.WebControls.Label Label3;   protected System.Web.UI.WebControls.TextBox Userid; public login()      {      Page.Init += new System.EventHandler(Page_Init);      } private void Page_Load(object sender, System.EventArgs e)      {      } private void Page_Init(object sender, EventArgs e)      {      InitializeComponent();      }      #region      //Web Form Designer generated code      #endregion private void Button1_Click(object sender, System.EventArgs e)      { /* Encrypt the password entered by the user to verify against  the encrypted password found in the XML file.*/ string Passidvalue = FormsAuthentication.HashPasswordForStoringInConfigFile    (Passid.Text,"SHA1");        String str = "UserID='" + Userid.Text+ "'";        DataSet ds = new DataSet();        FileStream fs = new FileStream(Server.MapPath("Users.xml"),          FileMode.Open,FileAccess.Read);        StreamReader reader = new StreamReader(fs);        ds.ReadXml(reader);        fs.Close();        DataTable clients = ds.Tables[0];        DataRow[] items = clients.Select(str);        if( items != null && items.Length > 0 )        {          DataRow row = items[0];          String pass = (String)row["UserPassword"];          if (pass == Passidvalue) FormsAuthentication.RedirectFromLoginPage(Userid.Text,    false);          else           Label3.Text = "Please enter a valid password!";        }      else      {      Label3.Text = "Invalid User ID and/or Password!"; /* The request is redirected to another page where the  submitted Username and password will be added to the XML  file.*/ Response.Redirect("adduser/adduser.aspx?UserID =    "+Userid.Text);      }      }   } } 

We read the XML file, which encloses the authenticated credentials and stores the retrieved data in the DataSet ds . Then, we verify the submitted UserID with the list of names in Users.aspx. If we find any value in the XML file, we store it in a DataRow named items . Then we check whether the password value provided by the user matches against the encrypted password found in the XML file. If the password matches, then we redirect the request to the originally requested default.aspx . Otherwise, the request is redirected to another page, where the submitted username and password are added to the XML file. But in real-time applications it is recommended to use a relational database for storing the authenticated users.

Method 3: Storing Credentials in a Database

In this method all the user information is stored in the database file instead of in the Web.config file. The default.aspx and Web.config files are similar to the above method. The only difference is in the login.aspx page. The code for the LoginBtn_Click method in the login.aspx code is as follows.

[View full width]
 
[View full width]
// The below code is only for pedagogical purpose. private void LoginBtn_Click(object sender, System.EventArgs e) { /*SqlConnection conn = new SqlConnection ("Server=(local);" + "Integrated Security=SSPI;" + "database=login");*/ OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data graphics/ccc.gif Source="+"C:\NetSecurity\Chapter9\Formsauthdatabase\ login.mdb"); try { conn.Open(); /* Here in the below code there is possibility of SQL injection if the user input is not properly validated. Therefore validation has to be made before processing the user input.*/ String str = "select count (*) from login where UserID= '" +Userid.Text+ "' and Password= '" + Passid.Text + "' "; /* SqlCommand command = new SqlCommand(str, conn);*/ OleDbCommand command = new OleDbCommand(str, conn); int count = (int)command.ExecuteScalar(); if (count!=0) FormsAuthentication.RedirectFromLoginPage(Userid.Text, false); else Label3.Text = "Please enter a valid password!"; } finally { conn.Close(); } }

While validating user credentials against a database file, consider the following two things:

  • Store one-way password hashes (with a random salt value).

  • Avoid SQL injection when validating user credentials.

In real-time applications, it is not recommended to store passwords (cleartext or encrypted) in the database. The problem with storing encrypted passwords is that it is difficult to keep the encryption key safe. Moreover, if an attacker accesses the key, then he or she can decrypt all the passwords that you store in the database. Therefore, the best method is to store a one-way hash of the password (combine the password hash with a salt value). [10]

[10] Salt value is a cryptographically strong random number.

You can create salt value as follows.

 public static string GenerateSalt(int size) { /* RNGCryptoServiceProvider class in the  System.Security.Cryptography namespace provides random  number generation functionality. */ RNGCryptoServiceProvider crypto = new    RNGCryptoServiceProvider(); byte[] buff = new byte[size]; crypto.GetBytes(buff); return Convert.ToBase64String(buff); } 

You can create a hash value from a given password and salt value as follows.

 public static string GeneratePasswordHash(string passid,    string salt) { string saltpassid = string.Concat(passid, salt); string password = FormsAuthentication.HashPasswordForStoringInConfigFile( saltpassid, "SHA1"); return password; } 
SQL INJECTION

SQL injection means that a user could pass arbitrary, extra (malicious) SQL code, which is typically appended to the valid SQL code. For instance, consider the following code.

[View full width]
 
[View full width]
String str = "select count (*) from login where UserID= '" +Userid.Text+ "' and Password= graphics/ccc.gif '" + Passid.Text + "' ";

If the attacker enters the following for the Passid.Text

 ' ;  Any malicious SQL string 

the above input will execute the malicious SQL string, because the ' (single quotation mark) character indicates that the current string literal in your SQL statement is terminated and the ; (semicolon) character indicates that you are opening a new statement.

To prevent SQL injection, consider the following.

  • Employ a strong validator and validate the user input. For instance, you can limit the size and type of input.

  • Run SQL code with a least-privileged account.

  • Use the Parameters collection when building your SQL statements as follows.

     SqlDataAdapter myCommand = new SqlDataAdapter( "SELECT * FROM login WHERE UserID= @userid", myConn); SqlParameter parm =     myCommand.SelectCommand.Parameters.Add( "@userid     ",SqlDbType.VarChar, 15);    parm.Value= Userid.Text; 


.NET Security and Cryptography
.NET Security and Cryptography
ISBN: 013100851X
EAN: 2147483647
Year: 2003
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net