Twitter: raymondcamden


Address: Lafayette, LA, USA

Using JavaScript to warn a user about a session timeout

09-20-2006 32,619 views JavaScript, ColdFusion 41 Comments

A coworker asked me this today so I thought I'd whip up a quick example. Many bank sites like to use a JavaScript warning to let you know when your session is about to end. Personally these things bug the heck out of me, but in the interest of helping her out (and others), here is a way to do it in ColdFusion and JavaScript. (Explanation follows the code.)

view plain print about
1<!--- Minutes into MS --->
2<cfset sessionTimeout = 2>
3<html>
4
5<head>
6<title>Timeout Example</title>
7
8<script>
9<cfoutput>
10var #toScript((sessionTimeout-1)*60*1000,"sTimeout")#
11</cfoutput>
12setTimeout('sessionWarning()', sTimeout);
13
14function sessionWarning() {
15    alert('Hey bonehead, your session is going to time out unless you do something!');    
16}
17</script>
18
19</head>
20
21<body>
22
23</body>
24</html>

Let me go down line by line. First off - you can't introspect an application to see what the session time out value is. (I'm sure you could with ServiceFactory methods, but that's cheating.) So I'm using a variable to stand in for the number of minutes a session will last.

view plain print about
1<cfset sessionTimeout = 2>

I would probably have set this in the application scope somewhere, but again, this is just a simple demo. I used 2 to make it a bit quicker to test. Now I need to get that value into JavaScript, but there are two things I need to change. First - I want to give the user a warning so she has time to do something. So, I subtract one from the number of minutes. You can obviously subtract more or less depending on how much of a warning you want to give. Secondly, the JavaScript code I'm going to use, setTimeout, expects time in milliseconds. So I take my number of minutes and multiply it by 60 and then 1000.

view plain print about
1<cfoutput>
2var #toScript((sessionTimeout-1)*60*1000,"sTimeout")#
3</cfoutput>

Why didn't I just multiply by 60000? Because I'm dumb and tend to forget things. The 60*1000 helps me remember. What is the toScript function? It lets you convert a ColdFusion variable into a valid JavaScript variable. For more information, check the toScript documentation. Honestly, it's a bit overkill for what I'm doing, but I thought I'd remind folks of this cool little utility. The next line simply tells JavaScript to call my function in the proper number of seconds:

view plain print about
1setTimeout('sessionWarning()', sTimeout);

Lastly, my "warning" function is a simple alert. You can use DHTML instead of an Alert or any other JavaScript obviously. But the alert is the simplest way to get your message across.

view plain print about
1function sessionWarning() {
2    alert('Hey bonehead, your session is going to time out unless you do something!');    
3}

There ya go. To use this on your site you could simply include it in your layout code. Of course, you want to ensure it isn't loaded if the user isn't logged in.

