Showing posts with label Session state. Show all posts
Showing posts with label Session state. Show all posts

Thursday, September 04, 2014

The curious problem of Apex login page session expiration

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.


Did you ever notice that if you open an Apex page requiring authentication but you don't log in during a long time, it may happen that when you finally try, you are bounced back?

That happens because even the Apex login page obeys the session expiration rules defined either at the application level or, in lack thereof, at the instance level.

For example, if the default session duration is 3600 seconds and you don't log in within 3600 seconds, Apex won't accept your credentials and it will reload the login page instead.
But that is not the end of the story: since the session lifetime starts as soon as you load the login page, if the total lifetime is 3600 seconds and you log in after 3500 seconds, there will be only 100 seconds left before Apex kicks you out of the application.

You can easily see this behavior in action if you set a rather short session life time, say 60 seconds, in a test application (don't do this in a production application please).
For your convenience I created a simple demo application on apex.oracle.com

Now, you can work around the problem by setting the session duration to the maximum of 12 hours (43200 secs) in case you don't mind about it or there are no special security requirements. Setting the session duration to a value higher than 12 hours is worthless because there is scheduled job that deletes sessions older than 12 hours anyway.

Or perhaps it could make sense to use this trick: put the (in)famous meta "refresh" HTML tag in the login page header with a reasonable refresh time, so we can ensure that the user is presented always with a fresh login page.

Now, the question is: how much is a reasonable value?
I think it depends on the session lifetime you define.  For short session durations, it must be a small number, for long session durations it can be much larger, for the reason explained above, users surely don't like to be thrown out of the application after a very short time.

For instance, if the total session duration is defined to be 2 hours and you reload the login page every 10 minutes, the user in the worst case will still have 1 hour and 50 minutes available that is roughly 90% of the maximum time. On the contrary, if you refresh every hour, in the worst case there will be just 50% of the time left.

<head>
... 
<meta http-equiv="refresh" content="600;&LOGOUT_URL.">
... 

Again, you can see a second demo app showing how it works. I set the refresh to 20 seconds, in this case.

In case you don't like to hard-code a fixed value, it's possible to retrieve the maximum_session_life_seconds from Apex's dictionary view APEX_APPLICATIONS (Apex 4.0 or better only) and store it in an application item that you can put inside the page header in its substitution string form:

<head>
... 
<meta http-equiv="refresh" content="&LOGIN_REFRESH.;&LOGOUT_URL.">
... 


Application item LOGIN_REFRESH can be calculated in a before header computation that runs only in your login page and you can adjust the value depending on some algorithm, for instance 10% of the session lifetime.

It is worth noting that besides the numerical value I also added LOGOUT_URL substitution variable, because after some tests I realized that this is the only way to avoid reloading the page with the same session number.

Please note that this approach requires that you always specify the maximum session life at the application level, because as far as I know, there is no dictionary view retrieving the instance-wide value.

Monday, February 08, 2010

Tale of a strange quirk in apex session state initialization

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.

Today was a good day because i finally managed to allocate some time and get to the bottom of an old standing issue that I've been encountering at intermittent times during the last five or six years spent developing applications with Apex:

how come that sometimes page item initialization doesn't *always* work as advertised?

In brief, items, page and region items alike, come with a source value attribute that may contain an initialization value. This value can be set in a variety of ways, most common being a static value, a query or a PL/SQL expression.
Now, given Apex defaults, the most frequent usage pattern for an item is to define a source value of type static assignment to be used only when current value in session state is null.

For instance, say we have a region containing an item called P20_MAX_ROWS and we want to initialize it to 11.


Now, say we have a report in a nearby region based on a query like this:
select page_name
from apex_application_pages
where application_id = :APP_ID
and rownum <= :P20_MAX_ROWS
I guess that everybody would expect to see a report displaying a maximum of 11 rows (or less).
What you get instead is an empty report.

In other words, if you have a report containing an item belonging to a different region and this item is used in the WHERE clause, it's very likely that you get an inconsistent or empty report (it depends on the WHERE conditions of course) upon the first loading of the page. Subsequent page loads may not be affected if the page is submitted and session state is consequently updated, hence it's easy to be puzzled by this behavior.

This behavior seems to be "consistent" throughout various Apex releases, including the most recent one, 3.2.1, as shown in the linked test page.

It's interesting to note that:
  1. the type of source value (static, pl/sql expression or sql query) doesn't seem to make any difference.
  2. if we relocate the item inside the report region, the initialization seems to work just fine and the report is generated correctly.
If we cannot relocate the item to the report region, then another workaround is to add a before header computation for initializing the item(s).

This is the way I've always dealt with this problem until now, even without knowing exactly what was wrong with item initialization, but this isn't always the best approach, it's much better to know how and when a certain feature will work or not.

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles