Skip Headers
Oracle® Application Server Containers for J2EE Security Guide
10g Release 2 (10.1.2)
B14013-02
  Go To Documentation Library
Library
Go To Product List
Product
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

10 Custom Login Modules

OC4J supplies a JAAS pluggable authentication framework that conforms to the JAAS standard. With this framework, an application server and any underlying authentication services remain independent from each other, and alternative authentication services can be plugged in through JAAS login modules without requiring modifications to the application server or application code.

This chapter discusses how to write and install a LoginModule to be used with the OracleAS JAAS Provider. The following topics are covered:


Notes:

  • Because the JAAS specification does not cover user management, when you configure your application to use a custom LoginModule, the use of the UserManager API within your application is not supported. The J2EE API, however, will continue to function within your application.

  • Because JAAS login module configuration is always stored in the OC4J home instance jazn-data.xml file, you should select the XML-based provider as the security provider for your application during deployment. Use of the LDAP-based provider in conjunction with custom login modules is not supported.

  • In almost all cases, you should set the JAZN property role.mapping.dynamic to "true" when you configure your application to use custom login modules. This property is "false" by default. Also see the discussion of this property under the <jazn> element in "The orion-application.xml File".


Integrating Custom JAAS Login Modules

A custom JAAS LoginModule may be desirable when Oracle Identity Management is not available and users and roles are defined in an external repository. You can configure a LoginModule using the XML-based provider type. When you create a custom LoginModule, the following preliminary questions need to be considered.

  1. Development: Do you want to take advantage of J2EE security constraints?

  2. Development, packaging, and deployment: Are you using the login modules that come with J2SE 1.4? Or are you deploying custom or third-party login modules?


    Note:

    Custom login modules are supported only with the XML-based provider.

Developing a Login Module

You can use an any JAAS-compliant LoginModule within the OC4J framework.


See Also:


When developing a LoginModule, you must consider several important issues:

Each of these is discussed in detail in its own section.

Subject-Based Authorization

When you associate a custom LoginModule with an application, the subject and the principals it contains are used as the sole basis for all authorization tasks, including evaluating J2EE security constraints. To ensure that all relevant principals are considered during authorization, the LoginModule must add the relevant principals, including all roles and groups that the authenticated user participates in, to the subject during the commit phase of the JAAS authentication process.

J2EE Security Authorization

The OracleAS JAAS Provider custom LoginModule framework supports the J2EE declarative security model. This means that subject-based authorization enforces the J2EE security constraints declared in deployment descriptors (web.xml and ejb-jar.xml, for example). We encourage you to take advantage of the J2EE security model whenever possible.

Callback Support

The OracleAS JAAS Provider supports the standard javax.security.auth.callback name (NameCallback) and password (PasswordCallback) callbacks.

Debugging Tips

When debugging your secure application, bear the following issues in mind:

Debug Logging

To turn on JAAS provider debug logging, set the system property jazn.debug.log.enable to true during Java Virtual Machine (JVM) startup.

You do this by modifying the <java-options> settings for your OC4J instance. In Oracle Application Server, you normally manage these settings using Oracle Enterprise Manager 10g Application Server Control Console, which stores these settings in opmn.xml. From the home page of your OC4J instance, do the following:

  1. Choose Administration.

  2. From the Administration page, choose Server Properties.

  3. From the Server Properties page, under Command Line Options, enter the option for debug logging (as described immediately following).

When running OC4J outside Oracle Application Server, you set this property using JVM command-line options. For instance, you might start standalone OC4J with a command line such as:

java -Djazn.debug.log.enable=true -jar oc4j.jar 

Or you might start the Admintool shell in debug mode with the command:

java -Djazn.debug.log.enable=true -jar jazn.jar -shell

When you turn on debug logging, the OracleAS JAAS Provider logs debugging output to the console. Under Oracle Application Server, debugging output is captured in the ORACLE_HOME/opmn/logs directory.

Debugging Login Modules

We encourage you to include debugging options in your custom LoginModule. For an example, see the default login module, RealmLoginModule, which provides diagnostic output if debug is set to true.

Accessing EJBs When Using Custom Login Modules

