Tuesday, October 19, 2010

Custom Authentication Scheme for Oracle Application Express and Oracle Access Manager

Our customers frequently ask about how to integrate Oracle Access Manager authentication with Oracle Application Express. There is currently a thread on the Oracle Technology Network discussion forum, asking for this type of solution. It has always been my intention to present this as an official whitepaper and recommended solution from Oracle. However, I have been struggling with some Oracle Access Manager configuration issues and I simply did not want to delay any further. The "official" whitepaper and detailed instructions will have to come later.

Back in March, 2010, I took careful note of a message that Scott Spadafore on our team had sent to someone in Oracle Support. It was a generic solution for authentication via an HTTP header variable. A couple months ago, this question came up again and Tyler Muth provided me a slightly modified version of what Scott had originally authored. With some more minor modifications on my part, I can share this custom authentication scheme, which can be used with Oracle Access Manager and really any environment which will securely set a header variable to an authenticated username.

The page sentry function is:


create or replace function header_variable_page_sentry ( p_apex_user in varchar2 default 'APEX_PUBLIC_USER' )
return boolean
as
l_cgi_var_name varchar2(100) := 'REMOTE_USER';
l_authenticated_username varchar2(256) := upper(owa_util.get_cgi_env(l_cgi_var_name));
--
l_current_sid number;
begin
-- check to ensure that we are running as the correct database user
if user != upper(p_apex_user) then
return false;
end if;

if l_authenticated_username is null then
return false;
end if;


l_current_sid := apex_custom_auth.get_session_id_from_cookie;
if apex_custom_auth.is_session_valid then
apex_application.g_instance := l_current_sid;
if l_authenticated_username = apex_custom_auth.get_username then
apex_custom_auth.define_user_session(
p_user=>l_authenticated_username,
p_session_id=>l_current_sid);
return true;
else -- username mismatch. unset the session cookie and redirect back here to take other branch
apex_custom_auth.logout(
p_this_app=>v('APP_ID'),
p_next_app_page_sess=>v('APP_ID')||':'||nvl(v('APP_PAGE_ID'),0)||':'||l_current_sid);
apex_application.g_unrecoverable_error := true; -- tell apex engine to quit
return false;
end if;

else -- application session cookie not valid; we need a new apex session
apex_custom_auth.define_user_session(
p_user=>l_authenticated_username,
p_session_id=>apex_custom_auth.get_next_session_id);
apex_application.g_unrecoverable_error := true; -- tell apex engine to quit
--
if owa_util.get_cgi_env('REQUEST_METHOD') = 'GET' then
wwv_flow_custom_auth.remember_deep_link(p_url => 'f?'|| wwv_flow_utilities.url_decode2(owa_util.get_cgi_env('QUERY_STRING')));
else
wwv_flow_custom_auth.remember_deep_link(p_url=>'f?p='||
to_char(apex_application.g_flow_id)||':'||
to_char(nvl(apex_application.g_flow_step_id,0))||':'||
to_char(apex_application.g_instance));
end if;
-- -- register session in APEX sessions table,set cookie,redirect back
apex_custom_auth.post_login(
p_uname => l_authenticated_username,
p_session_id => nv('APP_SESSION'),
p_app_page => apex_application.g_flow_id||':'||nvl(apex_application.g_flow_step_id,0));
return false;
end if;
end header_variable_page_sentry;

The high-level steps to be performed are:
  1. Compile this function header_variable_page_sentry in the parsing schema of your application
  2. Create a new custom authentication scheme. In the Page Sentry Function attribute of the custom authentication scheme, enter: return header_variable_page_sentry;
  3. Add directive PlsqlCGIEnvironmentList inside the corresponding APEX Database Access Descriptor. By default, OAM Webgate uses the header variable REMOTE_USER.
  4. Secure the APEX application in Oracle Access Policy Manager by defining its corresponding Policy Domain.
  5. Back in your APEX application, make this new authentication scheme "current" for your application.

The custom authentication scheme should work in any version of Application Express. A gentleman from Oracle Consulting got this to work at a customer site using APEX 3.2 and OAM 10g. He very graciously put together a document detailing all of the steps he performed in Application Express and Oracle Access Manager to get this to work, which is invaluable to someone like me who is essentially OAM-ignorant. I've asked for his permission to share this document, and when/if I get his okay, I'll make it available from this blog.

7 comments:

Ирина said...

Hello Joel,
Thank you for your custom authentication scheme for integration OAM with APEX for SSO.

We have 2 application servers configured for one instance of APEX: WebLogic with listener and Oracle Application Server.
Could you tell me is there any way to use OAM custom scheme (Weblogic) and scheme for Application Server for SSO simultaneously?

Joel R. Kallman said...

Hi Ирина,

Are you saying that you wish to use the "old" SSO SDK with Application Server? I know that internally at Oracle they setup OAM to work with old SSO SDK applications - how they did this, though, I don't know.

Joel

runcsmeduncs said...

Joel

Thanks for posting this. We are in the process of proving our new tech stack using OAM, Webgate, APEX and native authentication using domain credentials.

Moving our current APEX Authentication scheme from Oracle SSO to OAM (via native authentication) is the last link in the chain. I will give this a go when I am back in the office on Monday.

Any update of the official white paper yet?

Duncs

Joel R. Kallman said...

Duncs,

I'll be honest with you - there has been no movement on any "official" white paper. But I can tell you that in Application Express 4.1, we will natively support header variable authentication - so this custom code in a custom authentication scheme in APEX goes away. And all that remains is configuration via Oracle Access Manager, which is really outside of our domain of expertise.

However - you're not alone in your requirement. Oracle Support is getting more and more requests for configuration with OAM 11g (and not OAM 10g, as is in this Word document). If a configuration document is produced there (and it may be), I will certainly publicize it.

Joel

Joel R. Kallman said...

Just wanted to let you know that this "official" whitepaper is now available on OTN at http://www.oracle.com/technetwork/developer-tools/apex/learnmore/index.html, in the "Technical Information and White Papers" section at the bottom.

Joel

Gayle R said...

We are trying to use HTTP header variables to authenticate an APEX user. Can anyone supply a link to some examples of how you would set this up? What types of functions must you create?

Thanks.

Joel R. Kallman said...

Gayle R,

I'm not sure what type of setup you're looking for. To be able to exploit this in APEX, it's as simple as choosing the authentication scheme of HTTP Header Variable and specifying the name of the header variable.

Many identity management solutions, like Oracle's Access Manager or even SiteMinder all will protect a set of URLs and then transmit the authenticated username in an HTTP header variable.

Joel