Wednesday, 28 June 2017

A few weeks ago I wrote a post how to avoid multiple logins when using a link in an email. This solution however does not work in a batch process for two reasons:

the URL needs to be fully specified, so protocol, server, port and directory are also needed. These data are not available outside the Apex context

the function apex_util.prepare_url can only be called from within an Apex session

My first idea was to prepare the URL for every possible mail while being in an Apex session and store it in the database. The stored URL can be used when generating the email.
This would be technically complex, because a new column would have to be created and the content of this column would have to be kept up to date all the time.

Another possibility would be to create a fake Apex session within the batch process. Then the rest of the code need not be changed. Martin Giffy d'Souza provides a way to create an Apex session in this blogpost. Although this is an 5 year old post I was able to create an Apex session and generate a valid link.

The last solution was chosen because of the simplicity and the absence of need for code change.

ORA-06512: at "APEX_050100.WWV_FLOW_DEBUG", line 561ORA-06512: at "APEX_050100.WWV_FLOW_DEBUG", line 985ORA-06512: at "APEX_050100.WWV_FLOW_DEBUG", line 355ORA-06512: at "APEX_050100.WWV_FLOW_DYNAMIC_EXEC", line 165ORA-06512: at "APEX_050100.WWV_FLOW_DYNAMIC_EXEC", line 1855ORA-06512: at "APEX_050100.WWV_FLOW_DYNAMIC_EXEC", line 1894ORA-06512: at "APEX_050100.WWV_FLOW_DYNAMIC_EXEC", line 935ORA-06512: at "APEX_050100.WWV_FLOW_PLUGIN", line 1296

What was the matter?

I added an exception handler to the render function of the plugin, but no errors were reported from there.

I added a debug statement at the beginning of the render function and there was no output from it in the debug log.

I studied the case with my colleague Alex Nuijten and we could not find a solution. Until he had the bright idea to run the page not in debug mode. And the plugin rendered without errors! Thanks, Alex.

Now everything fell into place. The debugging outputs the PL/SQL Code section of the plugin.

And this code was not fully shown until the last end statement. So the error was generated because the amount of PL/SQL code was too much to output when debugging :-( . The code was 21K long in total and up to about 16K was shown in the output.

This provides yet another reason to move the PL/SQL code of a plugin to a database package.

Monday, 12 June 2017

Some Apex applications sends notifications emails to users when tasks are due. These emails contain a link to an Apex page. When the user clicks on the link he is taken to the page. When this page is not public - which usually is the case - he is directed to the login page of the application. Even when he is logged in for the same browser on another tab.
When users get a lot of these emails it is annoying they have to log in each time. Apex provides a way to avoid the login when a session exists in the same browser. This post describes how you can set it up using the Rejoin Sessions functionality.

In order to be able to rejoin an existing session a few settings have to be made.

The instance setting Rejoin sessions needs to be set to Enabled for All sessions. Log in as Instance Administrator and navigate to Manage Instance > Security :

The application setting Rejoin sessions needs to be set to Enabled for All sessions. As a developer go to Shared Components > Security Attributes > Session Management :

After setting this parameter you may be prompted to set the parameter Embed in frames to Deny or Allow from same Origin.

The link in the email usually contains parameters. Links with parameters should contain a checksum for session rejoining. So on the target page set Page Access Protection to Arguments must have checksum. Then provide the link URL with a checksum:

l_url := apex_util.prepare_url(l_url);

Use this URL in the notification email to your users.

When the user clicks on the link and there is no session in the browser he is prompted to login.

When the user clicks on the link and there is a session in the browser the target page is shown with the parameters from the URL. The user does not need to login a second time.

This method does not imply a security risk because an existing session is reused. When the user is not logged in the login page will be presented.

In this example the parameter names and values are exposed in the URL. To maximize the security these might be hidden by storing the actual URL in a table indexed with a hash value. The link in the email points to an intermediate page that uses the hash value to retrieve the actual URL and redirect to it.