Skip Headers
Oracle® Containers for J2EE Security Guide
10g (10.1.3.5.0)

Part Number E13977-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

12 User and Role API Framework

OC4J 10.1.3.x implementations provide a new pluggable identity management API framework for accessing user and role information from disparate identity management repositories. To avoid confusion with the pluggable identity management framework discussed in Chapter 13, which is independent, we will simply refer to the APIs discussed here as the "user and role APIs".

These APIs include functionality to replace the deprecated UserManager, User, and Group classes of the com.evermind.security package.

This chapter covers the following topics:

Overview of User and Role (Identity Management) API Framework

The user and role API framework allows applications to access identity information (users and roles) in a uniform and portable manner regardless of the particular underlying identity repository. The underlying repository could be an LDAP directory server such as Oracle Internet Directory, Active Directory (from Microsoft), or Sun Java System Directory Server (from Sun Microsystems), or could be a database, flat file, or some other custom repository.

This API framework provides a convenient way to access repositories programmatically in a portable way, freeing the application developer from the potentially difficult task of accounting for the intricacies of particular identity sources. The framework allows an application to work against different repositories seamlessly. An application can switch between various identity repositories without any code changes being required.

Supported operations include creating, updating, or deleting users and roles, or searching users and roles for attributes or information of interest. For example, you may want to search for the e-mail addresses of all users in a certain role. These APIs are not for authentication or authorization functions.

You can use a basic usage model (without OC4J integration) or a usage model with OC4J integration that allows your code to be portable.

User and Role API Features to Replace UserManager, User, Group

The user and role APIs include features to replace functionality of the deprecated com.evermind.security.UserManager, User, and Group classes, as follows:

User and Role API Framework and Providers

The user and role APIs are based on a framework and provider model similar to JNDI.

The framework specifies a generic mechanism for accessing identity information, and consists only of Java interfaces. It does not provide implementation details.

The "providers" (included with OC4J) each implement the framework interfaces, with specific implementation classes for accessing information from particular repositories—for example, to read identity information from Active Directory. Each type of identity repository has a corresponding provider.

The application developer creates code based on the generic framework. Later, during a configuration step, the application is plugged in to the appropriate provider for the desired identity repository. Subsequently, the application can be updated to use a different repository by simply reconfiguring it to use the corresponding provider. No changes are required to the application code.

OC4J comes with providers for Oracle Internet Directory, Active Directory, Sun Java System Directory Server (formerly iPlanet), Novell eDirectory, and OpenLDAP (an open source LDAP directory). Figure 12-1 following depicts the framework with respect to a few particular providers.

Figure 12-1 User and Role API Framework Model

Description of Figure 12-1 follows
Description of "Figure 12-1 User and Role API Framework Model"

Summary of User and Role Interfaces and Classes

This section summarizes interfaces and classes of the user and role API package, oracle.security.idm.

See Also:

  • Oracle Containers for J2EE User and Role Java API Reference (Javadoc)

User and Role Interface Descriptions

This section summarizes interfaces in the oracle.security.idm package.

There are the following interfaces for identity repositories:

  • IdentityStore: An IdentityStore instance represents a handle to an identity repository. Methods are specified for the following functions:

    • Get a user manager or role manager.

    • Search for users, roles, or their profiles.

    • Get a search filter or the list of searchable attributes for the identity repository.

  • IdentityStoreFactory: An IdentityStoreFactory instance represents the underlying identity repository, and includes a method to get an IdentityStore instance, taking as input a hashtable consisting of properties specific to the provider that are required in order to create the instance.

There are the following interfaces for user entries in the identity repository:

  • User: A User instance represents a user in the identity store. This is a subinterface of Identity, and specifies a method to get a user profile. It is also a superinterface of UserProfile.

  • UserProfile: A UserProfile instance represents detailed information about a user and includes constants for commonly accessed properties such as name, title, employee number, manager, postal address, e-mail address, phone number, fax number, wireless number, and many more. This is a subinterface of User. It specifies methods to get and set any of these common properties, as well as the more general methods getProperty(), getProperties(), setProperty(), and setProperties(). The setProperty() and setProperties() methods take instances of the oracle.security.idm.ModProperty class (described below).

  • UserManager: A UserManager instance is used to manage the user population within the repository, including the execution of operations involving users. This includes creating, authenticating, or dropping a user.