To access an EJB using a custom LoginModule, you must:

  • Grant login permission to the user JDOE_ENDUSER in the OC4J home instance jazn-data.xml file.

  • Grant namespace-access to the user JDOE_ENDUSER in orion-application.xml.

To grant login permission to JDOE_ENDUSER, use the JAZN Admintool, as in the following example:

java -jar jazn.jar -grantperm login -user JDOE_ENDUSER oracle.j2ee.server.rmi.RMIPermission 

To grant namespace access to JDOE_ENDUSER, edit orion-application.xml to add a <namespace-access> element like the following:

<namespace-access> 
  <read-access> 
    <namespace-resource root="">
      <security-role-mapping>
        <user name="JDOE_ENDUSER" />
      </security-role-mapping> 
    </namespace-resource>
  </read-access> 
</namespace-access>

Adding and Removing Login Modules

You use the JAZN Admintool to add and remove login modules. For basic information on running the JAZN Admintool, see "Admintool Overview" .

java -jar jazn.jar -addloginmodule application_name login_module_name
     control_flag [optionname=value ...]
java -jar jazn.jar -remloginmodule application_name login_module_name

The -addloginmodule option configures a new LoginModule for the named application.

The control_flag setting must be one of required, requisite, sufficient or optional, as specified in javax.security.auth.login.Configuration. See Table 10-1.

Table 10-1 Login Module Control Flags

Flag Meaning

required

The LoginModule must succeed. Whether or not it succeeds, authentication proceeds down the LoginModule list.

requisite

The LoginModule must succeed. If it succeeds, authentication continues down the LoginModule list. If it fails, control immediately returns to the application (authentication does not continue down the LoginModule list).

sufficient

The LoginModule is not required to succeed. If it succeeds, control immediately returns to the application and authentication does not proceed down the LoginModule list. If it fails, authentication continues down the LoginModule list.

optional

The LoginModule is not required to succeed. Whether or not it succeeds, authentication proceeds down the LoginModule list.


If the LoginModule accepts its own options, you specify each option and its value as an optionname=value pair. Each LoginModule has its own individual set of options.

For instance, to add MyLoginModule to the application myapp as a required module with debug set to true, specify:

java -jar jazn.jar -addloginmodule myapp MyLoginModule required debug=true

To delete MyLoginModule from myapp, specify:

java -jar jazn.jar -remloginmodule myapp MyLoginModule

Admintool shell:

JAZN:> addloginmodule myapp MyLoginModule required debug=true 
JAZN: remloginmodule myapp MyLoginModule

Listing Login Modules

Use the JAZN Admintool to list login modules.


See Also:


java -jar jazn.jar -listloginmodules [application_name [login_module_class]]

The -listloginmodules option displays all login modules either in the specified application_name , or, if no application_name is specified, in all applications. Specifying login_module_class, after application_name, displays information on only the specified class within the application.

For example, to display all login modules for the application myapp, specify:

java -jar jazn.jar -listloginmodules myapp

Admintool shell:

JAZN:> listloginmodules myapp

Packaging and Deploying

If you are using one or more of the default login modules provided with J2SE 1.3 and 1.4 (such as the J2SE1.4 com.sun.security.auth.module.Krb5LoginModule), then no additional configuration is needed. The OracleAS JAAS Provider can locate the default login modules.

If you are deploying your application with a custom login module, then you must deploy the login module and configure the OracleAS JAAS Provider properly so that the module can be found at runtime.

The following options are available when packaging and deploying your custom login modules:

The remainder of this section discusses these options in greater detail.

Deploying as Standard Extensions or Optional Packages

If you deploy your login modules as standard extensions, the OracleAS JAAS Provider will be able to find them. No additional configuration is necessary. Deploying login modules as standard extensions allows multiple applications to share the deployed login modules.

For example, one way to deploy your login modules as standard extensions is to deploy them to the ORACLE_HOME/j2ee/instance_name/lib/ext directory.


See Also:


Deploying within the J2EE Application

If your login module is used only by a single J2EE application rather than shared among multiple applications, then you can simply package your login module as part of your application, and the OracleAS JAAS Provider will be able to find it. No additional configuration is necessary.

If a later application needs the same LoginModule, you must repackage the login module and any relevant classes with the new application.

If you want to enable multiple applications to share the same LoginModule but you cannot deploy the LoginModule as an extension, then you can consider using the OC4J classloading mechanism.

