Introduction to ADF Security in JDeveloper 10.1.3.2
An Oracle JDeveloper Article
Written by
Frank Nimphius, Oracle Corporation
February, 2007
Introduction
Oracle Application Development Framework (ADF) is Oracle's JSR-227 compliant implementation of a generic binding layer for applications that follow the J2EE Model-View-Controller architecture. ADF Security is a key feature of the Oracle ADF binding layer. ADF Security allows developers to declaratively define fine-grained access control to iterators, attributes, and methods exposed by a business services. The goal of ADF Security is to ease and promote secure application development based on standard J2EE security features and the Java Authentication and Authorization Service (JAAS).
Don't put all your eggs into one basket
The defense-in-depth security design pattern demands that application developers implement application security with multiple lines of defense. A typical J2EE application has a minimum of four application layers that can be used to implement security in depth. The layers in the security-in-depth approach behave as follows:
- The View layer - enforces web authentication and provides field authorization and validation. An authorization strategy performed on the view layer might hide input fields or command components that a user is not allowed to use or it might render components as read only if the authenticated user does not have sufficient update privileges.
- The Controller - authorizes page to page navigation. Navigation in JavaServer Faces is handled by the NavigationHandler, which in the reference implementation (RI) cannot be extended and modified. To implement authorized page navigation, developers must create their own secure NavigationHandler, use a PhaseListener that checks page access privileges within the request lifecycle, or rely on an underlying application layer to enforce authorization.
- The Business Service - ensures that business logic is executed in the context of the authenticated user. The security implementation details of the business service varies with the technology (for example, EJB, POJO, ADF Business Components, web services, etc).
- The Persistence layer - usually the relational database. Database security features can be leveraged with J2EE applications if the authenticated user identity is propagated from the client to the server. A few Oracle database features commonly used in J2EE applications include Virtual Private Database (VPD), Database proxy users, and Enterprise User Security (EUS).
With the Oracle Application Development Framework (ADF), an additional layer, the binding layer, is added to the J2EE application architecture. The ADF binding layer is located between the view/controller layers and the business service.
|
| Figure 1: ADF web application security architecture
|
This article outlines how application developers define security on the ADF binding layer using the ADF Security framework. More in-depth technical information about ADF Security is available in the
Oracle WebCenter Framework Developer's Guide.
Container-Managed Security in OC4J (Oracle Containers for J2EE)
ADF Security leverages the JAAS security provider (JAZN) in Oracle OC4J for authentication and authorization. JAZN implements container-managed J2EE security in OC4J and is the default policy provider for JAAS (Java Authentication and Authorization Service).
|
| Figure 2: ADF Security authentication and authorization architecture in OC4J
|
One of the advanced features in OC4J security is the ability to use JAAS authorization with J2EE container-managed authentication. Using this option, applications can authorize user interaction based on URL patterns and Java Permissions. ADF Security runs within OC4J as part of the Oracle ADF runtime libraries and leverages JAAS for authorization to implement fine-grained access control.
ADF Security
ADF Security is a JAAS-based security framework in Oracle ADF that works with all business services. ADF Security requires the Oracle JAAS (JAZN) security provider in Oracle Application Server and OC4J and integrates with Oracle Single Sign-On and Identity Management. User authentication is performed with J2EE container-managed security while access control is through JAAS. During development and testing, ADF Security is configured in
system-jazn-data.xml file of the embedded OC4J server in Oracle JDeveloper. The
system-jazn-data.xml file is the configuration repository of the JAAS XML provider in OC4J and contains user accounts, user groups, and the ADF Security-generated JAAS permissions. After deployment to OC4J or Oracle Application Server, the security provider can be changed to Oracle Internet Directory (OID), an LDAP v3 compliant directory server.
ADF Security by Example
How ADF Security works at design time and runtime is best explained by a simple example. In this example, the following security policies will be applied to an ADF Faces web application:
- All users must be authenticated to work with the example application.
- Only the CEO is allowed to create new Departments.
- Managers and CEOs can update Departments.
- Managers are not allowed to update the Department ID.
- All navigation controls are hidden from the user if the user is not authorized to perform the action.
|
| Figure 3: Example application navigation flow
|
Note that a security best practice is to apply protection to an application during development and not after the fact.
Enabling ADF Security for a Web application
The ADF Security framework is a feature of Oracle ADF since JDeveloper 10.1.3.0. New functionality added in JDeveloper 10.1.3.2 includes the ADF Security wizard that guides developers through the configuration of ADF Security for web applications based on ADF Faces and the ADF binding layer.
|
| Figure 3: Authentication configuration
|
The first step in the ADF Security wizard defines authentication and authorization for the web application. Authorization is enforced with JAAS, which is enabled by selecting the
Enforce Authorization checkbox. Not selecting this option only sets up authentication.
The
Redirect Upon Successful Authentication option specifies a page that the authenticated user is redirected to after login. Using this feature, developers enforce a defined entry to an application, independent of the page requested by the user. The
Browse button allows the developer to browse the current web project to select a source file that represents the start of the application.
Note: ADF Security may also be configured for web applications built with JSP and Struts. In contrast to JSP applications, that are accessed relative from the J2EE context, JavaServer Faces applications require the Faces Servlet mapping to be part of the requesting URL to ensure a JavaServer Faces context exists. The
Faces Servlet mapping "faces/" is not added by the ADF Security wizard and must be added manually in front of the selected page as shown in the image above.
Authentication in ADF Security is enforced through a Servlet that is configured as
adfAuthentication in the
web.xml deployment descriptor. The servlet is protected by a J2EE security role in which all authorized application users are a member. Using the OC4J role
"
anyone
" ADF Security allows developers to grant access to unauthenticated users, which is useful to maintain public pages and to enforcing lazy authentication.
|
| Figure 5: JAAS provider selection
|
ADF Security supports both JAZN file-based security and the LDAP security provider for authentication and authorization. For application development the
Lightweight XML Provider is the default. Note that selecting the
LDAP Provider option in the wizard does not connect to the Oracle Internet Directory instance but configures the JAZN application deployment descriptor (
orion-application.xml) with the realm name and host location of the LDAP instance. The default lightweight XML provider reads its security definitions from
system-jazn-data.xml, which at design time is located in
JDeveloper_Home\jdev\system\oracle.j2ee.10.1.3.40.66\embedded-oc4j for development and testing.
|
| Figure 6: Configuring the XML based Provider
|
If authorization is enforced for web applications, the repository location must be chosen as
OC4J Default Repository, which points to the
system-jazn-data.xml file in the OC4J configuration. The default realm in OC4J is
jazn.com. A realm is comparable to a namespace that associates users and groups to a specific security policy. Setting the
JAAS Mode to
doAsPrivileged enforces permission checks to be performed against the Java permissions generated by the ADF Security design time for ADF iterator, attribute and control bindings. JAAS allows finer-grained authorization than standard J2EE container-managed security constraints defined on URL patterns.
|
| Figure 7: J2EE authentication dialog |
ADF Security uses J2EE container-managed authentication with one of the following authentication types: Basic Authentication, Digest Authentication, Forms-Based, Client Certificate.
If selecting
Form-Based Authentication, an HTML file or a JSP file is required to define the login page and the error page. The login page contains an HTML form with the
action attribute set to
j_security_check and two input text fields:
j_username and
j_password. J2EE containers understand that the
j_security_check
action is used to perform J2EE authentication.
The
Generate Default option generates two HTML files:
login.html and
error.html in the web application
public_html directory. The
login.html contains a HTML form element with the required
j_security_check
action and the
j_username and
j_password fields. To create files with a file name other than
login.html, deselect the
Generate Default option and click
Browse to locate the desired file name. The files are created when finishing the ADF Security wizard.
If an ADF Faces application is configured to use the JAZN XML provider, then authentication is performed against user accounts defined in the
system-jazn-data.xml file. If the LDAP provider is configured, then the authentication realm and user accounts are looked up in OID.
|
| Figure 8: Creating and managing J2EE security roles in web.xml
|
J2EE security roles are defined in the
web.xml deployment descriptor and mapped to users and groups in the
system-jazn-data.xml file. If the role name in
web.xml matches a group name in
system-jazn-data.xml, no further mapping is required. If the names do not match, then the
web.xml role name needs to be mapped to the name in the
system-jazn-data.xml using the
orion-application.xml file. The orion application file is automatically created and deployed with the J2EE application. Though it is possible to edit the
web.xml deployment descriptor outside of the ADF Security wizard, it is recommended to use the wizard to configure user access to the ADF Security authentication servlet.
Finishing the ADF Security wizard writes the configuration information to the
web.xml deployment descriptor and the
orion-application.xml file.
|
| Figure 9: ADF Security configuration in web.xml and orion-application.xml
|
Within the
web.xml deployment descriptor, the ADF authentication servlet is created with a
success_url initial parameter. The
success_url contains the name of the application start page defined by setting the
Redirect Upon Successful Authentication option as shown in Figure 3.
Configuring the embedded OC4J
The embedded OC4J J2EE container has its bootstrapping configuration files located in the
JDeveloper_Home\jdev\system\oracle.j2ee.10.1.3.<version>\embedded-oc4j\config directory. The configuration file used for ADF Security development and testing in Oracle JDeveloper is
system-jazn-data.xml. The
system-jazn-data.xml is an XML-based security repository for Oracle JAAS and contains user accounts and passwords, user groups, and ADF Security JAAS permissions.
To configure the
system-jazn-data.xml file for ADF Security from the Oracle JDeveloper IDE, choose the
Tools | Embedded OC4J Server Preferences menu option.
|
| Figure 10: Embedded OC4J configuration dialog
|
To configure ADF Security, the user and group accounts need to be created under the
Global node. The
jazn.com default realm also contains the OC4J administration accounts and for this reason is pre-defined in the
system-jazn-data.xml file. For this how to example, three users
sking
,
ahunold and
dfaviet are created and assigned to the application roles
users
,
managers and
ceo.
The authentication servlet is protected using the same role names in the
web.xml file, granting access to all user roles. If the role names configured in
jazn-data.xml differ from the names used in
web.xml, then the
orion-application.xml file needs to be edited to map
web.xml role names to
system-jazn-data.xml roles as documented in the OC4J security guide. In this example, the names are the same and thus no extra configuration is needed.
Defining Authorization
Authorization in ADF Security is defined through Java Permissions. The application developer defines authorization declaratively for iterator bindings, action bindings, and method bindings defined in the ADF page definition (
pageDef.xml) file and, alternatively, for the entire page definition itself.
|
| Figure 11: Authorization dialog for iterator bindings
|
A context menu option
Edit Authorization on all bindings that can have authorization defined. The Authorization editor dialog shows all possible actions for the developer to identify which user roles are allowed to perform which actions. In JDeveloper 10.1.3.2 an application either has security configured or it doesn't. This means that if ADF Security is enabled for a web application, all ADF bindings must have grants configured. All security grants are written as permissions to the
system-jazn-data.xml file. With ADF Security, the application developer doesn't need to understand how to implement JAAS to develop secure web applications. For deployment, the application specific permissions are defined in the
app-jazn-data.xml file that is deployed with the EAR file. The deployment of web applications protected by ADF Security is explained later in this document.
<grant>
<grantee>
<principals>
<principal>
<realm-name>jazn.com</realm-name>
<type>role</type>
<class>oracle.security.jazn.spi.xml.XMLRealmRole</class>
<name>managers</name>
</principal>
</principals>
</grantee>
<permissions>
<permission>
<class>oracle.adf.share.security.authorization.RowSetPermission</class>
<name>AppModuleDataControl.DepartmentsView1</name>
<actions>read,update</actions>
</permission>
</permissions>
</grant>
|
| Example 1: Permissions defined in system-jazn-data.xml
|
Note: It is important to define authorization for the
PageDef.xml files in the web application. Users need to have view privileges to access a JavaServer Faces page. Defining grants on the
PageDef.xml file permits developers to set up page-level authorization, a security feature otherwise not available in JavaServer Faces.
Programmatic access control with ADF Security
Developers may need to access user permissions programmatically in their applications for example to hide or to show UI components that execute protected actions or perform navigation. Programmatic access control can be used to implement the 5th security policy in the sample application mentioned above:
"All navigation controls are hidden from the user if the user is not authorized to perform the action".
Access through ADF Bindings
ADF Security sets the
updateable flag on ADF attribute bindings and action bindings. If, for example, a user is not authorized to update the data displayed in a table, then the table binding's
updateable property is automatically set to
false. This information can be used with Expression Language to set the
disabled property on a command button, as shown in the image below.
|
| Figure 12: Disabling a command button through the updateable flag on the attribute binding |
Access through Expression Language using the PermissionInfo object
The
PermissionInfo object on the ADF Security Context allows access to ADF Security through Expression Language and Java. The
PermissionInfo object is not shown in the Oracle JDeveloper Expression Language editor even though it exists on all binding types. The example of the disabled command button above can also be implemented with the
PermissionInfo object as shown below:
#{!bindings.DepartmentsView1.permissionInfo.update}
The general use of
PermissionInfo in Expression Language is
#{bindings.<iterator_binding>.permissionInfo.<read|create|delete|update>}
#{bindings.<method_binding>.permissionInfo.invoke}
#{bindings.<attribute_binding>.permissionInfo.<update|view>}
In addition, the
PermissionInfo object allows developers to access information from a binding container other than the current one. This is useful to handle page authorization. In the sample application, the create button should only be enabled for managers and CEOs. In the policies defined for the sample application, a rule states that if the authenticated user is not allowed to view the
EditCreateDepartmentsPageDef the
Create button should be disabled. The Expression Language string that needs to be added to the command button
Disabled property is:
#{!bindings.permissionInfo['EditCreateDepartmentsPageDef'].view}
|
| Figure 13: Disabling command buttons based on different user privileges
|
Access control through calls to hasPermission()
It is also possible to directly check a specific permission grant using the
hasPermission() method on the ADF Security Context. In this case the developer is aware of the permission names and actions defined in the
system-jazn-data.xml. The example below executes a create operation only if the authenticated user is granted
create on the
RowSetPermission for the
AppModuleDataControl.DepartmentsView1 iterator.
public String createDepartmentsAction() {
final FacesContext fc = FacesContext.getCurrentInstance();
final Application fapp = fc.getApplication();
//get binding
OperationBinding obind = (OperationBinding) fapp.createValueBinding("#{bindings.CreateDepartment}").getValue(fc);
if (
ADFContext.getCurrent().getSecurityContext().hasPermission(new RowSetPermission("AppModuleDataControl.DepartmentsView1","create"))){
obind.execute();
if (obind.getErrors() == null || obind.getErrors().size()==0){
return "editDepartments";
}
}
return null;
}
Note that using the
hasPermission() method for access authorization bears the risk that later changes in the ADF Security permission classes will require modification of the application code. To avoid this dependency on physical implementation classes, the
PermissionInfo object exists and should be used. The
hasPermission() method makes sense to be used with custom permission classes.
ADF Faces security aware components
ADF Faces components, like
af:inputText, are security-aware in that they render read-only if a user is not authorized to update the underlying ADF attribute binding. In the sample policy, rule 4 states that
"Managers are not allowed to update the Department ID". The attribute authorization for the DeptId is set on the ADF binding layer through the
pagedef.xml file so that managers have no update privilege. The image below shows the form rendering of the
EditCreateDepartments.jspx page when i) connecting as a manager and ii) when connecting as the CEO.
|
| Figure 14: Security aware ADF Faces components shows i) read-only text field for unauthorized user and ii) editable text field for authorized user
|
ADF Security Deployment
ADF Security is deployed by configuring the JAZN security provider of the target system with the Java security permissions created during web application development. In a deployment to the file-based provider, the Java Permissions need to be added manually to the
system-jazn-data.xml file of the target OC4J instance. In a deployment that uses the Oracle Internet Directory (OID) as the security provider, the security permissions need to be uploaded to OID. The upload is handled through
ldiff files, which is a specific file format for updating LDA entries using the
ldapadd or
ldapmodify command. A utility that migrates
jazn-data.xml file entries to
ldiff is provided with OC4J and documented in
Chapter 7: File-Based Security Provider of the Oracle Containers for J2EE Security Guide.
|
| Figure 15: ADF Security entry in OID
|
app-jazn-data.xml
The
app-jazn-data.xml file is located in the
.adf\META-INF folder under the Oracle JDeveloper workspace root folder and is deployed with the application. The
JDeveloper_Home\jdev\system\ oracle.j2ee.10.1.3.<version>\embedded-oc4j\config\system-jazn-data.xml file that is used to store the Java Permissions during development is not empty but contains permissions and user accounts needed to run OC4J.
To make ADF Security deployment easier, the
app-jazn-data.xml file contains only those Java Permissions of the
system-jazn-data.xml file in Oracle JDeveloper that are added by ADF Security. Deploying the
app-jazn-data.xml file with the application makes the security definitions available to the system administrator who sets up ADF Security for the production runtime.
To set up ADF Security for the file-based provider, the system administrator copies the user group and permission entries to the
system-jazn-data.xml file of the target OC4J instance.
To set up the LDAP provider with ADF Security, the administrator uses the JAZN migration utility to create an
ldiff file out of the
app-jazn-data.xml file. The
ldiff file then is used to configure OID through the
ldappadd or
ldapmodify command as documented in the
OC4J Security Guide.
Summary
ADF Security is a protection framework in Oracle ADF to authorize user access to iterator bindings, action bindings, and attribute bindings. ADF Security implements application security independent of the business service layer and works with EJB, POJO, ADF Business Components, and web services alike.
For further documentation see
Chapter 8: WebCenter Framework Tutorial
Chapter 7: File-Based Security Provider
Chapter 8: Oracle WebCenter Framework Developer's Guide
|