There are the following interfaces for roles in the identity repository:

  • Role: A Role instance represents a role in the identity store. This is a subinterface of Identity, and specifies a method to get a role profile. It is also a superinterface of RoleProfile.

  • RoleProfile: A RoleProfile instance represents detailed information about a role. This is a subinterface of Role, and specifies methods to add, remove, or get owners of the role; get all the grantees that are directly or indirectly granted the role; and determine whether this is an application role or an enterprise role.

  • RoleManager: A RoleManager instance is used to manage the role population within the repository, including the execution of operations involving roles. This includes creating a role, dropping a role, granting a role to a specified principal, or revoking a role from a specified principal.

User and Role Class Descriptions

This section summarizes a key class in the oracle.security.idm package.

  • IdentityStoreFactoryBuilder: Use an instance of this class to build an identity store factory. It includes the overloaded getIdentityStoreFactory() method to get an IdentityStoreFactory instance.

User and Role API Usage Models

This section supplies step-by-step instructions and samples for using the basic API framework and OC4J integration features, covering the following topics:

Step by Step: Basic Usage Model

This section describes steps to use the basic API framework. Steps 1 and 2 are primarily related to configuration, determining the provider to be used and its configuration. The code in these two steps would change for a different identity repository and provider. The operations performed on the repository in step 3 are generic in nature. Changing to a different repository would not affect this code.

See Also:

  1. Obtain an IdentityStoreFactory instance. This factory instance will represent the identity repository and is created using a getIdentityStoreFactory() call on an IdentityStoreFactoryBuilder instance. This call accepts the name of the provider to be used for connecting to the particular identity repository. It also accepts any configuration information required by the provider.

    For example, assume the application must connect to Oracle Internet Directory. The following is the provider name for Oracle Internet Directory:

    oracle.security.idm.providers.oid.OIDIdentityStoreFactory
    

    An LDAP provider, such as Oracle Internet Directory, will require configuration information including the LDAP URL, security principal, and credentials. For example:

    IdentityStoreFactoryBuilder builder =
                                new IdentityStoreFactoryBuilder();
    IdentityStoreFactory oidFactory = null;
     
    Hashtable factEnv = new Hashtable();
     
    // creating the factory instance
    // set the configuration information
    factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_PRINCIPAL, "cn=orcladmin");
    factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_CREDENTIALS, "welcome1");
    factEnv.put(OIDIdentityStoreFactory.ST_LDAP_URL,
             "ldap://ilinabc10.us.oracle.com:3060/");
    factEnv.put(OIDIdentityStoreFactory.ST_LOGGING,"false");
    factEnv.put(OIDIdentityStoreFactory.ST_LOG_LEVEL,
            java.util.logging.Level.ALL);
    oidFactory =  builder.getIdentityStoreFactory(
            "oracle.security.idm.providers.oid.OIDIdentityStoreFactory", factEnv);
    
  2. Obtain an IdentityStore instance to carry out operations on the repository. This is obtained using a getIdentityStoreInstance() call on the IdentityStoreFactory instance. This call can accept configuration information required for creation of the identity store instance. For example, for Oracle Internet Directory you must specify the subscriber or realm name upon which the operations are to be performed, as shown in the following sample:

    Hashtable storeEnv = new Hashtable();
     
    // creating the store instance
    storeEnv.put(OIDIdentityStoreFactory.ST_SUBSCRIBER_NAME, 
                                  "dc=us,dc=oracle,dc=com");
    oidStore = oidFactory.getIdentityStoreInstance(storeEnv);
    
  3. Using the IdentityStore instance, perform any operations of interest on the identity repository, such as searching, updating, creating, or deleting entries. For example, the following code will search for all users whose name begins with "john":

    // search filter for users whose name begins with "john"
    SimpleSearchFilter sf = oidStore.getSimpleSearchFilter(
            UserProfile.NAME, SimpleSearchFilter.TYPE_EQUAL, null);
     
    // Add the wildcard character
    sf.setValue("john"+sf.getWildCardChar());
     
    // generate the search parameter instance and set the search filter 
    SearchParameters params = new SearchParameters();
    params.setFilter(sf);
     
    // Searching for users
    // search on the IdentityStore instance 
     
    SearchResponse resp = oidStore.searchUsers(params);
    System.out.println("Searched users are:");
     
    // Iterate on the search results
    while (resp.hasNext()
    {
      User usr = (User) resp.next();
      System.out.println("Name: "+usr.getName());
    }
    

Step by Step: OC4J Integration Usage Model

As explained in the preceding section, "Step by Step: Basic Usage Model", the configuration-related code is tied to the identity repository and its associated provider, and thus is subject to change whenever the application changes to use a different identity repository.

To make your code portable, you can use the OC4J integration feature of the API framework. This feature uses security provider information present in the OC4J login module of the application, so that the application itself need not specify any configuration for the repository and provider. The application code becomes generic, and the application can change to a different identity source simply by changing the security provider information in the login module configuration.

Important:

The OC4J integration feature is a security-sensitive operation and requires the application to have necessary permissions. See the next section, "Permission Requirements for the OC4J Integration Feature", for java2.policy requirements.

See Also:

Use the OC4J integration feature as follows:

  1. The user and role framework requires a path to a user/role properties file (typically called userrole.properties by convention), specified as a Java system property, as follows:

    System.setProperty("oracle.userrole.properties",
                       "/home/jdoe/userrole.properties");
    

    The properties file contains settings required by the framework to access OC4J login module information. The properties file format is shown in "User and Role Properties File".

  2. Creating the IdentityStoreFactory instance is a privileged operation and must be carried out within an AccessController.doPrivileged() block, as follows:

    IdentityStoreFactory factory = null;
     
    try
    {
      factory = (IdentityStoreFactory) AccessController.doPrivileged(
                     new PrivilegedExceptionAction()
                     {
                       public Object run() throws IMException
                       {
                         IdentityStoreFactoryBuilder builder = 
                                      new IdentityStoreFactoryBuilder();
                         return builder.getIdentityStoreFactory();
                       }
                     });
      
    }catch (PrivilegedActionException e)
    {
      e.getException().printStackTrace(out);
    }
    catch (Exception e) 
    {
      e.printStackTrace(out);
    } 
    
  3. Obtaining the IdentityStore instance is convenient:

    IdentityStore store = factory.getIdentityStoreInstance();
    
  4. Perform operations on the identity store as shown in the previous section,"Step by Step: Basic Usage Model".

Permission Requirements for the OC4J Integration Feature

Because the OC4J integration feature is a security-sensitive operation, the application code must have certain permissions. In particular, the getIdentityStoreFactory() method of the IdentityStoreFactoryBuilder class makes API calls that require certain permissions.

In the OC4J java2.policy file, grant the following permissions to the application codebase:

grant codebase "file:${oracle.home}/application_code_base" 
{
    permission oracle.security.jazn.JAZNPermission "*";
};

Be aware that in order to use Java 2 policies, you must specifically enable a security manager, as discussed in "Specifying a Java 2 Security Manager and Policy File".

User and Role Properties File

To use the OC4J integration feature, the API framework must know the path to the user/role properties file, expressed as a Java system property. The properties file contains the properties required by the framework to access required OC4J login module information. The file can have any name you choose, but must have the following file format:

# This line should not be changed.
configurationsourceclass=oracle.security.idm.util.OC4JConfigurationSource
 
# This property specifies the JMX Mbean URL for the OC4J container in which the 
# application is deployed. 
# For OPMN-managed OC4J, uncomment the URL that follows; comment out all others.
# format: service:jmx:rmi:///opmn://opmnhost[:opmnport]/oc4jInstance

jmxserviceurl=service:jmx:rmi:///opmn://localhost:6008/home

# For standalone OC4J, uncomment the URL that follows; comment out all others.
# format: service:jmx:rmi:///opmn://oc4jhost:rmiport/oc4jContextRoot
#jmxserviceurl=service:jmx:rmi://localhost:23791/oc4j/

See Also:

  • Oracle Containers for J2EE Developer's Guide for information about setting the JMX Service URI for an OPMN-managed or standalone OC4J instance

Example: Basic User and Role API Framework

This section supplies the complete example corresponding to the steps discussed in "Step by Step: Basic Usage Model".

import oracle.security.idm.*;
import oracle.security.idm.providers.oid.*;
import java.util.*;
import java.io.*;
 
public class BasicSampleOID
{
  public static void main(String args[])
  {
    IdentityStoreFactoryBuilder builder = new IdentityStoreFactoryBuilder();
    IdentityStoreFactory oidFactory = null;
    IdentityStore oidStore = null;
 
    try
    {
 
      Hashtable factEnv = new Hashtable();
      Hashtable storeEnv = new Hashtable();
 
      // creating the factory instance
      factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_PRINCIPAL,
                  "cn=user,....");
      factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_CREDENTIALS, 
                   "password");
      factEnv.put(OIDIdentityStoreFactory.ST_LDAP_URL,
                  "ldap://johnmc.us.oracle.com:3060/");
      factEnv.put(OIDIdentityStoreFactory.ST_LOGGING,"false");
      factEnv.put(OIDIdentityStoreFactory.ST_LOG_LEVEL,
                  java.util.logging.Level.ALL);
 
      oidFactory =  builder.getIdentityStoreFactory(
                  "oracle.security.idm.providers.oid.OIDIdentityStoreFactory", 
                  factEnv);
      
      // creating the store instance
      storeEnv.put(OIDIdentityStoreFactory.ST_SUBSCRIBER_NAME, 
                   "dc=us,dc=oracle,dc=com");
      oidStore = oidFactory.getIdentityStoreInstance(storeEnv);
 
      // search filter (cn=a*)
      SimpleSearchFilter sf = oidStore.getSimpleSearchFilter(
                    UserProfile.NAME, SimpleSearchFilter.TYPE_EQUAL, null);
      sf.setValue("john"+sf.getWildCardChar());
      
      SearchParameters params = new SearchParameters();
      params.setFilter(sf);
 
      // Searching for users
      SearchResponse resp = oidStore.searchUsers(params);
      System.out.println("Searched users are:");
      while (resp.hasNext())
      {
        User usr = (User) resp.next();
        System.out.println("Name: "+usr.getName());
      }
 
    }catch (IMException e)
    {
      e.printStackTrace();
    }
  }
}

