Check authentication ticket expiration without affecting it

2.1k views Asked by At

I am trying to implement a Web Application Project where my web pages can check the server for the Authentication ticket expiration date/time using AJAX.

I am using Forms Authentication with slidingExpiration.

The problem I run across is I can't figure out how to check the value without resetting it. I created a simple page - CheckExpiration.aspx - below is the code behind:

  private class AjaxResponse
  {
     public bool success;
     public string message;
     public string expirationDateTime;
     public string secondsRemaining;
     public string issueDate;
  }

  protected void Page_Load(object sender, EventArgs e)
  {
     AjaxResponse ar = new AjaxResponse();
     JavaScriptSerializer js = new JavaScriptSerializer();

     if (HttpContext.Current.User.Identity.IsAuthenticated)
     {
        FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
        string expiration = id.Ticket.Expiration.ToString();

        TimeSpan timeRemaining = id.Ticket.Expiration - DateTime.Now;

        ar.success = true;
        ar.expirationDateTime = expiration;
        ar.issueDate = id.Ticket.IssueDate.ToString();
        ar.secondsRemaining = timeRemaining.Minutes.ToString() + ":" + timeRemaining.Seconds.ToString();
     }
     else
     {
        ar.success = false;
        ar.message = "User not authenticated";
     }

     string output = js.Serialize(ar);
     Response.Write(js.Serialize(ar));

  }

I call this page from the Master page in my application using ajax every second. Past the halfway point in the authentication expiration, the expiration gets reset.

How do I prevent this behavior? Is there anything I can do in the header of the request maybe?

2

There are 2 answers

0
0x1mason On

Why don't you store the expiration as a session variable that you compute yourself? You only need to get the value of id.Ticket.Expiration once. Then each call, get the value from the server and increment it accordingly, and store it back on the server.

http://msdn.microsoft.com/en-us/library/ms178581%28v=vs.85%29.aspx

Pseudocode:

if(!Session.KeyExists("Expiration"))
{
  Session["Expiration"] = id.Ticket.Expiration;
}

Session["TimeRemaining"] = Session["Expiration"] - DateTime.Now;

// get all ajaxy here
0
Steve P On

Put your CheckExpiration.aspx page in its own application and deploy this as a virtual directory beneath your main application. In that virtual directory, configure slidingExpiration=false. Your code will work as-is but will not regenerate the ticket when it gets below half the time until expiration.

Here's what I did in a quick local project to verify that it works:

  1. Created a new web application AuthTest4 and configured it to use local IIS server in path /AuthTest4
  2. Went into IIS and changed the Machine Key setting for /AuthTest4 to uncheck all the AutoGenerate/Isolate options and generated its own MachineKey.
  3. Created an empty web application ExpCheck and put your CheckExpiration.aspx code in it
  4. Configured ExpCheck web application to use local IIS in the virtual directory /AuthTest4/ExpCheck
  5. Modified the web.config of ExpCheck application to have only the section shown below

ExpCheck web.config. All other security settings will cascade down from the parent virtual directory.

<system.web>
  <authentication mode="Forms">
   <forms slidingExpiration="false" />
  </authentication>
</system.web>