Database Authentication and Authorization in J2EE Container Managed Security

An Oracle JDeveloper Article
Written by Frank Nimphius, Oracle Corporation
April, 2007

  1. Introduction
  2. Container-managed security in OC4J
  3. Configuring the database LoginModule with Oracle JDeveloper embedded OC4J
  4. Configuring the database LoginModule with Oracle OC4J stand alone
  5. Troubleshooting

Introduction

This article explains how to leverage database tables for storing account information for user authentication and authorization of Java EE applications in JDeveloper 10.1.3.2 and OC4J 10.1.3.2.

Container-managed security allows web applications to delegate authentication and authorization decisions to the executing web container. In Oracle Containers for J2EE (OC4J) the authentication and authorization decision is handled by the OracleAS JAAS Provider (referred to in previous releases as the Oracle JAZN framework). Web applications running in OC4J can be configured to authenticate users against Oracle Internet Directory (OID), third-party LDAP, CoreId, jazn-data.xml or a custom JAAS LoginModule. The web application code itself doesn't need to know about the configured security provider and instead uses the standard Java Servlet APIs isUserInRole(), getRemoteUser(), and getUserPrincipal() to programmatically evaluate access to application resources. In addition to programmatic security, the container enforces URL pattern based authorization and user authentication: Basic, Form, PKI or Digest. Although OracleAS JAAS Provider is a JAAS implementation, declarative security in J2EE does not require the application developer to use JAAS and instead is configured through the standard J2EE web.xml and OC4J orion-application.xml deployment descriptors. Usually the first thing developers understand when approaching security in J2EE is container-managed security. This is because container-managed security is easy to setup, easy to work with, and extremely portable across J2EE containers. A follow-up next step then usually is how to use a custom security provider like the database for user authentication and authorization.

This JDeveloper article explains how-to use the DBTableOraDataSourceLoginModule JAAS LoginModule in OC4J to implement container-managed authentication and authorization based on a database security provider. For guidance on how to create your own JAAS LoginModule that then can be configured for OC4J container managed security, see the Login Module Developer's Guide.

Container Managed Security in OC4J

In container-managed security the application delegates authentication and authorization decisions to the J2EE container. The benefit of container-managed security in contrast to a pure JAAS approach (Java Authentication and Authorization Service) approach is that the application logic is not mixed with authentication and authorization code, which ensures portability.

Figure 1: OC4J Security Architecture

Container-managed security protects web resources by their URL. If a user requests a protected web resource, the J2EE container checks whether the user is authenticated and otherwise delegates the request to the integrated authentication service. The Oracle JAAS Provider authenticates users based on a username and password pair or a client side x509 certificate. The default authentication provider is either file-based, ( jazn-data.xml) or LDAP directory-based (Oracle Internet Directory). Other authentication providers can be configured with OC4J but require a pluggable JAAS LoginModule. One of the LoginModules provided by OC4J since 10.1.3.1 is DBTableOraDataSourceLoginModule, which authenticates the user against a database user table and role table. Once the user is authenticated, OC4J checks whether the user is a member of the security role that is configured to protect the requested web resource. The authentication provider adds a user's role membership to the user subject in the form of a Java security Principal. Because authentication is performed only one time, no second opportunity exists to grant users role privileges. If the request is authenticated and authorized, the web resource is returned to the requesting client. Otherwise a HTTP error code is returned.

 

Web.xml deployment descriptor definition

J2EE authentication and authorization is configured in the web.xml deployment descriptor. If a custom JAAS LoginModule is specified, then OC4J delegates authentication and authorization to the pluggable security provider.

<security-constraint>
  <web-resource-collection>
    <web-resource-name>all_access</web-resource-name>
    <url-pattern>/</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>USER</role-name>
  </auth-constraint>
</security-constraint>
<login-config>
   <auth-method>BASIC</auth-method>
</login-config>
<security-role>
    <role-name>USER</role-name>
</security-role>

The web.xml confguration above defines basic authentication relying on the browser's native login dialog, with authentication to be enforced on the application's root URL. Access is granted to all users that are members of the USER role, a case sensitive, semantic role that doesn't have physical permissions associated. The JAAS LoginModule, if not using the default Oracle JAAS Provider, adds the USER role in form of a Java Principal to the authenticated user subject. Application developers don't necessarily need to be aware of how authentication is performed and configured. All implementation details are relevant to the administrator and JAAS LoginModule developer.

 

DBTableOraDataSourceLoginModule required database tables

The DBTableOraDataSourceLoginModule requires a USERS table and ROLES table in the database, where the username column of the USERS table is the primary key and the username column in the ROLES table is the corresponding foreign key (see note below). An example table script that creates the USERS table and ROLES table into the database authschema is:

CREATE TABLE "AUTHSCHEMA"."APPLICATION_USERS"
( "ID" NUMBER NOT NULL ENABLE,
"USERNAME" VARCHAR2(100) NOT NULL ENABLE,
"PASSWD" VARCHAR2(100) NOT NULL ENABLE
) ;
ALTER TABLE "AUTHSCHEMA"."APPLICATION_USERS" ADD CONSTRAINT "APPLICATION_USERS_PK" PRIMARY KEY ("USERNAME") ENABLE;
REM INSERTING into APPLICATION_USERS
Insert into APPLICATION_USERS ("ID","USERNAME","PASSWD") values (1,'DFAVIET','welcome');
Insert into APPLICATION_USERS ("ID","USERNAME","PASSWD") values (2,'AHUNOLD','welcome');
Insert into APPLICATION_USERS ("ID","USERNAME","PASSWD") values (3,'SKING','welcome');

/

CREATE TABLE "AUTHSCHEMA"."APPLICATION_ROLES"
( "ID" NUMBER NOT NULL ENABLE,
"ROLE_NAME" VARCHAR2(100) NOT NULL ENABLE,
"USERNAME" VARCHAR2(100)
) ;
ALTER TABLE "AUTHSCHEMA"."APPLICATION_ROLES" ADD CONSTRAINT "APPLICATION_ROLES_PK" PRIMARY KEY ("ID") ENABLE;
ALTER TABLE "AUTHSCHEMA"."APPLICATION_ROLES" ADD CONSTRAINT "APPLICATION_ROLES_APPLICA_FK1" FOREIGN KEY ("USERNAME")
REFERENCES "AUTHSCHEMA"."APPLICATION_USERS" ("USERNAME") ENABLE;
REM INSERTING into APPLICATION_ROLES
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (1,'PRESIDENT','SKING');
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (2,'MANAGER','SKING');
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (3,'MANAGER','AHUNOLD');
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (4,'USER','SKING');
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (5,'USER','AHUNOLD');
Insert into APPLICATION_ROLES ("ID","ROLE_NAME","USERNAME") values (6,'USER','DFAVIET');

/

The DBTableOraDataSourceLoginModule helps you to secure account passwords in two ways:

  • An option to configure a password encoder that encrypts the user-provided password before comparing it with the encrypted value in the database. Using this option the password is encrypted in the database, allowing you to use database encryption features when creating the user account.
  • A J2EE data source to provide the database access information for the LoginModule. In OC4J, data sources can use password indirection, in which case the password is read from a named user account in the OC4J system-jazn-data.xml. Using password indirection encrypts the password so it cannot be stolen from the configuration file.

Configuring the database LoginModule with Oracle JDeveloper embedded OC4J

Oracle JDeveloper has an embedded OC4J container for testing web applications during development. The embedded OC4J is configured differently than the standalone OC4J to support runtime testing of applications without requiring application deployment. To do this, all web applications are executed as "current-workspace-app", no matter what the assigned name for the J2EE application. This information is important because to use JAAS LoginModules with the embedded OC4J, they need to be configured under the name of the application using it: current-workspace-app.

NOTE: Failing to use the current-workspace-app name for the LoginModule will cause OC4J to use its own default Realm LoginModule and look for the username / password pair in the system-jazn-data.xml file directly. Thus, failing to find login credentials would end in an unauthenticated request.

All configuration files of the embedded OC4J are located in the JDEVELOPER_HOME\jdev\system\oracle.j2ee.10.1.3.40.66\embedded-oc4j\config directory, where JDEVELOPER_HOME is the directory in which you unzipped JDeveloper after downloading the software from OTN. The configuration files that you will edit to configure database LoginModule support are:

  • system-jazn-data.xml
  • application.xml
  • data-sources.xml

System-jazn-data.xml

The system-jazn-data.xml file contains the JAAS LoginModule definition of the DBTableOraDataSourceLoginModule or any custom JAAS LoginModule. The difference between the DBTableOraDataSourceLoginModule and a custom JAAS LoginModule is that this LoginModule already exists in the class path of OC4J and doesn't need to be added to the lib directory or configured in the application.xml file. The DBTableOraDataSourceLoginModule is configured and ready for you to use. Note however that the default LoginModule in OC4J is the JAZN Realm LoginModule, which is used for all applications that don't have a application specific login configuration. To create an application specific login configuration for the JDeveloper current-workspace-app, the LoginModule configuration in system-jazn-data.xml need to be edited as follows:

<application>
  <name>current-workspace-app</name>
  <login-modules>
    <login-module>
      <class>oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule</class>
      <control-flag>required</control-flag>
      <options>
       <option>
         <name>table</name>
         <value>application_users</value>
       </option>
       <option>
         <name>data_source_name</name>
         <value>jdbc/authschemaDS</value>
       </option>
       <option>
         <name>groupMembershipGroupFieldName</name>
         <value>role_name</value>
       </option>
       <option>
         <name>passwordField</name>
         <value>passwd</value>
       </option>
       <option>
         <name>groupMembershipTableName</name>
         <value>application_roles</value>
       </option>
       <option>
         <name>usernameField</name>
         <value>username</value>
       </option>
     </options>
   </login-module>
 </login-modules>
</application>

Note that a login configuration for a web application can have multiple JAAS LoginModules configured. In this case, they will be called in the sequence they show in the configuration file. The control-flag of the LoginModule configuration specifies whether the authentication performed by a LoginModule needs to be successful for the whole authentication to be successful, or whether the LoginModule is optional, which means it may fail. Because the DBTableOraDataSourceLoginModule is the only LoginModule configured for the default web application in the embedded OC4J, the flag needs to be set to required. All configured options are LoginModule-specific, including, for example, the name of the data source for the database table access.

While nothing prevents you from hand editing the system-jazn-data.xml file, JDeveloper provides a dialog to assist you. To launch the editor, select the menu option Tool | Embedded OC4J Server from the JDeveloper toolbar.

Figure 2: Visual editor for the system-jazn-data.xml file of the embedded OC4J

Application.xml

But how does embedded OC4J know that it should use DBTableOraDataSourceLoginModule for authentication and not the default Realm LoginModule? The application.xml file, located in the JDEVELOPER_HOME\jdev\system\oracle.j2ee.10.1.3.40.66\embedded-oc4j\config directory, can contain two properties as a switch that indicates that the JAAS LoginModule provider should be used instead of the default Realm LoginModule.

<orion-application ...>
...
 <jazn provider="XML">
  <property name="role.mapping.dynamic" value="true"/>
  <property name="custom.loginmodule.provider" value="true"/>
</jazn>
...
</orion-application ...>

The role.mapping.dynamic property defines that J2EE security roles should be read from the authenticated user subject, allowing the LoginModule to add role grants to the authenticated user. The custom.loginmodule.provider property tells OC4J to use a custom JAAS LoginModule for authentication.

The application.xml file cannot be edited from within JDeveloper and instead needs to be edited manually.

Note: Configuring the application.xml to authenticate with custom LoginModules enforces this authentication type to be used for all projects run by this JDeveloper instance. For this reason it is recommended to set up a JDeveloper installation to build and test applications that require JAAS LoginModule authentication.

Data-sources.xml

The data-sources.xml file is used to define the J2EE data-source referenced by the LoginModule to access the database tables for authentication. The LoginModule configuration shown earlier has the following LoginModule option defined

<option>
  <name>data_source_name</name>
  <value>jdbc/authschemaDS</value>
</option>

According to this configuration, the datasource name jdbc/authschemaDS is resolved by the LoginModule at runtime to connect to the database. The data-source.xml file is expected to be part of the JDeveloper view layer project an should be created manually as follows:

  1. In the Application Navigator, select the View layer project and choose New from the context menu to open the New Gallery
  2. In the Filter By select option, choose All Technologies.
  3. Expand the General node and select the Deployment Descriptors entry.
  4. Choose OC4J Deployment Descriptor Wizard from the available options.
  5. In the wizard choose data-sources.xml and continue.
  6. In the following wizard page, choose version 10.1 for a data-source.xml file that works with JDeveloper version 10.1.3 and above.

Finishing the wizard, creates a file data-sources.xml in the project's META-INF directory. To populate the data-source.xml file with the database connection expected by the LoginModule, create a named database connect in JDeveloper.

  1. Open the Connections Navigator by pressing Ctrl+Shift+O
  2. Right mouse click onto the database connection node to create a new connection.
  3. Enter the database name without the " jdbc/" and without the " DS" strings in the Connection Name field on the first wizard page. In the example used in this article, the name is " authschema".
  4. Continue and complete the wizard, providing the connect information for the database connect.

To populate the data-source.xml file with this information, choose Tools | Embedded OC4J Server Preferences from the JDeveloper menu. In the menu, expand the Current Workspace node and select the Data Sources entry. Press the Refresh Now button on the right hand side to copy all database connections that exist in JDeveloper into the data-sources.xml file. From the list of data sources created below the Data Sources entry , delete all data source definitions that are not required for this application.

Figure 3: data-sources.xml editing option

In order to protect the database password, JDeveloper uses OC4J password indirection for entries in the data-sources.xml file. Passwords in the data-sources.xml file may look similar to password="->DataBase_User_TNyMa-DJkD88CAzvVVLM8EX__YiKXy2P". The indirected password points to a user account created in the project specific jazn-data.xml file, located in the application - or workspace - root directory. The jazn-data.xml file is not shown in the JDeveloper project hierarchy.

To add the jazn-data.xml file to the JDeveloper project, so that it is visible to the application developer, do as follows:

  1. Select the ViewLayer project and choose New from the context menu to open the New Gallery.
  2. In the Filter By select option, choose All Technologies.
  3. Expand the General node and select the Deployment Descriptors entry.
  4. Choose OC4J Deployment Descriptor Wizard from the available options.
  5. In the wizard choose jazn-data.xml and continue.
  6. In the following wizard page choose version 10.1 for a jazn-data.xml file that works for JDeveloper version 10.1.3 and above.

To populate the created jazn-data.xml file with the indirected passwords from the data-sources.xml file, choose Tools | Embedded OC4J Server Preferences from the JDeveloper menu. In the menu, expand the Current Workspace node and select the Data Sources entry. Press the Refresh Now button on the right hand side to copy all database connections that exist in JDeveloper into the data-sources.xml file. At the same time, the indirected passwords are created in the jazn-data.xml file.

Note: If the password accounts aren't created, delete the data source entries shown under Data Sources node before pressing the refresh button.

Configuring the database LoginModule with Oracle OC4J standalone

Deploying an application that uses DBTableOraDataSourceLoginModule for J2EE authentication is easier to a standalone OC4J instance than to the embedded instance because JDeveloper automates many of the steps for you. The configuration files that needs to be added or edited are

  • orion-application.xml
  • data-sources.xml
  • system-jazn-data.xml

orion-application.xml

The orion-application.xml deployment descriptor is needed to define the DBTableOraDataSourceLoginModule configuration. To create an orion-application.xml file in Oracle JDeveloper:

  1. Select the View layer project and choose New from the context menu to open the New Gallery.
  2. In the Filter By select option, choose All Technologies.
  3. Expand the General node and select the Deployment Descriptors entry.
  4. Choose OC4J Deployment Descriptor Wizard from the available options.
  5. In the wizard choose orion-application.xml and continue.
  6. In the following wizard page, choose version 10.0 for a data-source.xml file that is required for JDeveloper version 10.1.3 and above.

Unlike the embedded OC4J server, in which the application name for the JAAS LoginModule is current-workspace-app, the application name for the standalone OC4J instance is the name of the deployed J2EE application. The application name can be defined when creating the deployment profile or within the View layer project's properties. To open the properties dialog, select the project node and choose Project Properties from the context menu. Select the J2EE Application entry to specify the J2EE application name and the name of the J2EE web context root.

Figure 4: J2EE Application definition in the View layer project properties

In the example shown above, the application name of the deployed application is secure-web-app. Edit the orion-application.xml file to contain the LoginModule configuration:

<?xml version = '1.0' encoding = 'windows-1252'?>
<orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd">
<jazn location="./jazn-data.xml" provider="XML"/>
<data-sources path="./data-sources.xml"/>

<jazn-loginconfig>
  <application>
    <name>secure-web-app</name>
    <login-modules>
      <login-module>
        <class>oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule</class>
        <control-flag>required</control-flag>
        <options>
          <option>
            <name>data_source_name</name>
            <value>jdbc/authschemaDS</value>
          </option>
          <option>
            <name>table</name>
            <value>application_users</value>
          </option>
          <option>
            <name>usernameField</name>
            <value>username</value>
          </option>
          <option>
            <name>passwordField</name>
            <value>passwd</value>
          </option>
          <option>
            <name>groupMembershipTableName</name>
            <value>application_roles</value>
          </option>
          <option>
            <name>groupMembershipGroupFieldName</name>
            <value>role_name</value>
          </option>
        </options>
      </login-module>
    </login-modules>
  </application>
</jazn-loginconfig>
</orion-application>


The LoginModule configuration itself hasn't changed compared to the embedded OC4J usage, except that the configuration is added to the orion-application.xml and not to the system-jazn-data.xml file. Upon deployment, OC4J performs the system-jazn-data.xml configuration and also sets the required properties:

<property name="role.mapping.dynamic" value="true"/>
<property name="custom.loginmodule.provider" value="true"/>

Note that t his configuration can be undone automatically when undeploying the J2EE web application. Furthermore standalone OC4J instances can run J2EE web application using both custom JAAS LoginModules for authentication and applications and the default Realm LoginModule authentication at the same time.

data-sources.xml

The DBTableOraDataSourceLoginModule is configured with a data source reference to connect to the database. The data-sources.xml file can be deployed with the J2EE web application or created after deployment using the Enterprise Manager web application console of OC4J, which you can access from http://server:8888/em.

Creating a data-sources.xml file in Oracle JDeveloper is explained earlier in this document.

system-jazn-data.xml

If the data-source.xml file is configured with password indirection, which is the Oracle JDeveloper default, then the user account must be added to the system-jazn-data.xml file of the OC4J instance. The system-jazn-data.xml file is located in the \j2ee\home\config directory of the OC4J instance. There are two options available to add the account in OC4J.

Manual account creation

In this scenario, you open the data-sources.xml file created in Oracle JDeveloper and locate the data-source definition of the data source used in the LoginModule configuration. In the example configuration above, this is jdbc/authschemaDS .

The content of the data-sources.xml file in this example is

<connection-pool name="jdev-connection-pool-authschema" disable-server-connection-pooling="false">
  <connection-factory factory-class="oracle.jdbc.pool.OracleDataSource" user="authschema"
  password="->DataBase_User_H3qWButn9PYa0q-iROlsk52Spi7YzAG_" url="jdbc:oracle:thin:@localhost:1621:ORCL"/>
</connection-pool>
<managed-data-source name="jdev-connection-managed-authschema" jndi-name=" jdbc/authschemaDS" connection-pool-name="jdev-
connection-pool-authschema"/>
<native-data-source name="jdev-connection-native-authschema" jndi-name="jdbc/authschemaCoreDS" url="jdbc:oracle:thin:@localhost:1621:ORCL" user="authschema" password="->DataBase_User_bsvQ9GfeZmRJ6W2XwC84fJaswBKa2prG" data-source-class="oracle.jdbc.pool.OracleDataSource"/>

Note that the jdbc/authschemaDS entry points to the jdev-connection-pool-authschema, which has its password redirected to the DataBase_User_H3qWButn9PYa0q-iROlsk52Spi7YzAG_ user account.

You can either keep this reference or change it to an existing username in the system-jazn-data.xml file of the target OC4J instance. Depending on your configuration in JDeveloper, the user account equivalent to DataBase_User_H3qWButn9PYa0q-iROlsk52Spi7YzAG_ contained in the project specific jazn-data.xml file , or the <workspace name>-jazn-data.xml in the root directory of your JDeveloper workspace in the file system.

It is also possible to change the user account name after deployment using the EnterpriseManager web console of OC4J.

Figure 5: EnterpriseManager console in OC4J to define the password indirection for a data source

Troubleshooting

This article explained how to configure the DBTableOraDataSourceLoginModule for the embedded and standalone OC4J. However, if things don't work as expected, follow these steps to help identify the source of the problem.

Logging in embedded OC4J

The DBTableOraDataSourceLoginModule is a closed system in that it is shipped without the source code. During application development it is important for the developer to understand what the LoginModule does to identify problems and their cause.

For the embedded OC4J container, edit the j2e-logging.xml file located in the JDEVELOPER_HOME\jdev\system\oracle.j2ee.10.1.3.40.66\embedded-oc4j\config directory and add

<logger name="oracle.j2ee.security" level="FINE" useParentHandlers="false">
  <handler name="oc4j-handler"/>
  <handler name="console-handler"/>
</logger>

Figure 6: Log messages printed to the JDeveloper console

Logging in standalone OC4J

Logging for the standalone instance of OC4J is configured in the j2ee-logging.xml file located in the OC4J_HOME\j2ee\home\config directory. The log entries are written in an XML format to the log.xml file located in the OC4J_HOME\j2ee\home\log\oc4j directory.

<logger name="oracle.j2ee.security.oc4j" level="FINE" useParentHandlers="false">
  <handler name="oc4j-handler"/>
  <handler name="console-handler"/>
</logger>

Please refer to the OC4J security documentation for more information about configuring logging in OC4J.

Verifying the J2EE data sources connection working

To ensure the J2EE datasource used by the DBTableOraDataSourceLoginModule to connect to the database work, open a SQL*Plus session, connect as System and type:

select username from v$session;

The resulting username list should contain an instance of the database schema the DBTableOraDataSourceLoginModule connects to.

Unlocking database accounts

Too many failed attempts to connect to the database schema will eventually lock the schema. You can verify this by opening SQL*Plus and connecting to the schema. If the account is locked, connect as System and type:

alter user authschema account unlock;

This unlocks the account for further testing.

Summary

Database authentication and authorization in container-managed J2EE security is possible through the OC4J DBTableOraDataSourceLoginModule or a custom database JAAS LoginModule. Developers that extend existing non-J2EE applications to Java usually have the requirement to leverage an existing database infrastructure for authentication and authorization. The Oracle Application Server security infrastructure in OC4J allows developers to configure standard JAAS LoginModules to be used at design time and runtime instead of the default XML file-based or LDAP directory-based provider. DBTableOraDataSourceLoginModule is a LoginModule provided by Oracle that authenticates and authorizes users against a defined database schema in a secure way by connecting to the database with J2EE data sources that protect the database password through password indirection.


[1]
[2] Declarative J2EE authentication and authorization with JAAS
[3] Free JAAS book in PDF
[4] DBTableOraDataSourceLoginModule
[5] Custom JAAS LoginModule packaging and deployment in OC4J
[6] otn.oracle.com/products/jdev
[7] OC4J logger documentation


Note: A bug in DBTableOraDataSourceLoginModule of OC4J 10.1.3.2 demands that the username column names are identical in the two tables. When this bug is fixed, the username column in the user table can be a different name than the name used for the same information in the roles table.

false ,,,,,,,,,,,,,,,