Using the OC4J Classloading Mechanism

The OracleAS JAAS Provider is integrated with the OC4J classloading architecture. If you configure your application so that the deployed custom login modules are part of your application classpath, then the OracleAS JAAS Provider can locate them.

One way to accomplish this is using the <library> element in either of the following files:

Configuring Your Application

You modify the following files to configure your application to take advantage of custom login modules:

This section gives details on the configuration files.


Note:

You must choose the XML-based provider when using custom login modules, as discussed in "Integrating Custom JAAS Login Modules".

The jazn-data.xml File

All login module configuration information is stored in the OC4J home instance jazn-data.xml file. This file is usually located in the ORACLE_HOME/j2ee/home/config directory.


Note:

The home instance jazn-data.xml must contain accounts for "admin" and "anonymous". Do not remove these accounts; if you do, the administrative functions of the OracleAS JAAS Provider will not work.

You must modify the home instance jazn-data.xml file whenever you deploy your application into a new OC4J instance. You edit this file using the JAZN Admintool.

The following sections discuss these XML elements:

<jazn-loginconfig>

This element contains information that associates applications with login modules.

Example 10-1 Example <jazn-loginconfig> Element

<jazn-loginconfig>
  <application>
    <name>sampleLM</name>
    <login-modules>
       <login-module>
          <class>oracle.security.jazn.samples.SampleLoginModule</class>
          <control-flag>required</control-flag>
       </login-module>
    </login-modules>
  </application>
</jazn-loginconfig>

This fragment associates the application sampleLM with the login module sample.SampleLoginModule.


Note:

Do not remove login configuration information on RealmLoginModule.

<jazn-policy>

This element contains information that associates grantees with permissions. If you want to make your fat client accessible to an EJB, you must explicitly make the permissions available. When you deploy a custom LoginModule in OC4J, you normally use custom principal classes or types. To grant or revoke permissions to these types, use the JAZN Admintool.


Note:

These policies must be set in the home instance jazn-data.xml file, in the ORACLE_HOME/j2ee/home/config directory.

Example 10-2 Example <jazn-policy> Element

<jazn-policy>
  <grant>
   <grantee>
     <principals>
      <principal>
        <class>oracle.security.jazn.samples.SampleUser</class>
        <name>admin</name>
      </principal>
    </principals>
   </grantee>
   <permissions>
     <permission>
       <class>oracle.j2ee.server.rmi.RMIPermission</class>
       <name>login</name>
     </permission>
   </permissions>
  </grant>
</jazn-policy>

This fragment grants the permission oracle.j2ee.server.rmi.RMIPermission with target name login to the principal with class oracle.security.jazn.samples.SampleUser and name admin.


Note:

Oracle recommends that you manage the contents of jazn-data.xml using the JAZN Admintool.


See Also:


The web.xml or ejb-jar.xml File

To take advantage of J2EE declarative security in your application, you must configure the appropriate security constraints, either using your IDE or by hand-editing either the web.xml or ejb-jar.xml file.


See Also:


The orion-application.xml File

This file is a container-specific deployment descriptor that is generated for each application deployed in OC4J. The following elements are relevant to writing custom login modules:


Note:

This section discusses only elements relevant to security.


See Also:


<jazn>

The following <jazn> property is specific to LoginModule configuration:

  • role.mapping.dynamic

    This property, when set to true, instructs the OracleAS JAAS Provider to base authorization checks on the authenticated Subject instance instead of basing checks on the users and roles defined in the application specific jazn-data.xml file.

    The LoginModule instance (or instances) must ensure that the appropriate principals (users, roles, or groups) are associated with the Subject instance during the commit phase of the authentication process, in order for the principals to be taken into consideration during the authorization process. This association of principals to the Subject instance is typically implemented using the standard JAAS API.

<jazn provider="XML" location="./jazn-data.xml">
   <property name="role.mapping.dynamic" value="true" />
</jazn>

See Also:


<security-role-mapping>

When you set J2EE security constraints in the web.xml or ejb-jar.xml file, you must configure security role mapping.The optional <security-role-mapping> element describes static security-role mapping information. If you set J2EE security constraints in your application deployment descriptors (web.xml or ejb-jar.xml), you must configure security role mapping.

