views:

277

answers:

3

I need to setup an Asp.Net application w/ forms authentication so that it meets the following criteria:

  1. User should log out after 15 minutes of inactivity
  2. User should log out after 24 hours, regardless of activity

I believe the first can be accomplished like so in the web.config:

<authentication mode="Forms">
  <forms loginUrl="Login.aspx" timeout="15" slidingExpiration="true"/>
</authentication>

But how would you go about resolving the second requirement?

+2  A: 

I do not think forms auth in ASP.Net has anything built in to handle this.

You could create a global application class (global.asax), handle the Session_Start event, and store the date/time in a session variable, like so:

public void Session_Start(object s, EventArgs e)
{
    Session["LoginDate"] = DateTime.Now;
}

Then, you can handle the OnBeginRequest event to check the difference between the session variable and the current date/time:

public void Application_OnBeginRequest(object s, EventArgs e)
{
    if (Session["LoginDate"] != null)
    {
        var loginDate = (DateTime)Session["LoginDate"];
        if ((DateTime.Now - loginDate).TotalHours >= 24)
        {
            Session.Abandon();
            Response.Redirect("~/Login.aspx");
        }
    }
}

To handle the OnBeginRequest event, you may need to create a custom HttpModule - see here: http://msdn.microsoft.com/en-us/library/ms227673%28VS.85%29.aspx

A S
Mircea has the better solution!
A S
His is similar to yours: I ended up doing something along these lines (actually stored as part of the identity.name opposed to session)
John
+2  A: 

There's a detailed article on MSDN that explains how Forms authentication works and what are the available configuration options. Basically Forms authentication uses cookies (unless you specifically tell it not to). So you could set the expiration date for your Forms authentication cookies to 24 hours. But there's a catch. You probably need to roll your own Membership code, since by default, the timeout attribute of the forms element is also used to set the lifetime of the persistent cookie. And you don't want that. You'd want to set the expiration for your cookie to 24 hours.

The way it works is that after the user logs in, the Forms authentication cookie is created, and afterwards it's included along with each request until it expires. From the linked article: The Membership Provider has code similar to this when authenticating a user:

if (Membership.ValidateUser(userName.Text, password.Text))
{
    if (Request.QueryString["ReturnUrl"] != null)
    {
        FormsAuthentication.RedirectFromLoginPage(userName.Text, false);
    }
    else
    {
        FormsAuthentication.SetAuthCookie(userName.Text, false);
    }
}
else
{
    Response.Write("Invalid UserID and Password");
}

You can create a Forms Authentication ticket using the FormsAuthenticationTicket class:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
        "cookieName",
        DateTime.Now,
        DateTime.Now.AddHours(24), // value of time out property
        false,
        String.Empty,
        FormsAuthentication.FormsCookiePath);

Forms authentication uses the Encrypt method for encrypting and signing the forms authentication ticket:

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

Create the cookie:

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

Add the cookie to the cookie collection:

Response.Cookies.Add(authCookie);

And that should be about it.

You probably need to roll your own cookie, because by default, the timeout property that you specified for your forms is the one that's going to be used for the cookie timeout. So in your example:

<authentication mode="Forms">
  <forms loginUrl="Login.aspx" timeout="15" slidingExpiration="true"/>
</authentication>

The cookie's timeout will be 15 minutes also. Probably the easier approach in your case would be to handle your enforced 24-hour timeout using a session variable. Since you'd only hit that if the user was actually active during that period (otherwise it would have timed-out from the cookie). So you could just terminate a Session if had been active for over 24 hours.

Mircea Grelus
+1  A: 

Well, as a simple solution you could use the Cache's timeout notification feature as a "reminder"/callback to abandon the session 24 hours after creating it.

void Session_Start(object sender, EventArgs e)
{
  Cache.Add(Session.SessionID,Session,null,DateTime.Now.AddHours(24),
  TimeSpan.Zero, CacheItemPriority.High, OnExpireSession)
}

public void OnExpireSession(String k, Object v, CacheItemRemovedReason r)
{
    //uhm.. maybe do some checks if the session was already abandoned?
   ((SessionState)v).Abandon();
}
Radu094