Monday, July 04, 2016

APEX session isolation across multiple browser tabs - Problem Solved (in APEX 5.1)

Since the genesis of Oracle Application Express, customers have asked for a way to open multiple browser tabs (or windows) of an APEX application and have the session state isolated between the respective tabs.  There is one and only one APEX session associated with a client, and because of this behavior in APEX, customers would find that the session state manipulated in one browser tab would collide with the session state of the other browser tab.

This has always been a vexing problem to solve for many years.  Back in 2007, I remember Carl Backstrom had spent countless hours researching for some handle or unique identifier to a browser window that we could correlate with a distinct browser session cookie, but he was never able to identify a feasible solution.  Customers have long asked for a solution, but all we were able to propose were rather cumbersome work arounds (ensure all items necessary for session state were posted with the page, or use the multiple DNS aliases "trick" for each tab).

In October 2015, our friends from BiLog arranged an informal meeting with a couple large enterprise customers from Croatia.  Goran, who was from one of the enterprise customers in the insurance industry, stated that the session management behavior of APEX presented a real problem for them.  Their typical scenario involved a sales representative who would meet with a customer in-person.  Because they wanted to offer insurance quotes or initiate insurance applications on multiple products, the sales representative would open up multiple tabs of their APEX application.  Of course, the session state across all of these tabs would collide and effectively corrupt the quoting process.  As Goran stated at the time, it became more and more difficult to justify the use of APEX because of this troublesome behavior.  I had no immediate answer, but I told him we would redouble our efforts and look at this problem again.

In February of this year, I had one of those lightbulb moments, and realized that we had been thinking about this problem the wrong way, and we needed to turn it inside out.  In APEX, there is always a single browser session cookie associated with an APEX session.  We were always trying to come up with a way to generate a new and differentiated browser session cookie every time a new tab was opened, and then associate this new browser session cookie with a new APEX session.  But the new approach was to simply keep the one and only one browser session cookie, and have this associated with multiple APEX sessions on the server.  I expressed my idea to the supremely intelligent Christian Neumueller of the APEX development team, and he went about with a masterful design and implementation of this feature.

In Application Express 5.1, we are introducing a new request to the APEX engine named APEX_CLONE_SESSION.  When requested from an existing APEX session, this will generate a new APEX session identifier and associate it with the existing browser session cookie.  Additionally, it will copy all of the session state values from the old session to the new session.  You, the developer, would have to provide a link for your end users to open up new browser tabs, and include APEX_CLONE_SESSION in the request of the URL.  So instead of your end users manually opening up a new tab from your APEX application, you would have to give them a prescribed way to open new tabs - could be a dynamic action or a button or a link.  The URL in the new tab should include APEX_CLONE_SESSION in the "Request" portion of the APEX URL.

An example URL would be:
f?p=&APP_ID.:&APP_PAGE_ID.:&APP_SESSION.:APEX_CLONE_SESSION

Because we were a bit paranoid about this feature until we could thoroughly vet the security of it, by default, this capability is turned off.  You can override this setting for a specific workspace by using the Administration API:

apex_instance_admin.set_workspace_parameter(
    p_workspace => 'JOELS_WORKSPACE',
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value     => 'Y');

or you can enable it for the entire instance using:
apex_instance_admin.set_parameter(
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value     => 'Y');

This feature is enabled instance-wide on the Application Express 5.1 Early Adopter site at https://apexea.oracle.com.  We would welcome your feedback about this feature.  And if you're reading this blog post after APEX 5.1 is generally available, please feel free to try it in your own APEX 5.1 (or later) instance or on https://apex.oracle.com.

13 comments:

Stewart Stevens said...

Really good news and glad to have the confirmation following the reveal at Kscope16

Byte64 said...

Hi Joel,
what happens if I open a link containing APEX_CLONE_SESSION when no other Apex session currently exists?

For instance, imagine you have two or three apex pages embedded inside a single HTML page using EMBED and each of these embedded pages contains APEX_CLONE_SESSION in the URL.

Thank you
Flavio

Joel R. Kallman said...

Hi Flavio,

This scenario will be no different than the "session doesn't exist" flow.

However, given the scenario you describe, it doesn't sound like "clone session" is desirable. I think it would be preferable to have "session joining" established for the application. This way, it doesn't matter which link you use into the application, once a session is established, the other links will be able to "attach" to that existing session.

Joel

Mark Lancaster said...

Hi Joel

Can you tell us how sesson timeout and session expiry work for multiple clone sessions.

Is session timeout per clone session, or for the cookie session?
Session expiry would logically (to me) apply to the cookie session.

Mark

Jason Daniel Aughenbaugh said...

Hi Joel,
Will this work when using the builder such that I could have the app builder open and the sql workshop open and using both?

regards,
Jason

Joel R. Kallman said...

Hi Mark - I believe when one session times out, then all sessions will be extinguished. They won't extend into perpetuity. But the idle time will be a function of the activity of sessions correlated to the one browser session cookie. If one logs out, then all are effectively logged out.

Hi Jason - good question. I haven't tried it. But using your example, you can use the App Builder and SQL Workshop *today* without worrying about any collision of separate state. App Builder and SQL Workshop are distinct applications, under the hood.

Joel

Jason D. Aughenbaugh said...

Good point so i'd revise it to be could we potentially develop 2 pages at once in the builder.

Jason D. Aughenbaugh said...

Good point so i'd revise it to be could we potentially develop 2 pages at once in the builder.

Joel R. Kallman said...

Jason - I confirmed with Dr. Neumueller. For now, you won't be able to clone session with the Application Builder (or any "internal" applications).

Кузьминов Андрей said...

We have lots of master-detail forms, connected with anchor e.g. in reports. In request-way we have to add request in each anchor and every single page-opening will copy session. User opens product list and open / compare / process multiple products with middle-click on anchors - it is common way in web-applications. But if the user open only one product, why we should clone session? Two different links is not an option. We can't prohibit user's opportunity to open Anchor in new tab using common browser feature.

Moreover, what about collections? If you copy all stuff with the session, consistency of the collection will be broken. Collection sometimes is used as a Session-alive array, that catches some changes in application. If such a collection is copied, it misses changes from "different tab".

Multiple page launch in our application is handled with special "instance"-item, that will be passed with each submit or get request. Special process restores separately stored item values via special process. But such way is a pain and unexpected behavior of items handling.

Andrzej Nowakowski (DBE) said...

Hi Joel

Can you commit or reject is this function exist in final vesrion ?

Joel R. Kallman said...

Hi Andrzej,

This functionality is in production APEX 5.1.

Joel

svenweller said...

Hi Joel,

I just tested this and was not able to allow session cloning for a single workspace.

The workspace was recently upgraded from Apex 5.0 to Apex 5.1.

begin
apex_instance_admin.set_workspace_parameter(
p_workspace => 'MYWORKSPACENAME',
p_parameter => 'CLONE_SESSION_ENABLED',
p_value => 'Y');
end;
/

ORA-20987: APEX - Instance parameter not found - Contact your application administrator.
ORA-06512: at "APEX_050100.WWV_FLOW_ERROR", line 1028
ORA-06512: at "APEX_050100.WWV_FLOW_ERROR", line 1395
ORA-06512: at "APEX_050100.WWV_FLOW_INSTANCE_ADMIN", line 678
ORA-06512: at line 2

This is somewhat consitent with the documentation for the set_workspace_parameter procedure. The CLONE_SESSION_ENABLED is not mentioned there in the available parameter list.

However enabling it at instance level seemed to work.

begin
apex_instance_admin.set_parameter(
p_parameter => 'CLONE_SESSION_ENABLED',
p_value => 'Y');
end;
/

PL/SQL procedure successfully completed.

Although for set_parameter there the doc also misses this CLONE_SESSION_ENABLED parameter.

But first tests showed that the session cloning works very well now.

Regards and keep up the good work
Sven