<library>

This element adds to the classpath associated with your application. For example:

<library path="../../shared/lib/sample.jar"/>
<library path="../../shared/lib/samplemodule.jar"/>

The oc4j-ra.xml File (J2EE Connector Architecture)

Each <connector-factory> element in oc4j-ra.xml can specify a different JAAS login module, as in the following example. This also shows <config-property> setup to connect to a database through Oracle JDBC.

  <connector-factory connector-name="myBlackbox" location="eis/myEIS1"> 
     <config-property name="connectionURL"
                      value="jdbc:oracle:thin:@localhost:5521/myservice" />
     <security-config use="jaas-module">
        <jaas-module>
           <jaas-application-name>JAASModuleDemo</jaas-application-name>
        </jaas-module>
     </security-config>
  </connector-factory>

Simple Login Module J2EE Integration

Developing a simple LoginModule follows the standard development, packaging, and deployment cycle. The following sections discuss each step in the cycle.

Development

Develop a JAAS-compliant LoginModule according to the JAAS SPI.


See Also:


Packaging

Package your LoginModule classes as part of your application EAR file. For Web applications, include the classes under the WEB-INF/classes.

Deployment

To deploy your LoginModule in the home instance jazn-data.xml file:

  1. Register your application login module within the <application> element of the jazn-data.xml file.

    The following entry registers the login module oracle.security.jazn.samples.SampleLoginModule to be used for authenticating users accessing the sampleLM application.

    <application>
       <name>sampleLM</name>
       <login-modules>
          <login-module>
             <class>oracle.security.jazn.samples.SampleLoginModule</class>
             <control-flag>required</control-flag>
             <options>
                <option>
                   <name>debug</name>
                   <value>true</value>
                </option>
             </options>
          </login-module>
       </login-modules>
    </application>
    
    
  2. Optional: Grant relevant permissions to your users and roles.

    For example, if the principal admin needs EJB access, then you must grant the permission oracle.j2ee.rmi.RMIPermission to admin.

    <grant>
      <grantee>
        <principals>
          <principal>
            <class>oracle.security.jazn.samples.SampleUser</class>
            <name>admin</name>
          </principal>
        </principals>
      </grantee>
      <permissions>
        <permission>
          <class>oracle.j2ee.server.rmi.RMIPermission</class>
          <name>login</name>
        </permission>
      </permissions>
    </grant>
    
    

To deploy your LoginModule in the application-specific orion-application.xml file:

  1. Set the <jazn> property role.mapping.dynamic to true:

    <jazn provider="XML" location="./jazn-data.xml" >
      <property name="role.mapping.dynamic" value="true" />
    </jazn>
    
    
  2. Create appropriate <security-role-mapping> entries:

    <security-role-mapping name="sr_developer">
      <user name="developer" />
    </security-role-mapping>
    <security-role-mapping name="sr_manager">
      <group name="managers" />
    </security-role-mapping>
    

Custom Login Module Example

This section gives source code for a simple custom LoginModule to be used by the CallerInfo example. You can find the complete source code for the revised example by searching the Oracle Technology Network:

http://www.oracle.com/technology/index.html

Example 10-3 SampleLoginModule.java

package oracle.security.jazn.samples;
 
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
import java.security.Principal;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
 
public class SampleLoginModule implements LoginModule {
 
    // initial state
    protected Subject _subject;
    protected CallbackHandler _callbackHandler;
    protected Map _sharedState;
    protected Map _options;
 
    // configuration options
    protected boolean _debug; 
 
    // the authentication status
    protected boolean _succeeded;
    protected boolean _commitSucceeded;
 
    // username and password
    protected String _name;
    protected char[] _password;
 
    protected Principal[] _authPrincipals;
 
 
    /**
     * Initialize this <code>LoginModule</code>.
     * <p/>
     * <p/>
     *
     * @param subject         the <code>Subject</code> to be authenticated. <p>
     * @param callbackHandler a <code>CallbackHandler</code> for communicating
     *                        with the end user (prompting for usernames and
     *                        passwords, for example). <p>
     * @param sharedState     shared <code>LoginModule</code> state. <p>
     * @param options         options specified in the login
     *                        <code>Configuration</code> for this particular
     *                        <code>LoginModule</code>.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map sharedState,
                           Map options) {
        this._subject = subject;
        this._callbackHandler = callbackHandler;
        this._sharedState = sharedState;
        this._options = options;
 
        // initialize any configured options
        _debug = "true".equalsIgnoreCase((String) _options.get("debug"));
 
        if (debug()) {
            printConfiguration(this);
        }
    }
 
 
    final public boolean debug() {
        return _debug;
    }
 
 
    protected Principal[] getAuthPrincipals() {
        return _authPrincipals;
    }
 
 
    /**
     * Authenticate the user by prompting for a username and password.
     * <p/>
     * <p/>
     *
     * @return true if the authentication succeeded, or false if this
     *         <code>LoginModule</code> should be ignored.
     * @throws FailedLoginException if the authentication fails. <p>
     * @throws LoginException       if this <code>LoginModule</code>
     *                              is unable to perform the authentication.
     */
    public boolean login() throws LoginException {
        if (debug())
            System.out.println("\t\t[SampleLoginModule] login");
 
        if (_callbackHandler == null)
            throw new LoginException("Error: no CallbackHandler available " +
                    "to garner authentication information from the user");
 
        // Setup default callback handlers.
        Callback[] callbacks = new Callback[] {
            new NameCallback("Username: "),
            new PasswordCallback("Password: ", false)
        };
 
        try {
            _callbackHandler.handle(callbacks);
        } catch (Exception e) {
            _succeeded = false;
            throw new LoginException(e.getMessage());
        }
 
 
        String username = ((NameCallback)callbacks[0]).getName();
        String password = 
                   new String(((PasswordCallback)callbacks[1]).getPassword());
        if (debug())
        {
            System.out.println("\t\t[SampleLoginModule] username : " + username);
        }
 
        // Authenticate the user. On successfull authentication add principals 
        // to the Subject. The name of the principal is used for authorization by
        // OC4J by mapping it to the value of the name attribute of the group 
        // element in the security-role-mapping for the application.
        if(username.equals("developer") && password.equals("welcome")) 
        {
            _succeeded = true;
            _name = "developer";
            _password = password.toCharArray();
            _authPrincipals = new SamplePrincipal[2];
            //Adding username as principal to the subject
            _authPrincipals[0] = new SamplePrincipal("developer");
            //Adding role developers to the subject
            _authPrincipals[1] = new SamplePrincipal("developers");
        }
 
        if(username.equals("manager") && password.equals("welcome")) 
        {
            _succeeded = true;
            _name = "manager";
            _password = password.toCharArray();
            _authPrincipals = new SamplePrincipal[3];
            //Adding username as principal to the subject
            _authPrincipals[0] = new SamplePrincipal("manager");
            //Adding roles developers and managers to the subject
            _authPrincipals[1] = new SamplePrincipal("developers");
            _authPrincipals[2] = new SamplePrincipal("managers");
        }
 
 
        ((PasswordCallback)callbacks[1]).clearPassword();
        callbacks[0] = null;
        callbacks[1] = null;
 
        if (debug())
        {
            System.out.println("\t\t[SampleLoginModule] success : " + _succeeded);
        }
 
        if (!_succeeded)
            throw new LoginException
                            ("Authentication failed: Password does not match");
 
        return true; 
    }
 
 
    /**
     * <p> This method is called if the LoginContext's
     * overall authentication succeeded
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * succeeded).
     * <p/>
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> method), then this method associates a
     * <code>Principal</code>
     * with the <code>Subject</code> located in the
     * <code>LoginModule</code>.  If this LoginModule's own
     * authentication attempted failed, then this method removes
     * any state that was originally saved.
     * <p/>
     * <p/>
     *
     * @return true if this LoginModule's own login and commit
     *         attempts succeeded, or false otherwise.
     * @throws LoginException if the commit fails.
     */
    public boolean commit()
            throws LoginException {
        try {
 
            if (_succeeded == false) {
                return false;
            }
 
            if (_subject.isReadOnly()) {
                throw new LoginException("Subject is ReadOnly");
            }
 
            // add authenticated principals to the Subject
            if (getAuthPrincipals() != null) {
                for (int i = 0; i < getAuthPrincipals().length; i++) {
                    if(!_subject.getPrincipals().contains(getAuthPrincipals()[i]))
{
                        _subject.getPrincipals().add(getAuthPrincipals()[i]);
                    }
                }
            }
 
            // in any case, clean out state
            cleanup();
            if (debug()) {
                printSubject(_subject);
            }
 
            _commitSucceeded = true;
            return true;
 
        } catch (Throwable t) {
            if (debug()) {
                System.out.println(t.getMessage());
                t.printStackTrace();
            }
            throw new LoginException(t.toString());
        }
    }
 
 
    /**
     * <p> This method is called if the LoginContext's
     * overall authentication failed.
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * did not succeed).
     * <p/>
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> and <code>commit</code> methods),
     * then this method cleans up any state that was originally saved.
     * <p/>
     * <p/>
     *
     * @return false if this LoginModule's own login and/or commit attempts
     *         failed, and true otherwise.
     * @throws LoginException if the abort fails.
     */
    public boolean abort() throws LoginException {
        if (debug()) {
            System.out.println
                     ("\t\t[SampleLoginModule] aborted authentication attempt.");
        }
 
        if (_succeeded == false) {
            cleanup();
            return false;
        } else if (_succeeded == true && _commitSucceeded == false) {
            // login succeeded but overall authentication failed
            _succeeded = false;
            cleanup();
        } else {
            // overall authentication succeeded and commit succeeded,
            // but someone else's commit failed
            logout();
        }
        return true;
    }
 
 
    protected void cleanup() {
        _name = null;
        if (_password != null) {
            for (int i = 0; i < _password.length; i++) {
                _password[i] = ' ';
            }
            _password = null;
        }
    }
 
 
    protected void cleanupAll() {
        cleanup();
 
        if (getAuthPrincipals() != null) {
            for (int i = 0; i < getAuthPrincipals().length; i++) {
                _subject.getPrincipals().remove(getAuthPrincipals()[i]);
            }
        }
    }
 
 
    /**
     * Logout the user.
     * <p/>
     * <p> This method removes the <code>Principal</code>
     * that was added by the <code>commit</code> method.
     * <p/>
     * <p/>
     *
     * @return true in all cases since this <code>LoginModule</code>
     *         should not be ignored.
     * @throws LoginException if the logout fails.
     */
    public boolean logout() throws LoginException {
        _succeeded = false;
        _commitSucceeded = false;
        cleanupAll();
        return true;
    }
 
