I'm mucking around with an authentication form that requires some extra authentication data for the user, so rather than using the stock Login control and it's authenticate method I'm using a custom ticket and manually redirecting the data. I'm not sure how this option to stick custom user data into the ticket escaped me until today, but somehow I missed it over the years <s>. This is obviously quite useful in scenarios where you just need one or two small pieces of user information that you'd otherwise have to store in Session or in an associated user table/membership all of which involves some additional overhead. In two busy applications I'm running this will definitely come in hand and remove the need to run sessions altogether. Duh (sound of hand slapping on forehead <g>).
[updated from Comments - 9/23]
Anyway, here's the code I'm using to handle the Login click from the this manual entry form (ie. no Login Control):
protected void LoginButton_Click(object sender, EventArgs e)
{
string username = this.Username.Text;
string password = this.Password.Text;
bool remember = this.RememberMe.Checked;
if (UserObject.AuthenticateAndLoad(username,password) != null)
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
username, DateTime.Now, DateTime.Now.AddDays(10),
remember, UserObject.Entity.UserName);
string ticketString = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticketString);
if (remember)
cookie.Expires = DateTime.Now.AddDays(10);
Response.Cookies.Add(cookie);
Response.Redirect(FormsAuthentication.GetRedirectUrl(username, false));
// *** This works too, although it sends the full page content in addition to Redirect header???
// FormsAuthentication.RedirectFromLoginPage(username,remember);
}
else
{
this.ErrorDisplay.ShowError("Invalid Login. Please make sure you fill in username and password.");
}
}
The authentication seems to work just fine as I get logged into my application, but for some odd reason the cookie is not created as a persistent cookie when the form is submitted. Just for kicks I also created another form with a LoginControl on it and it too doesn't seem to respect the persistance flag when set on the RememberMe var (or the default control).
Well it turns out I skipped setting hte cookie expires code above which makes perfect sense.
The problem here is that it's confusing of where the expiration is exactly applied. Both the ticket and the GetRedirectUrl() contain the expiration information, and so I assumed that ASP.NET was automatically injecting itself in the middle to set the expiration on the cookie explicitly. Not so - even if you use the explicit RedirectFromLoginPage() - if you call that method directly with the persistCookie option to true, ASP.NET will generate a generic (read very long) expiration time.
In short with the explicit ticket you need to be - well, explicit with the cookie and redirect and handle it all yourself. On future accesses ASP.NET might reissue the ticket and THEN it uses the information provided in the original ticket, but only then not on the original request.
Incidentally I ended up here because I also had problems with the plain old Login control not creating a persistent cookie EVEN IF the Remember me checkbox was applied.
This would not work until explicitly adding the slidingExpiration key:
<authentication mode="Forms">
<forms timeout="44000" slidingExpiration="true" ></forms>
</authentication>
Thanks to Bilal who pointed at the link in the comments below that pointed at the solution.
Other Posts you might also like