Example: OC4J Integration with User and Role API Framework

This section supplies the complete example corresponding to the steps discussed in "Step by Step: OC4J Integration Usage Model".

import java.io.*;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
 
// Packages for Servlets
import javax.servlet.*;
import javax.servlet.http.*;
import oracle.security.idm.*;
 
public class UserSearch extends HttpServlet 
{
    private String USERROLEPROPFILE = "UserRolePropFile";
    IdentityStore store = null;
 
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
 
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = "";
        String searchType = "usersearch";
        try 
        {
            name = request.getParameter("name");
            searchType = request.getParameter("searchtype");
        } catch (Exception e) 
        {
            e.printStackTrace();
        }
 
        String filter = (name != null)? name: "";
 
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>UserSearch</title></head>");
        out.println("<body>");
        out.println(
            "<label for=\"fld\"><b>User name begining with</b></label>");
        out.println(
          "<form action=\"usersearch\">"+
          "<P><select name=\"searchtype\" size=\"1\">"+
          "<option value=\"usersearch\">Search Users</option>"+
          "<option value=\"rolesearch\">Search Roles</option>"+
          "<option value=\"membershipsearch\">Search Membership details"+
          "<option value=\"membersearch\">Searchs Members of role"+
          "</option></select></P>"+
          "<input name=\"name\" id=\"fld\" value=\""
          + filter + 
          "\"type=\"text\"/><input type=\"SUBMIT\" value=\"Search\"/></form>");
        out.println("<br><br><br>");
 
        // Create the IdentityStore instance required for searching
        configureAPI(out);
 
        // Carries out the actual search using IdentityStore instance obtained 
        // above
        doSearch(out, searchType, name);
 
