Implementing session timeout in your ApEx app – Part 1
![]()
This entry talks about one method
for causing users to timeout of your
application after a period of inactivity.
STEP 1 – Create your USERS table
From SQL Workshop, run the following:
CREATE TABLE users (id NUMBER, username VARCHAR2(30), last_active_date DATE);
And then, once the table is created, populate it with a user:
INSERT INTO users (id
,username
,last_active_date)
VALUES (1
,'ANDY'
,'01-JAN-2008');
(Change the value of ‘ANDY’ to be the username of a user that exists. For example, if you are using ApEx Standard Authentication then change it to be the username of an ApEx user.)

STEP 2 – Create the APP_USERS package
From SQL Workshop, run the following to create the package specification:
CREATE OR REPLACE PACKAGE app_users
IS
c_session_timeout_minutes CONSTANT number(2,0) := 20;
PROCEDURE set_last_activity_date;
FUNCTION is_session_valid
RETURN boolean;
END app_users;

From SQLWorkshop, run the following to create the package body:
CREATE OR REPLACE PACKAGE BODY app_users
IS
PROCEDURE Set_Last_Activity_Date
IS
PRAGMA AUTONOMOUS_TRANSACTION;
l_current_user VARCHAR2(30);
BEGIN
l_current_user := v('APP_USER');
UPDATE users
SET last_active_date = sysdate
WHERE username = l_current_user;
COMMIT;
END;
FUNCTION Is_Session_Valid
RETURN boolean
IS
l_current_user VARCHAR2(30);
l_is_session_valid VARCHAR2(1);
BEGIN
l_current_user := v('APP_USER');
SELECT CASE
WHEN (last_active_date + APP_USERS.c_session_timeout_minutes/1440) < sysdate THEN
'N'
ELSE
'Y'
END
INTO l_is_session_valid
FROM users
WHERE username = l_current_user;
IF l_is_session_valid = 'N' THEN
return false;
ELSE
return true;
END IF;
END;
END app_users;

Step 4 – Create a user-friendly “Session timed out” page
Create an ApEx page and set its “Authentication” Security Setting to “Page is Public”. This page should contain a helpful message for the user indicating that their session has timed out. Make a note of the ID of this page (we’ll assume this is page 3 for this example).

Step 5 – Modify Authentication Scheme
Click “Shared Components > Security > Authentication Schemes” in Application Builder and select your authentication scheme.

Enter the following into the “Post-Authentication Process” field:
APP_USERS.set_last_activity_date;

Also, within this screen, set the Session Verify Function to be:
BEGIN
IF APP_USERS.is_session_valid THEN
APP_USERS.set_last_activity_date;
return true;
ELSE
OWA_UTIL.redirect_url(
owa_util.get_cgi_env('request_protocol')||
'://'||
owa_util.get_cgi_env('server_name')||
':'||
owa_util.get_cgi_env('server_port')||
owa_util.get_cgi_env('script_name')||
'/wwv_flow_custom_auth_std.logout?p_this_flow='||
:APP_ID||'&p_next_flow_page_sess='||:APP_ID||':3');
RETURN false;
END IF;
END;
In the above code, replace 3 with whatever the ID of your helpful “Your session has timed out” page is.
Step 6 – Finished, have a cup of tea
Now, whenever a user has been inactive for more than 20 minutes and they try to access another page in your application, they will be logged out and taken to a page indicating that there session has timed out.
Next time I’ll write about how we can make an ApEx application popup a message just before a user’s session is about to time out, giving them the option to remain logged in. You can now see the second part here.
on October 30, 2008 on 8:43 pm
[...] in your ApEx app – Part 3 This entry builds on the session timeout functionality described in part 1 and part 2. Be sure to check those posts out [...]
on October 30, 2008 on 7:50 pm
Jerry,
I have just retested the package spec and package body code to make sure it compiles and indeed it does. See below a copy of the SQL*Plus session I just ran to compile it. If you typed the code manually into SQL*Plus or SQL Workshop, you might like to try copying and pasting instead.
SQL> create user andytest identified by andytest;
User created.
SQL> grant connect, resource to andytest;
Grant succeeded.
SQL> conn andytest/andytest
Connected.
SQL> CREATE TABLE users (id NUMBER, username VARCHAR2(30), last_active_date DATE);
Table created.
SQL> CREATE OR REPLACE PACKAGE app_users
2 IS
3 c_session_timeout_minutes CONSTANT number(2,0) := 20;
4 PROCEDURE set_last_activity_date;
5 FUNCTION is_session_valid
6 RETURN boolean;
7 END app_users;
8 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY app_users
2 IS
3 PROCEDURE Set_Last_Activity_Date
4 IS
5 PRAGMA AUTONOMOUS_TRANSACTION;
6 l_current_user VARCHAR2(30);
7 BEGIN
8 l_current_user := v(‘APP_USER’);
9 UPDATE users
10 SET last_active_date = sysdate
11 WHERE username = l_current_user;
12 COMMIT;
13 END;
14
15 FUNCTION Is_Session_Valid
16 RETURN boolean
17 IS
18 l_current_user VARCHAR2(30);
19 l_is_session_valid VARCHAR2(1);
20 BEGIN
21 l_current_user := v(‘APP_USER’);
22 SELECT CASE
23 WHEN (last_active_date + APP_USERS.c_session_timeout_minutes/1440) < sysdate THEN
24 ‘N’
25 ELSE
26 ‘Y’
27 END
28 INTO l_is_session_valid
29 FROM users
30 WHERE username = l_current_user;
31 IF l_is_session_valid = ‘N’ THEN
32 return false;
33 ELSE
34 return true;
35 END IF;
36 END;
37 END app_users;
38 /
Package body created.
on October 9, 2008 on 2:24 pm
Your STEP 2 code does not compile!
Error at line 15: PLS-00103: Encountered the symbol “’” when expecting one of the following:
( ) – + case mod new not null others
table avg count current exists max min prior sql stddev sum
variance execute multiset the both leading trailing forall
merge year month DAY_ hour minute second timezone_hour
timezone_minute timezone_region timezone_abbr time timestamp
interval date
1. CREATE OR REPLACE PACKAGE BODY app_users IS
2. PROCEDURE Set_Last_Activity_Date IS
3. PRAGMA AUTONOMOUS_TRANSACTION;
on July 28, 2008 on 8:36 pm
Thanks for this post. I need to implement this in my app and was wondering the best way to achieve it.
on April 4, 2008 on 11:01 am
[...] in your ApEx app – Part 2 This entry builds on the session timeout functionality described in part 1. Be sure to check that out first. In this one I describe how to get your application to popup a [...]
on April 3, 2008 on 5:27 am
Nice post Andy