41 Comments

  • Commented on 09-20-2006 at 3:55 PM
    Nice post Ray. Along those same lines, I have been fooling around with the idea of allowing users to set up a "heart beat" Javascript method. This would be for admin-type sections, not for the public. The idea is that a user could opt to be kept logged in (via a user pref. page) by having a Javascript method that Pings the app every X seconds.
  • Commented on 09-20-2006 at 4:00 PM
    I think in the old days (app.cfm, not app.cfc), you could cheat and rerun the cfapp tag with a different timeout. ;) I think. Just ignore me, that's a bad idea. :)
  • Commented on 09-20-2006 at 4:02 PM
    Yeah, I dont think you can do that anymore. I was recently experimenting with that idea to see if I could force kill an applicaiton / session by re-running the app tag with zeroed-out timespans.

    No luck.
  • Commented on 09-20-2006 at 4:04 PM
    Lord forbid CF make that easy for us. Along with getSessions(), etc. (Ok, I won't complain about that again.)
  • Commented on 09-20-2006 at 4:26 PM
    I had this idea for using a CFHTTP page grab sending CFID/TOken in the URL... as in:

    <cfhttp url="http://.....kill.cfm?cfid=##&cftoken=##"; />

    Then that page would define the CFApplication tag with no timespan (or < 1 second or something). I never got it to work though. I think part of the problem was that the calling page (page performing CFHTttp) has the same session (in my testing). I would need to set up a scheduled task that did not have a session do call something like that... but then it wouldnt have access to the original CFID/CFTOKEN...

    ok, now I am rambling.
  • Sami Hoda #
    Commented on 09-20-2006 at 5:50 PM
    How effective is this when a user open a new tab and now has two windows open with the app? I'm assuming you will get two different pop-ups at two different times, and the first one will not be an accurate representation of the time left in the app. Is that correct?
  • TJ Downes #
    Commented on 09-20-2006 at 6:38 PM
    Just a word on the Javascript setTimeout function. I love it, but recently i wreaked havock on one of my apps. I was using setTimeout for a timed page redirect to serve up some PDF files created by CFDOCUMENT. These pages contained cfcontent and cfheader tags. For weeks I could not figure out why images where not appearing on my pages. With further testing I removed the setTimeout function and the images worked perfectly.
  • Commented on 09-20-2006 at 7:53 PM
    Sami: Absolutely. Most likely that would be the rare case though.
  • Commented on 09-20-2006 at 8:46 PM
    Could do something crazy. Like use a popup div rather than a alert. The let the user continue his session if before time out. If timeout passes, have him login before posting the content of a large form. AJAX is a marvelous thing!
  • Commented on 09-20-2006 at 9:57 PM
    Ray,

    GetSessions()... now THAT would be cool... I have SEVERAL uses for that
  • Rob Pilic #
    Commented on 09-21-2006 at 11:34 AM
    Hi Ray - I do this with a div popup and I do introspect the app for the session timeout: this.sessiontimeout returns the timeout in seconds. Maybe this is only an option with Application.cfc.
  • Sami Hoda #
    Commented on 09-21-2006 at 11:41 AM
    @Rob,

    I'd love to see that if possible.
  • Commented on 09-21-2006 at 1:01 PM
    rob: the problem though is that you wouldn't have access to that outside of the app.cfc file. You would need to do something like this in onapplicationstart:

    application.stimeout = this.sessiontimeout
  • Rob Pilic #
    Commented on 09-21-2006 at 1:39 PM
    Ray: are you sure? If I dump the 'this' scope on any page I see everything in app.cfc, including the on-event methods. I have an include file for the javascript session timer stuff that refences this.sessiontimeout directly and it seems to work ok, though now I am getting nervous :-)

    Sami: I did this a while ago so I am grimacing a bit as I look at it now, but essentially I have a table with my alert message that is hidden off the browser screen (visiblity:hidden; left:-100px, top:-100px;). Then I set the timeout value on the page:

    timeout = (this.sessiontimeout * 1000) - 1500

    I give them an extra minute plus so the CF session doesn't end before they can respond to the alert. When the session timer runs down I change the class of the table so it's visible and give the user 60 seconds to respond. If the 60 second timer runs down without any response from the user, I location.href them to a page that clears their session and displays a message that they have been automatically logged out. I like this because this way they won't fill out a long form and click submit, only to be told that their session has expired. I'd be glad to send you the code, just shoot me an email at robertpilic AT yahoo DOT com if you're interested.
  • Rob Pilic #
    Commented on 09-21-2006 at 1:49 PM
    Woops I should've copied and pasted - it's actually

    timeout = (this.sessiontimeout * 1000) - 90000
  • Commented on 09-21-2006 at 2:48 PM
    Ah - you have the onRequest method. One of the "side effects" of using onRequest is that it copies the app.cfc stuff to the page. If you don't use onRequest (which most folks don't), then you don't have that.
  • Rob Pilic #
    Commented on 09-21-2006 at 3:11 PM
    Ah yes, I see that now in livedocs as well. I think I'll switch to your suggestion of doing something like application.stimeout = this.sessiontimeout in app.cfc. I don't want a "side effect" in production code. Thanks for the tip!
  • Commented on 09-22-2006 at 12:06 PM
    Hey Ray, I have been wanting to something like this for a long time. I just implemented this at my work, and it works great!

    Thanks...
  • dave #
    Commented on 11-09-2006 at 11:16 AM
    Hi, is there a way to get value of Session time out, no matter it is set in Cf adminstrator or application.cfc?
    Thanks,
  • Commented on 11-09-2006 at 1:40 PM
    I don't think so. I'm sure you could via ServiceFactory, but I wouldn't recommend that. I'd just store it as a variable.
  • dave #
    Commented on 11-09-2006 at 2:09 PM
    Hey, Ray,
    Thanks for the response so quickly. I might not state my throught clearly.
    Anyway, You said you would like to store it as a variable. How to do this? I am still using CFMX 6.
  • Commented on 11-09-2006 at 2:12 PM
    If you look at my first code block, you will see I hard coded sessionTimeout. You would just change 2 (the number of minutes) to the real number for your application.
  • dave #
    Commented on 11-09-2006 at 4:26 PM
    Oh, ok, hard code.
  • Commented on 11-18-2006 at 8:48 PM
    Dude!
    Do an iTunes search for "javascript".
    There's actually a song called "Javascript Functions".
  • Commented on 11-19-2006 at 9:51 PM
    Scary.
  • valerie #
    Commented on 12-28-2006 at 3:09 PM
    How can you insure thie alert is on top of any programs you have open? Is that possible? You know we have mulitple apps open at once. It would be good to actually see the reminder no matter program you are in?
  • Commented on 12-28-2006 at 10:22 PM
    I think it depends on the OS and your settings. For me, a browser alert will NOT take over focus if I am using another app, and that is nice. (Personally I despise it when an application steals focus. No one app should be able to stop you using another app.) At minimum it should be on top when then browser is being used.
  • JC #
    Commented on 03-01-2007 at 5:16 PM
    I don't have CF 7.0. Is there anything similar toScript in previous versions?
  • I Rz #
    Commented on 03-23-2007 at 12:54 PM
    @JC
    I don't know why no one thought your question was worth a response, but you can try this:

    sessionTimeout = 60000 see above

    var sTimeout = #sessionTimeout#
  • Kevin #
    Commented on 05-08-2007 at 2:40 PM
    I'm trying to use a confirm dialoge box to continue the session, but I'm having this problem - while the dialogue box is open, the session timer is stopped. So if the person really did walk away and leave the window open, it never times out and the next person can come along a day later and continue their session.
    How can I make the dialogue box itself time out if it gets no response?
    ----
    var revive = window.confirm("Your session is about to time out. Do you want to continue?");
       if(revive){
    var imgAlive = new Image();
       var d = new Date();
       imgAlive.src = 'alive.cfm?d=' + d;
       }else{
        location.replace("App_Instructions.cfm");
       }
  • Kevin #
    Commented on 05-08-2007 at 3:50 PM
    ..nevermind, the whole dialogue box thing was clumsy and annoying, anyway. I just made my own timer, and put it at the top of the page with a reset button next to it.

    If the user doesn't pay attention to it, it's their own fault.

    ----
    For security, page will time out in
    <input type="button" id="timebtn" value="20 minutes 0 seconds." onClick="keepAlive()">
    Click button to reset timer and continue entering data.
  • kapitannwel #
    Commented on 02-19-2008 at 9:46 PM
    I have a page wherein i need to logoff user by querying database after some idle time. thank you for this.
    i greatly appriciate it.
  • Gers #
    Commented on 05-07-2009 at 11:30 AM
    I know this is an older post, but very helpful to me. Thanks very much.
  • Gers #
    Commented on 08-19-2009 at 4:11 PM
    Anyone else have problems with this not working any more on the new Safari 4.0.3?
    I get logged out as soon as I touch the browsers back button.
  • Dan Fredericks #
    Commented on 02-17-2010 at 1:27 PM
    Ray,
    I implemented this code, however it seems to not recognize when I start typing on the page, or click on a url link. Shouldn't the code know if I started using the form again? Does this not start my session again, or do I actually have to hit a refresh button or some save button on the page to restart my session?
  • Commented on 02-17-2010 at 2:18 PM
    Typing on a form does nothing to update a user's session. Typing in a form is client side. Submitting a form is server side.
  • emmy smith #
    Commented on 04-02-2013 at 11:42 AM
    pls sir, i need your help, am running a hotspot intenet cafe, on mikrotiik os, and i need alert timeout left time for my users, how best , can i implement this .
    thank u
    emmy
  • Commented on 04-02-2013 at 11:47 AM
    Sorry, I've got no idea what Mikrotiik OS is.
  • Commented on 06-18-2013 at 11:34 AM
    Ray, great stuff! This works beautifully in my back-end web application for my company's employees.

    Question: Are you aware of a way to check on the session timeout without resetting the timeout clock? Often users of our back-end system will have multiple windows open which causes the session warning to be inaccurate. My original plan was to do an AJAX post and check on the session and then react accordingly, but obviously if I did an AJAX post and the session did not expire, then I just reset the timeout clock leaving the user logged in indefinitely.

    Any information you can provide would be great! Thank you.
  • Commented on 06-18-2013 at 2:00 PM
    I did a bit of research into this. Apparently the only way to do cookie-less ajax calls is to use a subdomain that didn't have cookies on it (I mean use a subdomain just for the ajax call).

    That's an option, but probably not terribly simple.

    You could also use websockets to broadcast out the state, but you would need to keep a copy of the info (sessions + timeout) in the application scope.
  • Commented on 06-18-2013 at 2:54 PM
    Thank you, Ray. I will have to look into this in more detail.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty