Declarative J2EE authentication and authorization with JAAS
An Oracle JDeveloper How To Document
Written by Frank Nimphius and
Duncan Mills, Oracle Corporation
July , 2005
Content
Introduction
J2EE Declarative
Security
JAAS Authentication
Configuring JAAS
declarative J2EE security in OC4J
Oracle Database LoginModule
examples
DBSystemLoginModule
DBTableLoginModule
DBTableOraDataSourceLoginModule
DBProcLoginModule
DBProcOraDataSourceLoginModule
Writing log information
Using the provided ANT
scripts for configuration
Working with the
LoginModuleTestCase project in Oracle JDeveloper 10.1.2
Troubleshooting
Downloads
Introduction
Container-managed security, which is also referred to as J2EE declarative security,
and the Java Authentication and Authorization Services (JAAS) are the security
technologies for authentication and authorization in the Java 2 Enterprise Edition
(J2EE) release 1.4 and above. J2EE declarative security in Oracle Containers
for J2EE (OC4J) is implemented with Oracle JAAS, Oracle's implementation of
the JAAS 1.0 standard. By default, the Oracle JAAS security provider allows
user account information and security roles to be stored in one of two locations:
a file based XML format or in an LDAP directory, leveraging the Oracle Internet
Directory (OID). The file based Oracle JAAS provider is extensible to custom
security implementations through the support of custom JAAS login modules for
authentication and authorization.
This whitepaper explains how to use Oracle JDeveloper to configure declarative
J2EE security for web applications. Further it describes using Oracle JDeveloper
to deploy secure J2EE web application to an OC4J instance that is setup for
custom JAAS LoginModule authentication.
The JAAS LoginModules provided as an example perform three different types
of database authentication and authorization: based on a physical database schema,
based on user and role tables and based on a stored database procedure that
returns a Ref Cursor. The LoginModules are tested with OC4J 10.1.2, Oracle JDeveloper
10.1.2 and the Oracle 10g database. An Apache Ant script is provided to help
you configuring the JAAS LoginModules and the related demo SQL scripts. All
LoginModules, except the two that use container specific data-sources, can also
be used with J2SE Swing applications.
The source code and the Apache Ant scripts are downloadable from the Oracle
Technology Network (OTN).
J2EE Declarative Security
Container-managed security delegates all access control decisions to the J2EE
container, thus cleanly separating application logic from security definitions.
User roles in container-managed security, defined in the web application deployment
descriptor (web.xml) are statically mapped to security roles that are
defined on the target J2EE container, for example Oracle Containers for J2EE
(OC4J). Declarative J2EE security protects web applications by their URL patterns,
which can be full absolute paths or relative paths and file extensions. For
instance, to grant access to an application only to those users that are member
of the USERS role, the following definition would be needed in the web.xml file:
<security-constraint>
<web-resource-collection>
<web-resource-name>AllPublic</web-resource-name>
<url-pattern>/</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>USERS</role-name>
</auth-constraint>
</security-constraint>
This protects a web application starting from its J2EE root directory as indicated
through the "/" pattern. To apply protection only to subdirectories,
the pattern needed to be changed to "/<subdirectory name>".
The role name USERS is a logical name that needs to be mapped to an existing
role on the target platform, OC4J, using the container specific descriptor file,
orion-web.xml.
<security-role-mapping impliesAll="false" name="USERS">
<group name="APP_USERS"/>
</security-role-mapping>
In this example the security role USERS that is used to grant access to the
J2EE web application is mapped to the user group APP_USERS on the OC4J platform.
Members of the APP_USERS groups are specified either in the jazn-data.xml
repository or in the Oracle Internet Directory (OID). In Oracle Containers for
J2EE 10.1.3, users can also be defined in 3rd party LDAP servers. If the OC4J
group name is the same as the role name used in the web.xml file, then
no role to group mapping is required. Setting the impliesAll attribute
of the <security-role-mapping> element to true will grant all defined
users and groups of the target deployment platform as members of the logical
USERS group.
Both configuration file, the web.xml deployment descriptor and the container
specific orion-web.xml file can be edited visually using the Oracle JDeveloper
IDE. The visual editing dialog is accessible from the context menu of the web.xml
file entry in the Oracle JDeveloper project. The orion-web.xml file,
because its a platform specific configuration file for OC4J, is not automatically
added by default to a web application project in Oracle JDeveloper and must
be manually added using the New option on the project's node context
menu. Note that the orion-web.xml file is not required if the role names
specified in the web.xml file have matching group names in the OC4J or
Oracle Application Server user repository.
The benefit of the J2EE declarative security is that it does require little
or no programming by the application developer because most of the security
decisions are made during deployment. This model also allows changes to be applied
to the security definition without requiring re-coding in the application.
Checking security roles in the application code
To support programmatic security, a web application developer can use the request.isUserInRole("<role
name>") method call to evaluate the access granted to the authenticated
user. Technologies like Struts and JavaServer Faces perform server side page
forward navigation using postback requests, making it difficult to use declarative
security throughout. Programmatic use of J2EE security that evaluates a security
role within application code becomes more important with these technologies.
Role mapping
For the J2EE web application code that perform programmatic authorization to
remain independent from the roles defined in the web.xml file or on the
target platform, J2EE allows application developers to define logical role names
in their application code later get mapped to role names in the web.xml
deployment descriptor file.
In the application code, which can be in a Struts action, a JavaServer Faces
(JSF) managed bean or in a JavaServer Pages (JSP) page, the application developer
would use for example request.isUserInRole("VALID_USER") to
verify that a user has been granted the access privilege for a specific resource
or information. In the given example, the VALID_USER role name used in the application
code, is mapped to the USERS role defined in the web.xml file, using the <security-role-ref>
element as a sub-element of the <servlet></servlet> element in the
web.xml deployment descriptor file.
<security-role-ref>
<role-name>VALID_USER</role-name>
<role-link>USERS</role-link>
</security-role-ref>
User authentication
Authentication in declarative security is enforced when a user requests a protected
web application area. If the user hasn't been authenticated before, a login
dialog is shown for the user to identify himself. The commonly used types of
authentication are FORM based authentication and BASIC authentication. The type
of authentication is specified in the web.xml deployment descriptor using
the <login-config> element.
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
BASIC authentication uses the browser login dialog for the user to enter his
username and password. This dialog form cannot be customized and thus varies
in its look and feel depending on the type of browser used. The user credentials
are stored in the browser session for the authenticated realm. A realm in J2EE
is a protection domain that defines a set of permissions for the authenticated
user. The default realm in Oracle JAAS is jazn.com. Using Basic authentication,
the username and password is send with each request in a base64 encoded form
in the HTTP header.
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>logonform.jsp</form-login-page>
<form-error-page>error.jsp</form-error-page>
</form-login-config>
</login-config>
FORMS based authentication allows the application developer to specifies a
custom login dialog. The username parameter must have a name of j_username,
the password field must be named j_password. The logon form action must
have a value of j_security_check for the J2EE container to authenticate
the request. The user remains authenticated throughout the server session.
Both approaches, FORM based authentication and BASIC authentication aren't
secure and vulnerable against eavesdropping attacks. Therefore it is highly recommended
to run applications that use BASIC or FORM based authentication with the HTTPS
protocol. A less often used authentication, though more reliable, is to use
mutual authentication with digital certificates, also known as public key encryption
(PKI). All J2EE compliant containers support this type of authentication.
JAAS Authentication
The Java Authentication and Authorization Service (JAAS) consist of a set APIs
and interfaces for fine grained programmatic authentication and authorization.
JAAS was designed to augment the Java 2 Security platform, enabling security
developers to perform authorization not only based on the code location, but
also on the user executing the code. Authentication in JAAS is performed through
a pluggable authentication module architecture (PAM), which uses one or more
LoginModules to authenticate a user or service. Compared to declarative J2EE
security, JAAS enables the security developer to customize the authentication
process for an individual application. No changes are required in the J2EE application
code to change the authentication source for an application.
The key to JAAS authentication are pluggable LoginModules that perform the
authentication based on information provided through callback handlers. Custom
LoginModules must implement the methods defined by the javax.security.auth.spi.LoginModule
interface.
Callback handlers are used to obtain the user credentials to pass to the LoginModule(s)
for authentication. user credentials could be provided through login dialogs,
tokens, certificates and whatever developers come up with. The login() method
of a LoginModule is called by the LoginContext to authenticate a user and returns
either true for a successful authentication, false for a failed authentication
or throws a javax.security.auth.login.LoginException in case of a failure.
Its the LoginContext's responsibility to read the LoginModule configuration
file and call each of the LoginModules configured for a particular application.

A JAAS Subject represents the authenticated user after successful authentication.
LoginModules add instances of java.security.Principal to the Subject
upon successful authentication. Principals are used in JAAS to authorize an
authenticated user to perform specific privileged actions. Later, in the context
of this paper, user Principals will be used to dynamically define J2EE security
roles for the authenticated user. Only if the overall authentication of the
LoginContext succeeded, the commit method is called on each configured LoginModule.
Otherwise the LoginModule abort() method is called to reset the LoginModule's
inner state.
J2EE and J2SE applications use an instance of LoginContext to perform the login
process. The LoginModules are configured in an external configuration file under
a named entry, which gets passed as the first argument to the LoginContext constructor.
The second argument passed to the LoginContext is the callback handler that
is used to obtain the user's authentication credentials. Note that an application
that uses declarative J2EE authentication with JAAS in Oracle Application Server
or OC4J does not need to create the LoginContext because its created by the
Oracle J2EE container implicitly.
javax.security.auth.login.LoginContext lc = new javax.security.auth.login.LoginContext
("<LoginModuleDef",<callback handler>);
The "<LoginModuleDef>" is a named reference for one or more
LoginModule specified in the JAAS configuration. The named configuration reference
in the example is "DBLoginModuleAuth" and defines one LoginModule
to perform user authentication against the database. The first argument in the
configuration is the absolute class name of the LoginModule, followed by a flag
indicating whether the LoginModule needs to succeed for the overall authentication
to succeed.
DBLoginModuleAuth{ oracle.sample.dbloginmodule.DBSystemLM.DBSystemLoginModule
required debug="true" log_level="ALL" ... };
The flag after the login module class name indicates how the authentication
process continues in case of success or failure, in the case of a multiple LoginModule
configuration. Using multiple LoginModules allows application security administrators
to perform graduated authentication for an application, which is that different
users have different sets of privileges based on the number and type of authenticated
Principles added to the Subject. The available choice of flags is as follows:
| Required |
The LoginModule must succeed. Authentication always proceeds
down the list of LoginModule but the overall authentication will fail if
one of the required LoginModules fails authenticating the user. |
| Requisite |
The LoginModule must succeed. Authentication continues down the LoginModule
list, if successful. Control immediately returns to the application, if
failed |
| Sufficient |
The LoginModule is not required to succeed. If it succeeds, control immediately
returns to the application. If it fails, authentication continues down the
list of LoginModules |
| Optional |
The LoginModule is not required to succeed |
Following the flag, LoginModule specific options are listed. These options
are defined by the LoginModule itself and control the LoginModule behavior.
For a database LoginModule this information would include the JDBC connect string
to perform user authentication against. One commonly used option is debug
to enable or disable authentication logs being written. All options that are
configured for the LoginModule are accessible to the LoginModule at runtime:
String db_schema = options.get("db_schema")!=null?(String) options.get("db_schema"):null;
The options variable is an instance of java.util.Map and is implicitly
passed from the JAAS infrastructure to the LoginModules initialize method, based
on the LoginModule configuration.
Configuring JAAS declarative
J2EE security in OC4J
By default, Oracle Containers for J2EE (OC4J) authenticates users against
the jazn-data.xml file, an XML based user provider, or Oracle Internet Directory
(OID), an LDAP v3 compliant directory server. To customize J2EE authentication,
OC4J supports custom LoginModules that are configured with the bootstrap jazn-data.xml
file, which is located in the OC4J_Home\j2ee\home\config directory.
On OC4J, it is possible to define one or more LoginModules to authenticate
a specific J2EE application. Access privileges are added to the authenticated
Subject in the form of java.security.Principal instances. In OC4J, Principals
can be configured to map to J2EE declarative security roles defined in the web.xml
file. To successful deploy J2EE applications with a custom JAAS authentication
to OC4J, the following configuration steps need to be performed
- Definition of an application name for the J2EE application in Oracle JDeveloper
- Configuration of the bootstrap jazn-data.xml file with the JAAS Login Module(s)
- Configuration of the J2EE application to obtain security role names from
the authenticated Subject
- Configuration of data-sources.xml (optional)
- Configuration of password indirection (optional)
Defining the J2EE application name in Oracle JDeveloper
The J2EE application name is configured as Enterprise Application Name
when creating the WAR deployment profile for the web application project in
JDeveloper.

The application name may be different from the selected web context root, which
after deployment is shown as part of the request URL. In the example shown above,
the Enterprise Application Name is set to DBLMTest, which will be used
when configuring the JAAS LoginModules for J2EE declarative authentication.
Setting up the bootstrap jazn-data.xml file with application
specific LoginModules
To configure custom JAAS LoginModules in OC4J or Oracle Application Server,
the bootstrap jazn-data.xml file needs to be edited. The bootstrap jazn-data.xml
file is located in the OC4J_Home\j2ee\home\config directory and is read at OC4J
instance startup time. To edit this file, e.g. to add or remove JAAS LoginModule
for J2EE authentication, it is recommended to use the jazn.jar command
line tool with the following syntax, starting in the OC4J_Home\j2ee\home\ directory.
java -jar jazn.jar -addloginmodule application_name login_module_name control_flag
[optionname=value ...]
java -jar jazn.jar -remloginmodule application_name login_module_name
To use one of the example LoginModule provided with this document for declarative
J2EE authentication of the deployed "DBLMTest" web application, the
command would be as follows:
java -jar jazn.jar -addloginmodule DBLMTest oracle.sample.dbloginmodule.DBProcLM.DBProcLoginModule
required debug="true" log_level="ALL" jdbcUrl="jdbc:oracle:thin:@localhost:1521:orcl"
jdbcDriver="oracle.jdbc.driver.OracleDriver" db_schema="scott"
db_schema_pw="tiger" plsql_procedure="DBPROCLM.GET_USER_AUTHENTICATION"
application_realm="Online Trainings"
This command adds the LoginModule DBProcLoginModule with the required flag
for the DBLMTest application. LoginModule Specific options like debug, log_level
and the jdbcURL are also provided. This configuration gets written into jazn-data.xml
as
<application>
<name>DBLMTest</name>
<login-modules>
<login-module>
<class>oracle.sample.dbloginmodule.DBProcLM.DBProcLoginModule</class>
<control-flag>required</control-flag>
<options>
<option>
<name>debug</name>
<value>true</value>
</option>
<option>
<name>jdbcDriver</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</option>
<option>
<name>application_realm</name>
<value>Online Trainings</value>
</option>
<option>
<name>plsql_procedure</name>
<value>DBPROCLM.GET_USER_AUTHENTICATION</value>
</option>
<option>
<name>db_schema</name>
<value>scott</value>
</option>
<option>
<name>jdbcUrl</name>
<value>jdbc:oracle:thin:@localhost:1521:orcl</value>
</option>
<option>
<name>db_schema_pw</name>
<value>tiger</value>
</option>
<option>
<name>log_level</name>
<value>ALL</value>
</option>
</options>
</login-module>
</login-modules>
</application>
As it becomes obvious, having the database password value written in clear
text is not the safest way of configuration. This problem, or shall we say challenge,
will be addressed in one of the following sections of this paper that explains
how modified versions of the custom database LoginModule can be used with J2EE
data sources to perform the database connect.
Before the jazn-data.xml file settings get written to the jazn-data.xml file,
the OC4J administration username and password need to be provided at the command
line. By default the administration username is admin and the password
is set to welcome. To change the administration password, start OC4J
with the -install option.
java -jar oc4j.jar -install
It is possible to repeat the -addloginmodule command for a specific
application so that multiple LoginModule authentication is performed.
Configure the LoginModule JAR file with OC4J
The Java Archive file (JAR) that contains the custom LoginModule needs to be
copied to the OC4J_Home\lib directory and configured in the OC4J_Home\j2ee\home\config\application.xml
to be available for all web applications deployed on a OC4J instance. The application.xml
file is a global configuration file and can be edited with a text editor of
choice. To configure the LoginModule JAR file as a library entry, assuming the
LoginModules are stored in a file called DBLoginModule.jar, the following
entry needs to be added to the list of existing library entries:
<library path="../../../lib/DBLoginModule.jar"/>
It is necessary to restart the OC4J instance for this change to have an impact.
Configure the J2EE application to obtain security role names
from the authenticated Subject
To use Principals added to the authenticated Subject as J2EE security roles,
the role.mapping.dynamic property needs to be set in the application
specific orion-application.xml file. A Principal name of "manager"
the will be treated as the granted J2EE role "manager" that can be
used to access control access to J2EE web applications, as explained earlier
in this document.
Oracle JDeveloper can be used to add the orion-application.xml file
to a web project, choosing orion-application.xml from the list of Deployment
Descriptors in the JDeveloper New Gallery.
The orion-application.xml file gets created in the web application project's
Application Sources > META-INF directory and can be opened for editing with
a double click. After editing the file, its content should look like
<jazn provider="XML" location="jazn-data.xml" default-realm="jazn.com">
<property name="role.mapping.dynamic" value="true"/>
<property name="jaas.username.simple" value ="true"
/>
</jazn>
Beside of the role.mapping.dynamic parameter, a second parameter, jaas.username.simple,
is added in this example. Using the jaas.username.simple parameter removes
the realm name from the username retrieved in a call to request.getUserPrincipal().getName().
The orion-application.xml file is deployed with the J2EE web application
to OC4J.
Configuring J2EE data sources in j2ee\home\data-sources.xml
Database LoginModules require database account information to connect to the
database. As mentioned earlier, providing this information in clear text in
the jazn-data.xml file is not safe. An alternative option is to leverage J2EE
data-sources that are configured on the OC4J server to hold the database connect
information. The LoginModule can be programmed to obtain the required database
connect information from a configuration in the data-sources.xml file.
New data sources are configured in the OC4J_Home\j2ee\home\data-sources.xml
file using a text editor of choice. In the example below, a datasource "jdbc/OracleDS"
is defined that connects to the"scott" database account using
the "tiger" password.
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="jdbc/OracleDS"
location="jdbc/OracleCoreDS"
xa-location="jdbc/xa/OracleXADS"
ejb-location="jdbc/OracleDS"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="scott"
password="tiger"
url="jdbc:oracle:thin:@localhost:1521:orcl"
inactivity-timeout="30"
/>
To work with this information in a LoginModule, the following code need to
be added to the Loginmodule
Context ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup(_data_source_name);
Connection conn = dataSource.getConnection();
Now that the password no longer is passed as an option to the LoginModule,
it still doesn't look safe. This however can be achieved with the password indirection
feature in OC4J that allows passwords used in the data-sources.xml to
be stored encrypted in the jazn-data.xml file, as explained in the next
section.
Password indirection in OC4J
For stronger protection, configure the J2EE data sources to use password indirection
in OC4J. An indirect password is made up of a special indirection symbol, which
is a hyphen directly followed by a greater than character (->), and a user
name. When OC4J encounters an indirect password, it uses its privileged access
to retrieve the password associated with the specified user from the OC4J jazn-data.xml
file, which is located in the <OC4J_Home>\j2ee\home\config directory.
To use password indirection, the value of the password attribute in the <data-source/>
element is replaced by the "->PwdForScott" reference
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="jdbc/OracleDS"
location="jdbc/OracleCoreDS"
xa-location="jdbc/xa/OracleXADS"
ejb-location="jdbc/OracleDS"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="scott"
password="->PwdForScott"
url="jdbc:oracle:thin:@localhost:1521:orcl"
inactivity-timeout="30"
/>
The jazn-data.xml file in the <OC4J_Home>\j2ee\home\config directory
requires the following additional entry to make the password indirection work
<user>
<name>PwdForScott</name>
<display-name>PwdForScott</display-name>
<description>Scott's password</description>
<credentials>!tiger</credentials>
</user>
The database schema password in the jazn-data.xml example provided above
is "tiger". Because the password is specified with a leading "!"
character, it gets encrypted after re-starting the OC4J instance. The encrypted
password looks similar to "{903}ZECYw/3kJmhVjzXgbZhxFg1/F8mhpsrr".
The LoginModule usage of the data source does not need to be changed for using
the password indirection feature.
Oracle Database LoginModule
Examples
The Oracle database LoginModule examples provided with this document are designed
for the Oracle platform, which is Oracle Containers for J2EE and the Oracle
database. All LoginModules, except for the two that require a J2EE data source
to be defined, can be used in a J2SE environment as well and thus can be used
to also authenticate Swing applications. This section introduces each of the
LoginModules in turn and provides all the information needed to use them in
a customer project.
Note that LoginModules perform authentication only and do not connect the application
to the database. For performance reasons J2EE web applications usually use database
connection pools when interacting with the database.
List of example LoginModules and scripts
This how-to document provides 5 custom JAAS LoginModules for database authenticating
J2EE users.
- DBSystemLoginModule
- DBTableLoginModule
- DBTableOraDatasourceLoginModule
- DBProcLoginModule
- DBProcOraDataSourceLoginModule

The DBTableOraDatasourceLoginModule and DBProcOraDataSourceLoginModule are
slightly modified versions of the DBTableLoginModule and the DBProcLoginModule
that use the data-sources.xml file to retrieve the database connect information.
The LoginModules source code is available in the provided Oracle JDeveloper
10.1.2 workspace, named "DatabaseLoginModule1012". In this
section each of the LoginModules is explained in brief.
SQL scripts are provided to populate a database schema with sample tables and
data. The LoginModules however are configurable to use custom database table
structures instead. The two SQL scripts are
- TableLMDbScriptClearPw.sql
- TableLMDbScriptEncryptedPw.sql
The scripts can be accessed and deployed to the database from the JDeveloper
DatabaseLoginModule1012 workspace, using Oracle JDeveloper 10.1.2. both
scripts create user and role tables. The TableLMDbScriptClearPw.sql creates
users with passwords written in clear that can be used with the following LoginModules:
DBTableLoginModule, DBTableOraDatasourceLoginModule, DBProcLoginModule and
DBProcOraDataSourceLoginModule.
The TableLMDbScriptEncryptedPw.sql
script creates a user table with SHA1 encrypted passwords. This script can be
used with the DBTableLoginModule and DBTableOraDatasourceLoginModule,
setting the pw_encoding_class="oracle.sample.dbloginmodule.util.DBLoginModuleSHA1Encoder"
option in the LoginModule configuration.

To use other password encryptions techniques than SHA1, the LoginModule's password
encoder is made pluggable, allowing custom implementations to be created and
used. The default encoding class is DBLoginModuleClearTextEncoder, which
expects passwords to be stored in clear text the database table. The DBLoginModuleSHA1Encoder
used with one of the installation scripts uses the user password as the key
when creating the encrypted password representation for comparison with the
database stored user password. Developers that want to create their own password
encoder must implement the DBLoginModuleEncodingInterface to make their
implementation work with the LoginModules provided with this how-to document.
If database passwords are encrypted with the database encryption capabilities,
it may be preferred to use the DBProcLoginModule in a stored procedure
and handle the password verification directly in the database. An example stored
procedure that operates against the example database tables using the script
with clear text passwords is provided.
A JDeveloper test case project is provided to test each of the LoginModules
before deploying it to OC4J.
User accounts created by the TableLMDbScriptClearPw.sql or TableLMDbScriptEncryptedPw.sql
example scripts are
| Username |
Password |
Roles |
Application Realm |
| Darth Vader |
welcome0 |
Administrator,User,Content Owner |
Online Trainings |
| Luke Skywalker |
welcome1 |
User |
Online Trainings |
| Han Solo |
welcome2 |
User,Manager,Content Owner |
Online Trainings |
The application realm is used for fine grained application access control.
The application realm must not necessarily match the J2EE realm and is a named
identifier for the LoginModule to select the user roles. If no application realm
is provided in the JAAS LoginModule configuration then all roles are read from
the configured role table. The options to use are: realm_column="realm"
and application_realm="Online Trainings".
Possible JAAS database LoginModule custom enhancements: The example
database table scripts also contain columns that store information about the
validness of user accounts and granted user roles . For the user table, "SEC_USERS",
this column is named "VALID_ACCOUNT" and has a value of 1 for
valid user accounts and 0 for temporarily invalidated accounts. Similarly the
"SEC_USER_ROLE_MAPS" table has a "VALID_GRANT" column
to temporarily remove a permission from a user. The database LoginModules provided
with this paper don't evaluate these columns but could be adapted to do so.
The LoginModules' source code is provided and can be modified to reflect account
and role granting expiry. This modification is relative easy to do within the
"performDbAuthentication(String username, char[] password)" method,
which is part of each database LoginModules. All that needs to be done to handle
temporary user account and role grant expiry is to include the two columns mentioned
above in the JAAS authentication query for users and roles and evaluate the
results when adding Principals to the JAAS Subject. Adding this functionality
allows administrators to manage revocation lists easily, a feature that you
don't usually find in declarative J2EE authentication, especially because the
specification doesn't demand for it.
DBSystemLoginModule
The DBSystemLoginModule authenticates a user against a physical database schema
using the provided username and password for authentication. If the user can
be authenticated, the LoginModule reads all database role names that are granted
to this user and turns them into J2EE security roles. This LoginModules is ideal
for environments in which each user has his own database account and where non-J2EE
web applications need to co-exist with J2EE applications, leveraging the same
role names for permission granting.
The following JAAS options are case sensitive and can be configured for this
LoginModule
| Option |
Meaning |
| jdbcUrl |
The JDBC connect string except for username and password: jdbc:oracle:thin:@host:port:sid |
| jdbcDriver |
The JDBC driver used. The default setting is: "oracle.jdbc.driver.OracleDriver" |
| logger_class |
The class that implements the LMLogger interface to write log information
for this LoginModule. Custom logging can be implemented using this option.
The default configuration uses oracle.sample.dbloginmodule.util .ScreenLoggerImpl,
which writes log messages to the console. The logger_class option can be
omitted if console output is sufficient
A second option provided in the examples are oracle.sample. dbloginmodule.util.JavaLoggerImpl
to leverage the java.util.logging package, in which case the location
of a Java Logger properties file needs to be specified when starting OC4J
or a J2SE application |
| log_level |
This option determines the granularity of the messages that are printed
by the LoginModule. If this option isn't provided then all possible messages
are written if the "debug" option is set to true. Similar, specifying
log_level=ALL prints out all message details. Setting log_level to AUTH
will only print the messages that are directly related to the authentication
process itself |
| debug |
debug=true prints authentication process information to the configured
logging system, which by default is the console |
To configure the DBSystemLoginModule with jazn-data.xml in OC4J 10.1.2, a command
similar to the following needs to be specified on a command line in the OC4J_Home\j2ee\home
directory:
java -jar jazn.jar -addloginmodule <application name> oracle.sample.dbloginmodule.DBSystemLM.DBSystemLoginModule
required debug="true" log_level="ALL" jdbcUrl="jdbc:oracle:thin:@localhost:1521:orcl"
jdbcDriver="oracle.jdbc.driver.OracleDriver"
DBTableLoginModule
The DBTableLoginModule authenticates the user against a configurable
database table. Granted user roles as well are queried from a configurable table.
Unlike existing database LoginModules, this LoginModule does not demand for
a specific table structure, allowing users to leverage any existing database
tables. This LoginModule is useful when new J2EE built applications should leverage
existing custom security infrastructures in the database.
The following JAAS options are case sensitive and can be configured for this
LoginModule
| Option |
Meaning |
| jdbcUrl |
The JDBC connect string except for username and password: jdbc:oracle:thin:@host:port:sid |
| jdbcDriver |
The JDBC driver used. The default setting is: "oracle.jdbc.driver.OracleDriver" |
| logger_class |
The class that implements the LMLogger interface to write log information
for this LoginModule. Custom logging can be implemented using this option.
The default configuration uses oracle.sample.dbloginmodule.util .ScreenLoggerImpl,
which writes log messages to the console. The logger_class option can be
omitted if console output is sufficient
A second option provided in the examples are oracle.sample. dbloginmodule.util.JavaLoggerImpl
to leverage the java.util.logging package, in which case the location
of a Java Logger properties file needs to be specified when starting OC4J
or a J2SE application |
| log_level |
This option determines the granularity of the messages that are printed
by the LoginModule. If this option isn't provided then all possible messages
are written if the "debug" option is set to true. Similar, specifying
log_level=ALL prints out all message details. Setting log_level to AUTH
will only print the messages that are directly related to the authentication
process itself |
| db_schema |
The database schema that holds the user and role tables fro authentication
and authorization. The schema itself should be less privileged because of
its exposure in the JAAS configuration files. |
| db_schema_pw |
The password to connect to the database schema that holds the authentication
and authorization tables. The password is provided in clear text, which
is not safe. To make it safe, for J2EE applications it is recommended to
use the DBTableOraDataSourceLoginModule. |
| user_table |
The name of the table holding the user authentication columns |
| roles_table |
The name of the table holding the user role information |
| username_column |
The name of the column in the user table that holds the username |
| password_column |
The name of the column in the user table that holds the user password
for authentication |
| pw_encoding_class |
This LoginModules supports encrypted passwords in the database table
. The pw_encoding_class option expects an implementation of the DBLoginModuleEncodingInterface
interface to work with. This allows custom password encryption algorithms
to be used. Note that the passwords are compared by their encrypted values,
not by their unencrypted strings.
The default implementation uses passwords written in clear text. An alternative
implementation using SAH1 is provided with the oracle. sample.dbloginmodule.util.DBLoginModuleSHA1Encoder
class, which performs a SHA1 encryption plus base64 encoding of the password,
using the same string as a key if no extra encryption key is provided.
The SQL script "TableLMDbScriptEncryptedPw.sql" provides
a testcase that uses SHA1 encrypted passwords. |
| pw_key |
Option that, if provided, passes the encryption key to the LoginModule.
The key is accessible for the class specified in pw_encoding_class. |
| roles_column |
Name of the column in the roles table that holds the user role names |
| realm_column |
Optional, the name of the column in the roles table that holds the application
realm. The application realm can be used for fine grained authorization.
For example, a user may be granted the manager role in app1 but not in app2. |
| application_realm |
The name of an application realm that restricts the user role query. This
name is optional and is only required in combination with the realm_column.
Not specifying a realm makes the LoginModule to read all user roles from
the roles table |
| user_pk_column |
Name of the primary key column in the user table |
| roles_fk_column |
Name of the foreign key column in the roles table |
| debug |
debug=true prints authentication process information to the configured
logging system, which by default is the console |
To configure the DBSystemLoginModule with jazn-data.xml in OC4J 10.1.2, a command
similar to the following, based on the provided TableLMDbScriptEncryptedPw
example script, needs to be specified on a command line in the OC4J_Home\j2ee\home
directory
java -jar jazn.jar -addloginmodule <application name> oracle.sample.dbloginmodule.DBTableLM.DBTableLoginModule
required debug="true" log_level="ALL" jdbcUrl="jdbc:oracle:thin:@localhost:1521:orcl"
jdbcDriver="oracle.jdbc.driver.OracleDriver" db_schema="scott"
db_schema_pw="tiger" user_table="sec_users" roles_table="user_roles_view"
username_column="username" password_column="password" roles_column="rolename"
user_pk_column="userid" roles_fk_column="userid" realm_column="realm"
application_realm="Online Trainings" pw_encoding_class="oracle.sample.dbloginmodule.util.DBLoginModuleSHA1Encoder"
Note: It should be possible to copy the example configuration shown
above and paste it on a command line to save you from typing.
DBTableOraDataSourceLoginModule
One important aspect in application security is configuration
security. Unfortunately, providing database passwords in clear when configuring
the custom JAAS LoginModule is a possible security breech. To enable better
configuration security when deploying J2EE applications with OC4J, it is possible
to define a J2EE datasource for the database connect information and use the
password indirection feature of OC4J to encrypt the password. The DBTableOraDataSourceLoginModule
supports J2EE data sources and the OC4J password indirection and should be the
preferred LoginModule to use for user table based J2EE authentication. This
LoginModule however doesn't work in J2SE environments.
The following JAAS options are case sensitive and can be configured for this
LoginModule
| Option |
Meaning |
| logger_class |
The class that implements the LMLogger interface to write log information
for this LoginModule. Custom logging can be implemented using this option.
The default configuration uses oracle.sample.dbloginmodule.util .ScreenLoggerImpl,
which writes log messages to the console. The logger_class option can be
omitted if console output is sufficient
A second option provided in the examples are oracle.sample. dbloginmodule.util.JavaLoggerImpl
to leverage the java.util.logging package, in which case the location
of a Java Logger properties file needs to be specified when starting OC4J
or a J2SE application |
| log_level |
This option determines the granularity of the messages that are printed
by the LoginModule. If this option isn't provided then all possible messages
are written if the "debug" option is set to true. Similar, specifying
log_level=ALL prints out all message details. Setting log_level to AUTH
will only print the messages that are directly related to the authentication
process itself |
| data_source_name |
Name of the data source configured in the data-sources.xml file |
| user_table |
The name of the table holding the user authentication columns |
| roles_table |
The name of the table holding the user role information |
| username_column |
The name of the column in the user table that holds the username |
| password_column |
The name of the column in the user table that holds the user password
for authentication |
| pw_encoding_class |
This LoginModules supports encrypted passwords in the database table
. The pw_encoding_class option expects an implementation of the DBLoginModuleEncodingInterface
interface to work with. This allows custom password encryption algorithms
to be used. Note that the passwords are compared by their encrypted values,
not by their unencrypted strings.
The default implementation uses passwords written in clear text. An alternative
implementation using SAH1 is provided with the oracle. sample.dbloginmodule.util.DBLoginModuleSHA1Encoder
class, which performs a SHA1 encryption plus base64 encoding of the password,
using the same string as a key if no extra encryption key is provided.
The SQL script "TableLMDbScriptEncryptedPw.sql" provides
a testcase that uses SHA1 encrypted passwords. |
| pw_key |
Option that, if provided, passes the encryption key to the LoginModule.
The key is accessible for the class specified in pw_encoding_class. |
| roles_column |
Name of the column in the roles table that holds the user role names |
| realm_column |
Optional, the name of the column in the roles table that holds the application
realm. The application realm can be used for fine grained authorization.
For example, a user may be granted the manager role in app1 but not in app2. |
| application_realm |
The name of an application realm that restricts the user role query. This
name is optional and is only required in combination with the realm_column.
Not specifying a realm makes the LoginModule to read all user roles from
the roles table |
| user_pk_column |
Name of the primary key column in the user table |
| roles_fk_column |
Name of the foreign key column in the roles table |
| debug |
debug=true prints authentication process information to the configured
logging system, which by default is the console |
To configure the DBSystemLoginModule with jazn-data.xml in OC4J 10.1.2, a command
similar to the following, based on the provided TableLMDbScriptEncryptedPw
example script, needs to be specified on a command line in the OC4J_Home\j2ee\home
directory
java -jar jazn.jar -addloginmodule <application name> oracle.sample.dbloginmodule.DBTableLM.DBTableOraDataSourceLoginModule
required debug="true" log_level="ALL" data_source_name="jdbc/OracleDS"
user_table="sec_users" roles_table="user_roles_view" username_column="username"
password_column="password" roles_column="rolename" user_pk_column="userid"
roles_fk_column="userid" realm_column="realm" application_realm="Online
Trainings" pw_encoding_class="oracle.sample.dbloginmodule.util.DBLoginModuleSHA1Encoder"
The J2EE datasource information configured in the OC4J_Home\j2ee\home\config\data-sources.xml
looks similar to the following
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="jdbc/OracleDS"
location="jdbc/OracleCoreDS"
xa-location="jdbc/xa/OracleXADS"
ejb-location="jdbc/OracleDS"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="scott"
password="->PwdForScott"
url="jdbc:oracle:thin:@localhost:1521:orcl"
inactivity-timeout="30"
/>
The bootstrap jazn-data.xml file located in the OC4J_Home\j2ee\home\config
directory contains the user password, which gets encrypted after restarting
OC4J
<user>
<name>PwdForScott</name>
<display-name>PwdForScott</display-name>
<description>Scott's password</description>
<credentials>!tiger</credentials>
</user>
DBProcLoginModule
Generic LoginModules are hard to write for complex customer
environments that leverage their own security schema, if it is not based on
two simple database tables. Another use case for this LoginModule is if database
encryption capabilities are used to encrypt the user passwords, which also is
a better solution then delegating password encryption to the middle tier where
it can't be shared across different types of applications.
The DBProcLoginModule handles this more complex usecase
and relies on a store database procedure to authenticate users. The granted
user roles are provided to the LoginModule through a ref cursor. An example
stored PLSQL procedure, taken from the example SQL scripts, looks like
CREATE OR REPLACE PACKAGE "DBPROCLM" IS
TYPE principal_ref IS REF CURSOR;
function get_user_authentication(p_username in varchar2, p_password in
varchar2, p_realm varchar2) return principal_ref;
END;
/
CREATE OR REPLACE PACKAGE BODY "DBPROCLM" IS
FUNCTION get_user_authentication (p_username in varchar2, p_password
in varchar2, p_realm varchar2)
RETURN principal_ref
AS
var_username varchar2(100);
var_userid number(10);
var_password varchar2(100);
role_cursor principal_ref;
FAILED_AUTHENTICATION exception;
BEGIN
select userid, username, password into var_userid, var_username,
var_password from sec_users where username = p_username;
if (var_password = p_password) then
begin
if (p_realm is null) then
open role_cursor for
select rolename from user_roles_view
where userid = var_userid;
else
open role_cursor for
select rolename from user_roles_view
where userid = var_userid and realm=p_realm;
end if; -- p_realm check
end;
-- if password doesn't match, raise Excpetion for
LM to
-- abort the authentication process
else raise FAILED_AUTHENTICATION;
end if;
RETURN role_cursor;
END get_user_authentication;
END;
/
The following JAAS options are case sensitive and can be
configured for this LoginModule
Option |
Meaning |
jdbcUrl |
The JDBC connect string except for username and password: jdbc:oracle:thin:@host:port:sid |
jdbcDriver |
The JDBC driver used. The default setting is: "oracle.jdbc.driver.OracleDriver" |
logger_class |
The class that implements the LMLogger interface to write log
information for this LoginModule. Custom logging can be implemented
using this option. The default configuration uses oracle.sample.dbloginmodule.util
.ScreenLoggerImpl, which writes log messages to the console.
The logger_class option can be omitted if console output is sufficient.
A second option provided in the examples are oracle.sample. dbloginmodule.util.JavaLoggerImpl
to leverage the java.util.logging package, in which case the
location of a Java Logger properties file needs to be specified
when starting OC4J or a J2SE application |
log_level |
This option determines the granularity of the messages that are
printed by the LoginModule. If this option isn't provided then all
possible messages are written if the "debug" option is
set to true. Similar, specifying log_level=ALL prints out all message
details. Setting log_level to AUTH will only print the messages
that are directly related to the authentication process itself |
db_schema |
The database schema that holds the user and role tables fro authentication
and authorization. The schema itself should be less privileged because
of its exposure in the JAAS configuration files. |
db_schema_pw |
The password to connect to the database schema that holds the
authentication and authorization tables. The password is provided
in clear text, which is not safe. To make it safe, for J2EE applications
it is recommended to use the DBTableOraDataSourceLoginModule. |
plsql_procedure |
The name of the PLSQL procedure to delegate authentication and
authorization to |
application_realm |
The name of an application realm that restricts the user role
query. This name is optional and is only required if the stored
procedure supports least privilege access through application specific
role grants. |
debug |
debug=true prints authentication process information to the configured
logging system, which by default is the console |
Note that the example stored procedure shown above doesn't handle encrypted
passwords, which means that testing requires the TableLMDbScriptClearPw.sql
to be installed. To configure the DBSystemLoginModule with jazn-data.xml in
OC4J 10.1.2, a command similar to the following needs to be specified on a command
line in the OC4J_Home\j2ee\home directory
java -jar jazn.jar -addloginmodule <application name> oracle.sample.dbloginmodule.DBProcLM.DBProcLoginModule
required debug="true" log_level="ALL" jdbcUrl="jdbc:oracle:thin:@localhost:1521:orcl"
jdbcDriver="oracle.jdbc.driver.OracleDriver" db_schema="scott"
db_schema_pw="tiger" plsql_procedure="DBPROCLM.GET_USER_AUTHENTICATION"
application_realm="Online Trainings"
DBProcOraDataSourceLoginModule
Similar to what is mentioned for using the DBTableLoginModule
implementation, exposing the database password in clear in the JAAS configuration
doesn't support secure configuration. For this reason the DBProcOraDataSourceLoginModule
supports the use of J2EE data sources for configuring the LoginModule's database
connection. In combination with the OC4J password indirection feature, configuration
security is provided. The DBProcOraDataSourceLoginModule can't be used
with J2SE applications because of its dependency to the data-sources.xml
file.
The following JAAS options are case sensitive and can be configured for this
LoginModule
| Option |
Meaning |
| logger_class |
The class that implements the LMLogger interface to write log information
for this LoginModule. Custom logging can be implemented using this option.
The default configuration uses oracle.sample.dbloginmodule.util .ScreenLoggerImpl,
which writes log messages to the console. The logger_class option can be
omitted if console output is sufficient.
A second option provided in the examples are oracle.sample. dbloginmodule.util.JavaLoggerImpl
to leverage the java.util.logging package, in which case the location
of a Java Logger properties file needs to be specified when starting OC4J
or a J2SE application |
| log_level |
This option determines the granularity of the messages that are printed
by the LoginModule. If this option isn't provided then all possible messages
are written if the "debug" option is set to true. Similar, specifying
log_level=ALL prints out all message details. Setting log_level to AUTH
will only print the messages that are directly related to the authentication
process itself |
| plsql_procedure |
The name of the PLSQL procedure to delegate authentication and authorization
to |
| application_realm |
The name of an application realm that restricts the user role query. This
name is optional and is only required if the stored procedure supports least
privilege access through application specific role grants. |
| data_source_name |
Name of the data source configured in the data-sources.xml file |
| debug |
debug=true prints authentication process information to the configured
logging system, which by default is the console |
Note that the example stored procedure shown above doesn't handle encrypted
passwords, which means that testing requires the TableLMDbScriptClearPw.sql
to be installed. To configure the DBSystemLoginModule with jazn-data.xml in
OC4J 10.1.2, a command similar to the following needs to be specified on a command
line in the OC4J_Home\j2ee\home directory
java -jar jazn.jar -addloginmodule <application name> oracle.sample.dbloginmodule.DBProcLM.DBProcOraDataSourceLoginModule
required debug="true" log_level="ALL" data_source_name="jdbc/OracleDS"
plsql_procedure="DBPROCLM.GET_USER_AUTHENTICATION" application_realm="Online
Trainings"
The J2EE datasource information configured in the OC4J_Home\j2ee\home\config\data-sources.xml
looks similar to the following
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="jdbc/OracleDS"
location="jdbc/OracleCoreDS"
xa-location="jdbc/xa/OracleXADS"
ejb-location="jdbc/OracleDS"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="scott"
password="->PwdForScott"
url="jdbc:oracle:thin:@localhost:1521:orcl"
inactivity-timeout="30"
/>
The bootstrap jazn-data.xml file located in the OC4J_Home\j2ee\home\config
directory contains the user password, which gets encrypted after restarting
OC4J
<user>
<name>PwdForScott</name>
<display-name>PwdForScott</display-name>
<description>Scott's password</description>
<credentials>!tiger</credentials>
</user>
Writing log information
Setting the JAAS LoginModule's debug option to true
prints out logging messages during the authentication process. The granularity
of the printed message can be configured using the log_level LoginModule
option, which can be set to "ALL" or "AUTH". The "AUTH"
value prints only the information required to document the authentication process.

For logging, all database JAAS LoginModules support a pluggable
logging infrastructure, which by default uses an implementation of System.out.println()
to write the log output to the console. An implementation that leverages the
java.util.logger package is provided as an alternate logging provider. To write
a custom logger class, the LMLogger interface needs to be implemented.
To use a logger instance other than the default, the JAAS LoginModule option
logger_class is set to a value of "oracle.sample.dbloginmodule.util.JavaLoggerImpl"
or any other custom logger class. For the java.util.logging.Logger class implementation
to work, the application needs to be started with the -Djava.util.config.file
command line option. The referenced config file needs to be a valid Java
Logger properties file, as defined in the J2SE documentation.
The Oracle OC4J default logging is based on the J2SE 1.4 java.util.logging
as well. This means that even if the JAAS LoginModules uses System.out.println()
for logging, messages get written to the java.util.logging.Logger class.
To customize the logging output format, a Logger properties file can be specified
when starting OC4J with the -Djava.util.config.file option
java -Djava.util.logging.config.file=<OC4J Home>\j2ee\home\config\<logger
file name>.properties -jar oc4j.jar
Note that using the database LoginModules with J2SE applications requires the
-Djava.util.logging.config.file to be specified with the application
start command if messages should be written with the java.util.logging.Logger
class. An example properties file is provided in the JDeveloper 10.1.2 LoginModuleTestCase
project contained in the demo downloads.
Using the provided ANT scripts
for configuration
To ease the task of installation and administration, an Ant
script is provided that can be used to configure the various LoginModules provided
with this paper. The scripts requires Apache
Ant version 1.6 or above.
The Ant scripts are located in the JDeveloper1012Workspaces\DatabaseLoginModule1012
directory contained in the demo sources zip file.
The scripts must be executed within this directory because all the required
deployment sources and SQL scripts are addressed relative to that location.
The benefit of storing the scripts within the DatabaseLoginModule1012 directory
comes from this directory also being the Oracle JDeveloper 10.1.2 workspace
directory. This way the scripts can be used to deploy custom modifications of
the LoginModules to OC4J without having to copy the source files to other locations.
Note that the source files and scripts are provided as they are. You can use
them as a starting point for custom LoginModule development.
What the Ant Script does for you
The primary function of the supplied Ant script is to eliminate
typing errors in the long commands needed to add LoginModules using jazn.jar.
The script has a set of pre-built targets, one for each flavor of LoginModule
documented in this paper. All of the settings such as the name of the application
that is being secured and the connection information are defined in the build.properties
file which you need to customize before running the script.
As well as installing (and removing) login modules the script
also ensures that the custom LoginModule jar file is put in the correct place
in the OC4J directory structure, and it will also set up the database schema
objects used by the demo application if required.
Note that there are still some manual tasks that you will
need to carry out when using this script:
- You must edit the DatabaseLoginModule1012\build.properties file to
define your environment and settings
- You must still manually your OC4J application.xml file to add the entry
for the custom LoginModule jar file
- You must manually define any DataSources that you may be using in the OC4J
data-sources.xml
Running the Ant Script
For convenience a simple DOS batch file is provided for windows
users run.bat. This simply acts as a wrapper to run the supplied Ant
build script. To use this batch file, set the environment variables JAVA_HOME
and ANT_HOME to point to the Java SDK directory and the Ant install directories
respectively. You can set these values from the command shell using the SET
command, or you can edit the REM'ed out values in the DatabaseLoginModule1012/run.bat
file, (don't forget to uncomment the settings by removing the REM string in
front of it). Once theses variables are set you type run at the command
prompt and the usage screen for the script will display:

To carry out a specific action, such as installing the demo
tables with clear-text passwords, type run followed by the name of the
target as specified by the usage screen. In this case run demoClear.
Note that the run targets are case sensitive.
If you are not running on a Windows platform you can still
run the Ant scripts by directly invoking the ant command from the DatabaseLoginModule1012
directory. You should again set JAVA_HOME and ANT_HOME in your environment shell
before doing so. The command to run is $ANT_HOME/bin/ant demoClear to
install the demo tables as above.
About the demos that use encrypted user passwords
The Ant script does support the installation of the sample
SQL script with the encrypted passwords in it. It doesn't however configure
the LoginModules. To test it, configure the DBTableLoginModule by running the
run table command. Open the jazn-data.xml file and add
<option>
<name>pw_encoding_class</name>
<value>oracle.sample.dbloginmodule.util.DBLoginModuleSHA1Encoder</value>
</option>
to the configuration before starting up OC4J.
Testing the Ant Script
The JDeveloper1012Workspaces\DBLMTest directory also
is an Oracle JDeveloper 10.1.2 workspace directory. It contains a J2EE application
that you can use for testing. Deploy the application to the OC4J instance you
configured with the Ant Script and it will create an application "foo"
that is by default the configuration name used in the scripts.
Request the application after deployment by typing the following
URL
http://servername:port/foo-webcontext/authtest.jsp
If you deployed the DBSystemLoginModule, provide a valid database schema username
and password in the authentication dialog. If you use one of the other LoginModules,
assuming you installed the example SQL scripts, try Han Solo as a username
and welcome2 as the password. See a list of all user accounts here.
Note: Please read the comments provided in the build.properties file.
SQL Injection detection
With the first invention of keys and locks, a breed of people
was born that never learned to accept "no" for an answer. This group
of users typically tries to explore a system for what's beneath, trying to break
in to what they normally aren't granted access to. One way of doing this is
to use SQL injection, which is an act of entering SQL commands where developers
expect username and passwords to be provided. The database LoginModules provided
with this document use prepared statements when querying the underlying database,
which should be safe. To better secure the JAAS LoginModule implementation,
regular expression is used to analyze the provided username and passwords strings
for possible SQL injection attacks. The LoginModules will immediately stop processing
authentication the authentication when one of the defined SQL key words is found
as part of the user login. This solution is not 100 % perfect and may not resist
the attempt of a skilled hacker, but it helps keeping out the wannabe's.
// SQL INJECTION DETECTION
// Detects and reports SQL injection attempts. The following code logs all attempts
to enter
// SQL commands like create, drop, update, delete, insert, hexadecimal encoded
characters etc.
// and immediately returns false
Pattern p = Pattern.compile("(?i)\\bselect|create|insert|delete|drop|update|or|%.\\d\\b");
Matcher m = p.matcher(username);
if (m.find())
{
//someone tries to break into this application and should be tracked
back
log("SQL Injection attempt detected: username was altered
to include SQL keyword: "+m.group(),LOG_AUTH);
return false;
}
All database LoginModules that perform authentication based on user and role
tables contain this code snippet. The regular expression can be extended to
filter even more SQL key words if needed.
Working with the LoginModuleTestCase
project in Oracle JDeveloper 10.1.2
The Oracle JDeveloper 10.1.2 LoginModuleTestCase project
is contained in the "DatabaseLoginModule1012" workspace and
allows instant LoginModule testing to be performed. For this, the LoginModule
configuration is stored in a text file "jaasTestConfig.txt"
that is part of the JDeveloper project as well. This file contains named configuration
sections and can be edited with a text editor or within Oracle JDeveloper directly.
Executing the JaasTester.java file performs the LoginModule
functional testing, writing all messages to the JDeveloper output window. Testings
scenarios are defined in the class constructor and can be enabled by uncommenting
the code line. Each test references a configuration in the jaasTestConfig.txt
file.
/* Database Schema Users */
// lc = new LoginContext("DBTableLoginModuleTest", pcbh);
/* Clear Text Passwords in User Table */
// lc = new LoginContext("DBTableLoginModuleJavaLogger", pcbh);
/* Encrypted Passwords in User Table */
//lc = new LoginContext("DBTableLoginModuleJavaLoggerEncrPw", pcbh);
/* Authentication using stored procedure */
lc = new LoginContext("DBProcLoginModuleJavaLogger", pcbh);
In addition, the LoginModuleTestCase project contains the two example
SQL scripts to populate a database schema with the example user and role tables.
All test entries in the jaasTestConfig.txt file that have the "EncrPw"
string in their name require the script TableLMDbScriptEncryptedPw.sql
to be used.

The main method of the JaasTester class performs the authentication when instantiating
the JaasTester. The username and password pair to test is provided in the constructor,
allowing multiple accounts to be tested within one execution.
The DbLoginModuleFileLogging.properties entry in the LoginModuleTestCase
project enables testing of the java.util.logging package, using the logger_class="oracle.sample.dbloginmodule.util.JavaLoggerImpl
option in the jaasTestConfig.txt JAAS LoginModule configuration. For
example, to switch between an XML formatted log and a plain text log, the following
two lines contained in the logger properties file can be switched:
#java.util.logging.ConsoleHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
Testing the LoginModules in OC4J using the DBLMTest J2EE
web application
To make it easy to get started with deploying the custom database login modules,
a J2EE web application is provided in a separate Oracle JDeveloper 10.1.2 workspace,
named DBLMTest. The testcase only contains one project with one JSP file
that shows a table listing the name of the authenticated user and the granted
J2EE security roles. The logon is configured to use BASIC authentication. To
use this application, the following steps should be followed
- Deploy and configure the custom database LoginModule JAR file to OC4J
- Configure the bootstrap jazn-data.xml file to include the LAAS LoginModule
configuration for the "DBLMTest" application
- Create a OC4J connection in Oracle JDeveloper 10.1.2
- Deploy the DBLMTest project from JDeveloper 10.1.2 to OC4J using
the project's DBLMTest.deploy entry
- After successful deployment, run the URL http://<server name>:8888/DBLoginModuleTest/authtest.jsp
The following screen is shown when running the example and authenticating as
"Han Solo" with a password of "welcome2"

Troubleshooting
We did our best to describe the configurations of the LoginModules and also
provided an Ant configuration script for you to use. To expect the unexpected,
this section is about troubleshooting the situation in which the custom J2EE
application cannot be authenticated and the logon screen keeps on showing.
Enable debugging
All the provided LoginModules can print debug messages to the OC4J console
window. To enable debugging, the debug flag needs to be set to true in the jazn-data.xml
file configuration.
<options>
<option>
<name>debug</name>
<value>true</value>
</option>
<option>
<name>log_level</name>
<value>ALL</value>
</option>
</options>
If no debug messages are written
If no debug messages are written then chances are that either
the J2EE application name doesn't match the case sensitive name specified in
the LoginModule configuration or that the JAR file containing the LoginModules
is not accessible in OC4J.
jazn-data.xml
Verify that the jazn-data.xml file located in the OC4J_Home\j2ee\home\config
directory contains the LoginModule configuration for the J2EE application. The
name of the JAAS LoginModule configuration should be exactly the same name you
provided in the Enterprise Application
Name option of the deployment profile configuration. Note that the enterprise
application name does not represent the web context root. The name of the enterprise
application and the web context root can be same but don't have to be.
Note The jazn-data.xml file that gets deployed with
the project is not used and can be omitted completely.
Wrong location of DBLoginModule.jar
The Java Archive file (JAR) that contains the custom LoginModule needs to be
copied to the OC4J_Home\lib directory and configured in the OC4J_Home\j2ee\home\config\application.xml
to be available for all web applications deployed on a OC4J instance.
<library path="../../../lib/DBLoginModule.jar"/>
Missing or badly configured orion-application.xml file
The orion-application.xml file defines that custom LoginModules
should be used by OC4J for J2EE authentication and must be added
to and deployed with the Oracle JDeveloper project. A missing orion-application.xml
file disables custom JAAS authentication and enforces the default container
managed authentication.
If debug messages are written
Debug messages indicate success of the JAAS LoginModule configuration.
The information provided should be explicit enough for you to track down the
problem. For security reasons the debug statement doesn't print any user passwords,
even for failed login attempts.
[DBSystemLoginModule] Error: Io exception: The Network Adapter
could not establish the connection
Start the database and make sure the TNS listener is working
[DBSystemLoginModule] Error: Io exception
ORA-12505, TNS:listener does not currently know of SID given
in connect descriptor The Connection descriptor used by the client was:
localhost:1521:orcls
Make sure the database information provided in the jdbcUrl
configuration option of the LoginModule is correct.
[DBTableLoginModule] Error: ORA-01017: invalid username/password;
logon denied
You are using one of the table or PLSQL stored procedure
based LoginModules. The database schema access information provided for the
LoginModule to access the user and role tables is not correct.
You can't find the encryption class to create encrypted
passwords
One of the sample SQL scripts creates database user tables
with encrypted passwords. The file used to encrypt the data is not provided.
Modern encryption is based on algorithms that are publicly known and encryption
keys that are kept secret. The encryption in the example uses a very weak key
that should not be used in production. We've seen many lines of demo code getting
copied unchanged into production code sources so that we decided to not publish
this part of the example. The JAAS LoginModules that authenticate against tables
with encrypted passwords are configurable to use custom
encoding classes to work with custom encryption.
Downloads
The jaasdatabaseloginmodule.zip file contains two JDeveloper 10.1.2 workspaces.
The "DatabaseLoginModule1012" workspace contains the JAAS LoginModules
and the JaasTester project with the SQL scripts mentioned throughout this paper.
The "DBLMTest" workspace contains the J2EE application shown above
that can be used to test the JAAS LoginModules with OC4J. It is strongly recommended
to use the password indirection feature for all JAAS LoginModules that otherwise
would expose user passwords in their configuration. The JAAS LoginModules are
also made available in a separate JAR file.
In addition to the LoginModule and JDeveloper source files, the zip file also
contains ANT scripts to automate the configuration of JAAS LoginModules in OC4J.
Note that the Ant scripts require at least Ant
version 1.6.
Download
|