This essentially terminates the user's session in the database and the next time they submit the page they'll be redirected to the login screen. The user will only know that they are logged out once they submit the page. If you have an Interactive Report (IR), or use Partial Page Refresh (PPR) the users won't know they're logged out. Instead it will look as though the report is still trying to load.
Another situation that may happen is that the user is filling out a long form on your page, their session timesout, then they click "submit". They'll be redirected to the login page and they'll lose all the information that they entered.
What if a user wants to extend their session? i.e. they haven't done anything to the page but would like a warning message before we automatically log them out? Or they are entering a log form and don't want to be logged out? I got this idea from the Air Canada web site when I was booking tickets. I really liked the fact that they let me know that they were to end my session, and gave me the option to extend my session.
The following solution will allow you to use APEX's session timeout and resolve the issues listed above. You can view the demo here: http://apex.oracle.com/pls/otn/f?p=20195:2600
Please note that since the demo page is set to public you can refresh after the session is supposed to have timedout and it will still work. If you set the Idle Session in APEX, this will work for pages that require authentication
Here's a high level overview of what this solution does:
- Start a timer (pingApexSession) that will constantly "ping" (therefore refresh) your APEX session every X seconds.
- Start a timer (idleTimer) to detect movement on the page.
- If the idleTimer times out, give the user the option to extend session
- If the user does not extend their session, terminate their session
I haven't put this code into a production application yet. As I mention below, I plan to make a jQuery plugin for this, so if you please send me any feedback that would be useful fur the plugin.
This solution uses jQuery and the following plugins:
- Create Application Process: AP_NULL
- Process Point: On Demand
- Name: AP_NULL
- Type: PL/SQL Anonymous Block
- Process Text: NULL;
- Create Application Process: AP_LOGOUT
- Process Point: On Demand
- Name: AP_LOGOUT
- Type: PL/SQL Anonymous Block
- Process Text:
1 2 3 4 5 6 | BEGIN apex_custom_auth.LOGOUT (p_this_app => :app_id, p_next_app_page_sess => :app_id || ':1' ); END ; |
- Create Region: "Extend Session" on Page 0
- Title: Extend Session
- Type: HTML Text
- Static ID: P0_REG_EXTEND_SESSION
- Region Attributes: style="display:none"
- Region Source: Your session will timeout in: <span id="timeoutCountdownDisplay" style="font-weight:bold"></span>
You can put whatever message you want. Just make sure the span tags exist for the countdown timer
- Create Button: "Extend Session" on Page 0
- Button Name: EXTEND_SESSION
- Text Label: Extend Session
- Display in Region: Extend Session
- Target is a: URL
- URL Target: javascript:gTimeout.timers.killSession.liveFn();
- Create Region: "Session Timedout" on Page 0
- Title: Session Ended
- Type: HTML Text
- Static ID: P0_REG_SESSION_ENDED
- Region Attributes: style="display:none"
- Region Source: Your session has ended. Please login.
- Create Button: "Login" on Page 0
- Button Name: LOGIN
- Text Label: Login
- Display in Region: Session Ended
- Target is a: Page in this Application
- Page: 1
- Create Region: "JavaScript - Session Timeout" on Page 0
- Title: JavaScript - Session Timeout
- Type: HTML Text
- Template: No Template
- Region Source:
1 2 3 4 5 6 7 8 9 10 11 12 | < script src = "#APP_IMAGES#jquery-1.3.2.min.js" type = "text/javascript" ></ script > < script src = "#APP_IMAGES#jquery.simplemodal-1.3.min.js" type = "text/javascript" ></ script > < script src = "#APP_IMAGES#idle-timer-0.7.080609.js" type = "text/javascript" ></ script > < script src = "#APP_IMAGES#jquery.jApex.0.9.2.js" type = "text/javascript" ></ script > < script src = "#APP_IMAGES#jquery.countdown-1.5.3.js" type = "text/javascript" ></ script > < script type = "text/javascript" > //*** Insert script from below ***/ //Removed for display purposes </ script > |
You'll need to upload the JS files beforehand. Please see the list above to obtain the files
Here's the script to put into the region above. I separated them for display purposes.
I probably should have created this as a jQuery plugin. I may convert it later on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | var gTimeout = { //debug debug: false , //Set to True to turn on debugging debugFn: function (pMsg) { if (gTimeout.debug){ console.log(pMsg); } }, //debug modalRegions: { //Region that contains the "Extend Session" information extendSession: { id: 'P0_REG_EXTEND_SESSION' , backgroundColor: '#CCC' , opacity: 70, openFn: function () { gTimeout.debugFn( 'gTimeout.modalRegions.extendSession.openFn' ); // Start display timeout counter $( '#timeoutCountdownDisplay' ).countdown( 'destroy' ); $( '#timeoutCountdownDisplay' ).countdown({ until: '+' + (gTimeout.timers.killSession.time / 1000), compact: true , format: 'M:S' }); // Load modal box to give user option to extend session $( '#' + gTimeout.modalRegions.extendSession.id).modal({ overlayCss: {backgroundColor: this .backgroundColor}, opacity: this .opacity }); return ; }, //openFn closeFn: function (){ gTimeout.debugFn( 'gTimeout.modalRegions.extendSession.closeFn' ); $.modal.close(); return ; } //closeFn }, //Region that will be displayed if the user does not extend thier session sessionEnded: { id: 'P0_REG_SESSION_ENDED' , backgroundColor: 'black' , opacity: 70, openFn: function () { gTimeout.debugFn( 'gTimeout.modalRegions.sessionEnded.openFn' ); // Close Extend Sessios modal window gTimeout.modalRegions.extendSession.closeFn(); // Open Logout modal window $( '#' + gTimeout.modalRegions.sessionEnded.id).modal({ overlayCss: {backgroundColor: this .backgroundColor}, opacity: this .opacity }); return ; } // openFn } //sessionEnded }, //modalRegions timers: { //Ping APEX Session timer will update the database session timer pingApexSession: { id: -1, time: 5000, //Time to keep database session alive. This should be really close to the APEX idle time loadFn: function (){ gTimeout.debugFn( 'gTimeout.timers.pingApexSession.loadFn:' ); this .id = setTimeout( 'gTimeout.timers.pingApexSession.fn();' , this .time); return ; }, unloadFn: function (){ gTimeout.debugFn( 'gTimeout.timers.pingApexSession.unloadFn:' ); clearTimeout( this .id); this .id = -1; return ; }, //unloadFn fn: function (){ gTimeout.debugFn( 'gTimeout.timers.pingApexSession.fn: Extending APEX Session' ); jQuery.jApex.ajax({ appProcess: 'AP_NULL' , success: function (){}, async: true }); gTimeout.timers.pingApexSession.loadFn(); return ; } //fn }, //pingApexSessions //Kill current session. This is called when the user gets the option to extend their session killSession: { id: -1, time: 5000, // Time to kill the APEX session once launched. Should only be run when extend session popup box is loaded loadFn: function (){ gTimeout.debugFn( 'gTimeout.timers.killSession.loadFn:' ); this .id = setTimeout( 'gTimeout.timers.killSession.killFn();' , this .time); return ; }, unloadFn: function (){ gTimeout.debugFn( 'gTimeout.timers.killSession.unloadFn: ' ); clearTimeout( this .id); this .id = -1; gTimeout.modalRegions.extendSession.closeFn(); // Close extendSession Modal return ; }, killFn: function (){ gTimeout.debugFn( 'gTimeout.timers.killSession.killFn: Killing APEX Session' ); // Open Logout modal window gTimeout.modalRegions.sessionEnded.openFn(); // Stop ping Apex session gTimeout.timers.pingApexSession.unloadFn(); // Logout APEX session jQuery.jApex.ajax({ appProcess: 'AP_LOGOUT' , success: function (){}, async: true }); return ; }, // Prevents the session from being killed. We should be in a about to kill state now liveFn: function (){ gTimeout.debugFn( 'gTimeout.timers.killSession.liveFn: ' ); //Check that we're about to be killed if ( this .id == -1){ alert('Session is not marked to be killed '); return; } // Stop the kill timer this.unloadFn(); return; }//liveFn },//killSession // Timer for user movement time idle:{ time: 5000, // Time to load the "Extend Session" popup box loadFn: function(){ gTimeout.debugFn(' gTimeout.timers.idle.loadFn: '); $.idleTimer(this.time); $(document).bind("idle.idleTimer", function(){gTimeout.timers.idle.idleFn();}); // Trigger countdown timer return; }, idleFn: function(){ gTimeout.debugFn(' gTimeout.timers.idle.idleFn: '); // Load modal box to give user option to extend session gTimeout.modalRegions.extendSession.openFn(); // Only load if we' re not in a kill state if (gTimeout.timers.killSession.id == -1){ gTimeout.timers.killSession.loadFn(); } return ; } //idle Fn } // idle }, //timers loadFn: function () { gTimeout.timers.pingApexSession.loadFn(); // Keep database sessions alive gTimeout.timers.idle.loadFn(); // Turn on user idle timer return ; } //loadFn }; //gTimeout $(document).ready( function (){ // Set Parameters gTimeout.timers.pingApexSession.time = 5 * 1000; // Refresh APEX session every 5 seconds. This should be really close to your apex session timeout values gTimeout.timers.idle.time = 10 * 1000; // 10 seconds of inactivity will trigger this window gTimeout.timers.killSession.time = 10 * 1000; // Once the warning message pops up, user has 10 seconds to extend their session // Configure Modal windows (not required) gTimeout.modalRegions.extendSession.backgroundColor = '#CCC' ; gTimeout.loadFn(); }); |
Any input on how to use this for an examination system application as a timer for question? And how to prevent page refresh from resetting the timer? Thanks! Helpful article.
ReplyDeleteYou could implement something that once a user views a question it triggers a timer specific to the timer. The first thing the time would do is detect if it's already been activated. This way if the user refreshes the page they won't get additional time.
ReplyDeleteHi Martin,
DeleteSince the above js files (jApex) is no longer available..do you have any alternative solution for this idle time issue. I saw a skillbuilder plug in but it did not have that flexibility to show the timer counter etc. Thanks for excellent / helpful article.
Thanks,
Kavin
Hi Kavin,
DeleteThey're a few options. You could take the plugin and modify it (the source files are included with the plugin) so that you can show the timer counter. If you wanted to use the code above you'd need to take out the jApex and write custom calls to application processes.
I'd recommend taking a look at the plugin and seeing if you can tweak it for your needs.
Martin
Many thanks Martin for your quick response. Yes, I will try to tweak the plug in.
Delete~K
For the jApex plugin. The jApex sample app at http://apex.oracle.com/pls/otn/f?p=52603 is still operational and it has the jquery.jApex.0.9.2.js plugin still available. Plus you could download it from the example shown above.
ReplyDeleteMore specifically http://apex.oracle.com/pls/otn/wwv_flow_file_mgr.get_file?p_security_group_id=4274532926776640618&p_flow_id=20195&p_fname=jquery.jApex.0.9.2.js
Hello Martin,
ReplyDeletei have implemented your solution and it works!
One thing that nervs me: if the user clicks on the 'Login' Button and are redirected to the Login-Page, the expired message are also generated :-(
I tried several settings (session timeout, idle timeout)but without luck.
Any hint on this?
regards,
Wolfgang
Hi Wolfgang,
DeleteSince this was written Dan has created a plugin that will handle session timeouts. You can download it here. Please try it out to see if it resolves your issue.
Martin
Hi Martin,
ReplyDeleteWe liked the solution provided by you for Session Timeout but unfortunately we have been facing some problem implementing the same.
The issue is that the popup doesn't display when the session timeout happens. This is very critical for our business and any help in resolving this issue will be highly appreciated.
Here is how we implemented the code.
1. Changed the setting - Shared Components / Edit Security Attributes / Maximum Session Idle Time in Seconds to 10 seconds.
2. Copied all the .js files to Shared Components - Images in the Application and changed the code in javascript on Page 0 as follows:
src="#WORKSPACE_IMAGES#jquery-1.3.2.min.js"
Used jquery.countdown instead of jquery.countdown-1.5.3.js. We were unable to find the download for 1.5.3 version of the plugin.
3. Copied the rest of the code for creating regions, buttons and the javascript as is.
Please let us know what we are doing wrong.
Thanks,
RB
A plugin has been created for this. Since this post is old I'd recommend using the plugin: http://apex-plugin.com/oracle-apex-plugins/dynamic-action-plugin/skillbuilders-session-timeout_188.html
DeleteHi,
ReplyDeleteCan you provide some sample code to customize or showing how to use the Session-timeout plugin?
Thanks,
Santosh
Hi Santosh,
DeleteI didn't write the plugin so you'll need to contact its author for samples. I think there's one on the site above.
Martin
hi martin have u created new solution for this issue?? i need a logout or session time out timer with warning for apex 5.0.. any idea?
ReplyDeleteThere is a plugin for this: http://apex-plugin.com/oracle-apex-plugins/dynamic-action-plugin/skillbuilders-session-timeout_188.html
Deletehi martin I used the plugin and i want coundown timer in session out alert pop-up.
ReplyDeletehow it is implemented in it
You'll have to contact the plugin developer or look to merge the code from this post into the plugin to get the countdown timer.
Delete