Oct 28, 2007

Debugging Form Authentication API in asp.net

  FormsAuthentication.RedirectFromLoginPage(UsernameText.Text, false);
This method performs serveral tasks at once:
  1. It creates an authentication ticket for the user.
  2. It encryptes the information from the authentication ticket.
  3. It creates a cookie to persist the encrypted ticket information.
  4. It adds the cookie to the HTTP response, sending it to the client.
  5. It redirects to the user to orignal requested page.

The second parameter of RedirectFromLoginPage() indicates whether a persistent cookie should be created. Persistent cookies are stored on the user’s hard drive and can be reused for later visits. If the value is false and user closes the browser, the cookie is immediately removed. The cookie returned is something like

"Set-Cookie: FormCookie=0AA27321DF30103594921784C0C2D721208FC509952739C2E5530F3BE9F8472E6A68283AF5C7DD539D56D2BD2CC39FCC3E488503B8299BCE04307B934B4B8B5C91224CBDBD81EAB3753F4FDEC0518199; path=/; HttpOnly".

If it is true, it will set the cookie for persisted for the timeout time in the forms tag. The cookie you get is something like

"Set-Cookie: FormCookie=C63E21885ED5930E10A2D10CC262FA0929B68DD467B05566226346CC612DE7728244C8122D8445085616412C45A9B47F2B430F369EA68E5596A9642E4FAD4413AA3D170056130847E175292F01FEED1A; expires=Mon, 29-Oct-2007 04:43:35 GMT; path=/; HttpOnly".

If you want to dynamically set the cookie's expiration date, you need to do manually.

if (FormsAuthentication.Authenticate(UsernameText.Text, PasswordText.Text))
{
            // Create the authentication cookie
            HttpCookie AuthCookie;
            AuthCookie = FormsAuthentication.GetAuthCookie(
            UsernameText.Text, true);
            AuthCookie.Expires = DateTime.Now.AddDays(10);
            // Add the cookie to the response
            Response.Cookies.Add(AuthCookie);
            // Redirect to the originally requested page
            Response.Redirect(FormsAuthentication.GetRedirectUrl(
            UsernameText.Text, true));
}
else
{
            // User name and password are not correct
            LegendStatus.Text = "Invalid username or password!";
}

When you Signout, you will get the response in header

"Set-Cookie: FormCookie=; expires=Tue, 12-Oct-1999 00:00:00 GMT; path=/; HttpOnly".

FormCookie is actually a ticket in a serialized string. You can also manually created the ticket, and then manually create a cooke and assign the cookie value with the ticket string.

private void btnLogin_Click(object sender, System.EventArgs e)
{
            SqlDataReader sdr;
            // Create a connection
            SqlConnection sc = new SqlConnection(Application["DSN"].ToString());

            // Open the database connection
            sc.Open();

            // Create a command to get the user
            SqlCommand cmd = new SqlCommand("GetUser '" + txtEmail.Text + "', '" + txtPassword.Text + "'", sc);

            // Execute the command
            sdr = cmd.ExecuteReader();

            // Attempt to read the first record
            if (sdr.Read())
            {
            // close the datareader
            sdr.Close();
            // Get the list of roles the user is in
            SqlDataReader drRoles;
            SqlCommand cmdRoles = new SqlCommand("GetRoles '" + txtEmail.Text + "'", sc);
            ArrayList arRoles = new ArrayList();

            // Execute the command
            drRoles = cmdRoles.ExecuteReader();

            // Get a string builder to store the roles in a csv list
            System.Text.StringBuilder bldr = new System.Text.StringBuilder();

            // Loop through the list of roles and get them
            while (drRoles.Read())
            {
            bldr.Append(drRoles["Role"]);
            bldr.Append(",");
            }

            // Strip the last comma
            bldr.Remove(bldr.Length - 1, 1);

            // Create an authentication ticket
            // Place a serialized representation of the roles into the authentication ticket
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, txtEmail.Text, DateTime.Now, DateTime.Now.AddMinutes(20), false, bldr.ToString());

            // Get the encrypted version of the ticket
            string strEncrypted = FormsAuthentication.Encrypt(ticket);

            // Put it into a cookie
            HttpCookie hc = new HttpCookie(FormsAuthentication.FormsCookieName, strEncrypted);
            hc.Expires = DateTime.Now.AddMinutes(20);


            // Add it to the cookies collection
            Response.Cookies.Add(hc);

            // Redirect the user to the page they requested
            string strReturnURL = Request.Params["ReturnUrl"].ToString();
            if (strReturnURL != "") Response.Redirect(strReturnURL);
            }
            else
            {
            // Show a message that the credentials are invalid
            lblInvalidPassword.Visible = false;
            }
            }