Protecting a WebCenter app with OAM 11g - the Webcenter side
- by Martin Deh
Recently, there was a customer requirment to enable a WebCenter custom portal application to have multiple login-type pages and have the authentication be handle through Oracle Access Manager (OAM) As my security colleagues would tell me, this is fully supported through OAM. Basically, all that would have to be done is to define in OAM individual resources (directories, URLS , .etc) that needed to be secured. Once that was done, OAM would handle the rest and the user would typically then be prompted by a login page, which was provided by OAM. I am not going to discuss talking about OAM security in this blog. In addition, my colleague Chris Johnson (ATEAM security) has already blogged his side of the story here: http://fusionsecurity.blogspot.com/2012/06/protecting-webcenter-app-with-oam-11g.html . What I am going to cover is what was done on the WebCenter/ADF side of things.
In the test application, basically the structure of pages defined in the pages.xml are as follows:
In this screenshot, notice that "Delegated Security" has been selected, and of the absence for the anonymous-role for the "secured" page (A - B is the same)
This essentially in the WebCenter world means that each of these pages are protected, and only accessible by those define by the applications "role". For more information on how WebCenter handles security, which by the way extends from ADF security, please refer to the documentation. The (default) navigation model was configured. You can see that with this set up, a user will be able to view the "links", where the links define navigation to the respective page:
Note from this dialog, you could also set some security on each link via the "visible" property. However, the recommended best practice is to set the permissions through the page hierarchy (pages.xml). Now based on this set up, the expected behavior is that I could only see the link for secured A page only if I was already authenticated (logged in). But, this is not the use case of the requirement, since any user (anonymous) should be able to view (and click on the link). So how is this accomplished? There is now a patch that enables this. In addition, the portal application's web.xml will need an additional context parameter:
<context-param>
<param-name>oracle.webcenter.navigationframework.SECURITY_LEVEL</param-name>
<param-value>public</param-value>
</context-param>
As Chris mentions in his part of the blog, the code that is responsible for displaying the "links" is based upon the retrieval of the navigation model "node" prettyURL. The prettyURL is a generated URL that also includes the adf.ctrl-state token, which is very important to the ADF framework runtime. URLs that are void of this token, get new tokens from the ADF runtime. This can lead to potential memory issues.
<af:forEach var="node" varStatus="vs"
items="#{navigationContext.defaultNavigationModel.listModel['startNode=/,includeStartNode=false']}">
<af:spacer width="10" height="10" id="s1"/>
<af:panelGroupLayout id="pgl2" layout="vertical"
inlineStyle="border:blue solid 1px">
<af:goLink id="pt_gl1" text="#{node.title}"
destination="#{node.goLinkPrettyUrl}"
targetFrame="#{node.attributes['Target']}"
inlineStyle="font-size:large;#{node.selected ? 'font-weight:bold;' : ''}"/>
<af:spacer width="10" height="10" id="s2"/>
<af:outputText value="#{node.goLinkPrettyUrl}" id="ot2"
inlineStyle="font-size:medium; font-weight:bold;"/>
</af:panelGroupLayout>
</af:forEach>
So now that the links are visible to all, clicking on a secure link will be intercepted by OAM. Since the OAM can also configure in the Authentication Scheme, the challenging URL (the login page(s)) can also come from anywhere. In this case the each login page have been defined in the custom portal application. This was another requirement as well, since this login page also needed to have ADF based content. This would not be possible if the login page came from OAM. The following is the example login page:
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<f:view>
<af:document title="Settings" id="d1">
<af:panelGroupLayout id="pgl1" layout="vertical"/>
<af:outputText value="LOGIN FORM FOR A" id="ot1"/>
<form id="loginform" name="loginform" method="POST"
action="XXXXXXXX:14100/oam/server/auth_cred_submit">
<table>
<tr>
<td align="right">username:</td>
<td align="left">
<input name="username" type="text"/>
</td>
</tr>
<tr>
<td align="right">password:</td>
<td align="left">
<input name="password" type="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input value=" login " type="submit"/>
</td>
</tr>
</table>
<input name="request_id" type="hidden" value="${param['request_id']}"
id="itsss"/>
</form>
</af:document>
</f:view>
</jsp:root>
As you can see the code is pretty straight forward. The most important section is in the form tag, where the submit is a POST to the OAM server. This example page is mostly HTML, however, it is valid to have adf tags mixed in as well. As a side note, this solution is really to tailored for a specific requirement. Normally, there would be only one login page (or dialog/popup), and the OAM challenge resource would be /adfAuthentication. This maps to the adfAuthentication servlet. Please see the documentation for more about ADF security here.