Issue:  When user profile information is not saved

            When Remember Me does not work for the website

            You keep getting thrown out of the site- logged out

You have tried building a web site with form authentication and you get stuck in one of these three scenarios,

  • You save profiles on one page and when you try retrieving the profile information from another page, it’s empty!
  • The site never lets you be “remembered” even if “ remember me next time” is ticked
  • Your logged out way before than expected,having to sign in again.

Before we get to the resolution let’s try understanding what happens when we have a login control on a page and form authentication set up.

Once you enter the credentials and click on the login button a post back is fired.

1. First Login control’s Logging In event fires.

2. Then Login Control’s Authenticate event is fired. By default, the Authenticate event is handled internally by the Login control using the Membership class’s ValidateUser method to validate the user.

However you can customize the authentication logic used by the Login control, you can create your own event handler for this event. You just need to make sure that you set the e.Authenticated property to True if the user’s credentials are valid, False otherwise.

So once the user is authenticated FormAuthenticationModule will create a ticket for the user, encapsulates it into a cookie and sends it to the user. (Further requests from the user are sent along with the cookie to let the server know that the user is already authenticated.)

  • You enter the credentials in the login page, click on the login button
  • Once the user is validated the FormAuthentication class internally creates a FormAuthentication cookie,

è Creates a ticket

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,
userName, DateTime.Now, DateTime.Now.AddMinutes((double) _Timeout),
createPersistentCookie, string.Empty, strCookiePath);

è Encrypts the ticket

string str = Encrypt(ticket, hexEncodedTicket);

è Creates a form authentication cookie and adds the same to the cookie collection

HttpCookie cookie = new HttpCookie(FormsCookieName, str);
cookie.HttpOnly = true;
cookie.Path = strCookiePath;
cookie.Secure = _RequireSSL;

HttpContext.Current.Response.Cookies.Add(cookie);

  1. If the user is not authenticated due to any reason then the LoginError event is raised.

Else the LoggedIn event is fired.

Cause:

Now you want to write your own custom authentication and create your own ticket.

You would generally do as follows,

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)

{

string username = Login1.UserName;

string password = Login1.Password;

if (username.Equals(localUserName) && password.Equals(localPassword))

{

CreateFormAuthenticationTicket()

e.Authenticated = true;

}

else

     {

     Response.Write("Invalid UserID and Password");

    }

}

Where ,

CreateFormAuthenticationTicket()

{

FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(

1,           //TicketVersion

User,      // Name associated with ticket

DateTime.Now,          // DateTime issued

DateTime.MaxValue,        // DateTime to expire

isPersistent,// If cookie is persistent after browser closure

"User"); // Roles of the User

string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

Response.Cookies.Add(authCookie);

}

You try pulling out the profile information on another page based on the “user” roles from a cookie and instead of pulling out the role you entered it returns no value.

When you have ticked remember me next time, it does not remember you when you try logging in the next time.

The reason being if you have a closer look at the code above, this is what happens

  •  User is validated based on the custom validation
  •  A custom formauthentication cookie is created –the custom ticket as follows,

clip_image001

  •  e.Authenticated is set to true and since user is validated FormAuthentication class will now internally create its own cookie.

We add the following lines to another page, for instance, the page login.aspx redirects you to - this retrieves the cookie and the ticket created by FormAuthentication class,

Httpcookie authcookie=Request.Cookies[FormAuthentication.FormsCookieName];

FormAuthenticationTicket authTicket=FormAuthentication.Decrypt(authCookie.Value);

-the ticket created internally as follows,

clip_image002

If you notice above the cookie is no longer persistent and hence cannot remember you anymore,expires way earlier than expected and also the Userdata is missing preventing you from saving or retrieving profile information based on the roles.

Authenticate event is only used for you to provide custom user validation code logic; it will still use the Login Control’s default code logic to generate authentication cookie.

Resolution:

How do we overcome this? What if we do want to set our custom validation or simply just want to get rid of the above stated issue(s)?

Ø If you want to explicitly set your own custom cookie then, you can use the LoggingIn event. When a user submits his or her login information, the Login control first raises the LoggingIn event, then the Authenticate event, and finally the LoggedIn event.

protected void Login1_LoggingIn(object sender, LoginCancelEventArgs e)
{
//code for generation of custom cookie and custom authentication

string username = Login1.UserName;

string password = Login1.Password;

if (username.Equals(localUserName) && password.Equals(localPassword))

{

CreateFormAuthenticationTicket()

//logic to take care of when the user is validated

}

else

{

Response.Write("Invalid UserID and Password");

}

e.Cancel = true; //stops the internal authentication and cookie generating process
}

NOTE: It’s important that you add e.Cancel so as to prevent the built in cookie generation to discontinue and use your custom cookie and custom authentication instead. If you notice while debugging after e.Cancel is executed it DOES NOT raise the Authenticate event or LoggedIn event.

If you simply want to get rid of the above issue you can use Formauthentication’s setauthcookie method in the Login_authenticate event instead of CreateFormauthenticationTicket( ),

FormsAuthentication.SetAuthCookie(Username, true);

This creates a formauthentication cookie for you.

Where the second parameter is to set a persistent cookie.Just setting the second parameter to true is not enough.

SetAuthCookie has a createPersistentCookie in the constructor but you need to explicitly set the expiration of the cookie.

Either by setting HttpCookie.Expire before adding the cookie to the response.

DateTime dt = DateTime.Now;

TimeSpan ts = new TimeSpan(0,0,10,0);

MyCookie.Expires = dt.Add(ts);

Or by setting the timeout value in the web.config file,

<forms name=".ASPXFORMSAUTH" loginUrl="Login.aspx" timeout=" " />

This automatically creates a cookie which is persistent and you need not worry about having to overwrite the cookies , losing profile information,getting logged out .etc.

These postings are provided "AS IS" with no warranties, and confer no rights.