    // helper methods //
 
    protected static void printConfiguration(SampleLoginModule slm) {
        if (slm == null) {
            return;
        }
        System.out.println("\t\t[SampleLoginModule] configuration options:");
        if (slm.debug()) {
            System.out.println("\t\t\tdebug = " + slm.debug());
        }
    }
 
 
    protected static void printSet(Set s) {
        try {
            Iterator principalIterator = s.iterator();
            while (principalIterator.hasNext()) {
                Principal p = (Principal) principalIterator.next();
                System.out.println("\t\t\t" + p.toString());
            }
        } catch (Throwable t) {
        }
    }
 
 
    protected static void printSubject(Subject subject) {
        try {
            if (subject == null) {
                return;
            }
            Set s = subject.getPrincipals();
            if ((s != null) && (s.size() != 0)) {
                System.out.println
                     ("\t\t[SampleLoginModule] added the following Principals:");
                printSet(s);
            }
 
            s = subject.getPublicCredentials();
            if ((s != null) && (s.size() != 0)) {
                System.out.println
              ("\t\t[SampleLoginModule] added the following Public Credentials:");
                printSet(s);
            }
        } catch (Throwable t) {
        }
    }
}

The Principal that this LoginModule uses is in Example 10-4.

Example 10-4 SamplePrincipal example

package oracle.security.jazn.samples;
 
import java.security.Principal;
 
public class SamplePrincipal implements Principal {
 
    private String _name = null;
        
 
    public SamplePrincipal(String name) {
        _name = name;
    }
 
    
    public boolean equals(Object another) {
        return ((SamplePrincipal)another).getName().equals(_name);
    }
 
 
    public String getName() {
        return _name;
    }
 
 
    public int hashCode() {
        return _name.hashCode();
    }
 
 
    public String toString() {
        return "[SamplePrincipal] : " + _name;
    }
 
}