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.
<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:
<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.