        out.println("</body></html>");
        out.close();
    }
 
    public void configureAPI(PrintWriter out) 
    {
      IdentityStoreFactoryBuilder builder = new IdentityStoreFactoryBuilder();
 
      // Set the following system property to specify the location of 
      // "userrole.properties" file. This file is used by user-role apis for 
      // reading the configuration from OC4J
       
      // Get the file location from the servlet init parameters
      System.setProperty("oracle.userrole.properties", 
                 getServletConfig().getInitParameter(USERROLEPROPFILE));
      
      IdentityStoreFactory factory = null;
 
      try
      {
        factory = (IdentityStoreFactory) AccessController.doPrivileged(
                 new PrivilegedExceptionAction()
                 {
                   public Object run() throws IMException
                   {
                     IdentityStoreFactoryBuilder builder = 
                                  new IdentityStoreFactoryBuilder();
                     return builder.getIdentityStoreFactory();
                   }
                 });
        store = factory.getIdentityStoreInstance();
      }catch (PrivilegedActionException e)
      {
        e.getException().printStackTrace(out);
      }
      catch (Exception e) 
      {
        e.printStackTrace(out);
      }
    }
 
    public void doSearch(PrintWriter out, String searchType, String name) 
    {
        System.out.println("Inside doSearch");
 
        if (name == null) return;
        if (searchType.equals("usersearch"))
          searchUsers(out, name);
        else if (searchType.equals("rolesearch"))
          searchRoles(out, name);
        else if (searchType.equals("membershipsearch")) 
          searchMembership(out, name);
        else if (searchType.equals("membersearch")) 
          searchMembers(out, name);
    }
 
    public void searchMembers(PrintWriter out, String name) 
    {
        System.out.println("Inside searchMembers");
        if (name == null) return;
        out.println("Results: <br>");
 
        try {
            Role rle = store.searchRole(IdentityStore.SEARCH_BY_NAME, name);
            out.println("Members of role \""+rle.getName()+
                        "\" are:<br>");
            SearchResponse resp = 
             rle.getRoleProfile().getGrantees(null, false);
            while (resp.hasNext()) {
                Identity idy = resp.next();
                out.println("Unique name: " + idy.getUniqueName() + "<br>");
            }
 
        } catch (IMException e) {
            e.printStackTrace(out);
        }
    }
 
    public void searchMembership(PrintWriter out, String name) 
    {
        System.out.println("Inside searchMembership");
        if (name == null) return;
        out.println("Results: <br>");
 
        try {
            User usr = store.searchUser(name);
            out.println("Membership details for user \""+usr.getName()+
                        "\" are:<br>");
            SearchResponse resp = 
             store.getRoleManager().getGrantedRoles(usr.getPrincipal(), false);
            while (resp.hasNext()) {
                Identity idy = resp.next();
                out.println("Unique name: " + idy.getUniqueName() + "<br>");
            }
 
        } catch (IMException e) {
            e.printStackTrace(out);
        }
    }
 
    public void searchRoles(PrintWriter out, String name) 
    {
        System.out.println("Inside searchRoles");
        if (name == null) return;
        out.println("Results: <br>");
 
        try {
            SimpleSearchFilter sf = store.getSimpleSearchFilter(
                    RoleProfile.NAME, SimpleSearchFilter.TYPE_EQUAL, null);
            sf.setValue(name + sf.getWildCardChar());
 
            SearchParameters params = new SearchParameters();
            params.setFilter(sf);
 
            // Searching for users
            SearchResponse resp = store.searchRoles(0, params);
            out.println("Searched roles are:<br>");
            while (resp.hasNext()) {
                Identity idy = resp.next();
                out.println("Unique name: " + idy.getUniqueName() + "<br>");
            }
 
        } catch (IMException e) {
            e.printStackTrace(out);
        }
    }
 
    public void searchUsers(PrintWriter out, String name) 
    {
        System.out.println("Inside searchUsers");
        if (name == null) return;
        out.println("Results: <br>");
 
        try {
            SimpleSearchFilter sf = store.getSimpleSearchFilter(
                    UserProfile.NAME, SimpleSearchFilter.TYPE_EQUAL, null);
            sf.setValue(name + sf.getWildCardChar());
 
            SearchParameters params = new SearchParameters();
            params.setFilter(sf);
 
            // Searching for users
            SearchResponse resp = store.searchUsers(params);
            out.println("Searched users are:<br>");
            while (resp.hasNext()) {
                Identity idy = resp.next();
                out.println("Unique name: " + idy.getUniqueName() + "<br>");
            }
 
        } catch (IMException e) {
            e.printStackTrace(out);
        }
    }
}