Friday, October 06, 2006

Detecting user authentication expiration from an AJAX request

Problem:
How to detect that an AJAX request has been redirected to a login page by the ASP.NET's Forms Authentication?

Background:
Forms Authentication is a standard user authentication is ASP.NET. As a refresher, this authentication scheme utilizes cookie to track whether a user already login. A user requesting a secured page will be redirected to a login page if he/she is not authenticated yet. Once the user is authenticated, the server will redirect to the page that the user originally request.

The Forms Authentication works fine for normal ASPX pages. When the user is idle for a certain amount of time (the default is 30 minutes), the cookie is expired, and the user will be forced to relogin again.

In an AJAX application, the server also behaves the same way. When the cookie is expired, the server will automatically redirect to the login page. However, since the request is made through a XmlHttpRequest object, the browser does not automatically load the login page, instead the content of login page is retrieved by the XmlHttpRequest object.


Solution:
I use a HTTP custom header to differentiate a login page from other pages in the web application. By doing this way, Javascript can easily identify whether an AJAX request has been redirected to a login page (Well... it actually detects whether it receives the login page instead of the expected response).

In the code behind of the login page, add the following code:

// add a custom HTTP header to identify that this is a login page
Response.AppendHeader("IsLoginPage","1");

In the Javascript code, in the function that handles XmlHttpRequest's response, add the code in bold:

xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState==4) {
if (xmlHttp.status==200 && xmlHttp.responseText!=null) {
if (xmlHttp.getResponseHeader('IsLoginPage')=='1') {
alert('Your session has expired. Please relogin again');

} else if (typeof(responseHandler)=='function') {
responseHandler(xmlHttp.responseText);
}
}
}
};


I decided to simply display an alert so that the user is aware of the situation. My expectation is upon receiving this message, the user will explicitly relogin to the application.


No comments: