Background:
Back at work, I’m working on a Web Forms App that uses default, sliding expiration for Session and FormsAuthentication time outs. My task is to track user inactivity and , if needed, display modal window with a warning about session expiration, timer and a button to refresh session time out (it would refresh forms authentication time out also). Button is wired to the event on the master page with an empty body, it does the job for now. (I’m aware of other solutions).
Partially working solution:
My approach was to use master page Page_PreRender method to get Session and FormsAuthentication time out values, compare them and pass smaller(or any) value to the client’s browser (with other necessary data). In the browser, I would then display warning with the timer at some particular moment in modal window and it would all work as intended… that is…when the user is doing nothing.
Problem:
Our app has lots of pages with update panels. Those update panels are used to interact with and manipulate data stored in the Session. Whenever user does something inside one of those update panels, the session time out slides (restarts). I cannot track those things on the client (in the real world), I need a way to track Session expiration on the server.
Things I don’t want to do
I dont’ want go through every single page, every single gridview, every single imagebutton etc and to bind some client event to track user actions. I want more… generic and maintainable solution if possible.
My idea:
I would like to be able to track/check Session or FormsAuthentication remaining time before expiration occurs OR to be notified if those values have been reseted. That way I could have initial data on the client about the moment in time when I should display the modal window with warning, and at that time, I would like to be able to check with the server first IF that time is right (approximately) or if I should update my javascript data on the client and prolong the time before displaying warning window since the session expiration has been updated…
And what about intercepting and filtering user requests ? Would that help ?
First of all, thank you all for your suggestions. I’ve managed to solve this problem last week, just didn’t had time to post earlier… and frankly, I was interested in other solutions. I’ll make sure to read all the material you posted and suggested. Thank you for that.
Here’s what I did:
On the server side:
I used cookies to track session expiration time. One thing that slipped my mind was that Page goes through its whole life cycle even on asynchronous requests. The whole idea was to use Master Page’s Pre_Render event to set the appropriate cookies on EVERY request.
I was using UTC time format and was calculating milliseconds that are translatable to javascript time format :
With this, I had everything I needed for my calculations, current time, session expiration (Session.Timeout) time, and time for warning… basic math from there.
On the client side:
First, I red all three cookies to start tracking up and initialized two separate variables for tracking current server time. They were both initialized to the same value of the first cookie read of the current server time.
Then, I’ve used setTimeout function to read cookie (current server time) every second (jQuery plug-in). I was checking if current server time from former cookie read and current server time from latest cookie read were equal(separate variables) – that way I knew if there were any requests made and if there were, I would read 2 other cookies for warning time and time-out time to update things up and close warning dialog if it was opened. After that I would make current server time variables equal and continue comparing them after every cookie read and updating only one of them.
Also, on every setTimeout call I’m getting current time with
which returns current UTC time measured on the client machine. In any case we rely on the presumption that client has valid clock set-up on his/her machine. After that I’m comparing current time with warning time and if current time is “bigger” that the warning time and “smaller” than the time-out time, then we have to display popup.
If the current time is “bigger” than the time-out time, click invisible button that calls method in the masters page code behind that logs out user. This works great even when user has multiple tabs open in browser. Once the user is logged out in one tab, every other page(tab) that tries to log him out also, gets redirected to login page.
If the user click OK button to confirm his/her presence, an empty event in masters page code behind is triggered (click hidden asp button). This is enough to refresh the session. This will automatically resend cookies, and everything goes as intended. (given that you have sliding session).
It was easy to implement timer in the warning window. I’ve dynamically created div for modal window with message and 3 spans. On every setTimeout iteration I was setting timer like this:
For The End
Make sure that, when you are reading cookies to parse them as floats, just to be sure.
I’m interested to see the application of server push technology and usage of web sockets in this particular situation but I think it would be an overkill if you would track and calculate session expiration on the server for every client.
I know that I’ve asked for session expiration tracking on the server and that this looks like tracking on the client, but it’s not… those cookies are all we need for tracking and they come from server so… that’s about it.