17 Developing a Custom User Provisioning Plug-in

Oracle Access Management Identity Federation (Identity Federation) leverages the Access Manager plug-in framework to facilitate the provisioning of users. A standard user provisioning plug-in is provided or you can develop a custom plug-in, which is discussed here. This chapter provides the following sections:

See Also:

For more information about using the default user provisioning plug-in, see Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

17.1 Introduction to User Provisioning Plug-ins

When Identity Federation is acting in Service Provider (SP) mode, the user assertion is mapped to a local store to complete the federated single sign-on. However, in some cases when a Service Provider is performing user assertion, a user may not be found. The default user provisioning plug-in (LDAPProvisioningPlugin) will provision the user in the LDAP store configured as the Access Manager identity store.

All the information collected at runtime is passed to any user provisioning plug-in, standard or custom. The custom user provisioning plug-in must decide, based on this information, what user information it needs to retrieve and use. Additionally, each custom plug-in can include its own configuration designed to perform extra processing of the user to be provisioned.

When Identity Federation is acting in SP mode and fails to map assertion to a user, it will look for a configuration property to check if the missing user should be provisioned. If the user provisioning flag is set to true, Identity Federation will look up the plug-in name that needs invoking. The stand plug-in (LDAPProvisioningPlugin) is invoked by default if a custom plug-in is not being used. The GenricPluginFactory is used to locate the plug-in defined and executes the provisioning logic.

Identity Federation retrieves the property associated with the partner nameideattrname to populate the nameid value in the attribute list sent to the plug-in. If Identity Federation is configured to use the standard plug-in, the options for data store selection is as follows:

  • If Identity Federation is using the partner specific data store (multi-store), then Identity Federation will pass the identify store name to the plug-in.

  • If Identity Federation uses the default user identity store, the standard plug-in will use the User Provisioning APIs to provision user data in the data store.

  • If no partner specific store is configured, the default identity store is used.

The User Provisioning API used to provision a user is the same regardless whether a default identity store or a partner specific store is used.

17.2 Introduction to Plug-in Interfaces

The main class a custom user provisioning plug-in extends is OIFUserProvisioningPlugin. The following interfaces are exposed to custom plug-ins:

  • oracle.security.fed.plugins.fed.provisioning.OIFUserProvisioningPlugin.java (extends oracle.security.am.plugin.AbstractAMPlugin)

  • oracle.security.fed.plugins.fed.provisioning.UserContext.java

  • oracle.security.fed.plugins.fed.provisioning.UserProvisioningException.java

  • oracle.security.fed.plugins.fed.provisioning.UserProvisioningConstants.java

For more information about these interfaces, see Oracle Fusion Middleware User Provisioning Plug-in Java API Reference for Oracle Access Management Identity Federation.

17.3 Sample Code: Custom User Provisioning Plug-in

The custom user provisioning plug-in jar file structure must conform to an Access Manager custom authentication plug-in structure. Namely, it requires the following files: plugin.class, plugin.xml, and MANIFEST.MF. For more information about this structure, see Section 3.4, "Sample Code: Custom Database User Authentication Plug-in".

This section provides the following user provisioning plug-in code samples:

Example 17-1 Sample UserProvisioning.java

package oif.test;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import oracle.security.am.plugin.ExecutionStatus;
import oracle.security.am.plugin.MonitoringData;
import oracle.security.am.plugin.PluginConfig;
import oracle.security.fed.plugins.fed.provisioning.OIFUserProvisioningPlugin;
import oracle.security.fed.plugins.fed.provisioning.UserContext;
import oracle.security.fed.plugins.fed.provisioning.UserProvisioningConstants;
import oracle.security.fed.plugins.fed.provisioning.UserProvisioningException;
 * Sample OIF User proisioning plugin
public class ProvisioningPlugin extends OIFUserProvisioningPlugin {
    private boolean monitoringStatus = false;
    private Map paramMap ;
private String userRecordAttrList = null;
private String useridAssertionAttr = null;
    /* (non-Javadoc)
    public ExecutionStatus process(UserContext context) throws UserProvisioningException {
        * Execute method for plugin
        boolean provisioningStatus = false;
        Map<String, Object> attrs = context.getAttributes();
        Map<String, Object> attrsMapping = context.getAttributesUsedInMapping();
if (useridAssertionAttr == null) {
System.out.println("User id attribute to create user is not found in the attributes list");
return ExecutionStatus.ABORT;
String userid = null;
if (attrs.containsKey(useridAssertionAttr)) {
Object valueObj = attrs.get(useridAssertionAttr);
if (valueObj instanceof String)
userid = (String) valueObj;
else {
userid = (String)((Set) valueObj).iterator().next();
        DirContext ctx = getContext();
        // creating the user record
        Attributes record = new BasicAttributes();
        // Create the objectclass to add
        Attribute objClasses = new BasicAttribute("objectClass");
        String objectClass = "inetOrgPerson";
            String userIDAttr = "uid";
        // Set the attributes
        record.put(new BasicAttribute(userIDAttr, userid));
StringTokenizer st = new StringTokenizer(userRecordAttrList, ",");
while (st.hasMoreTokens()) {
String key = (String) st.nextToken();
       record.put(new BasicAttribute(key, attrs.get(key)));
                Set keys = attrsMapping.keySet();
Iterator itr = keys.iterator();
while (itr.hasNext()) {
String key = (String) itr.next();
if (!attrs.containsKey(key)) {
       record.put(new BasicAttribute(key, attrsMapping.get(key)));

    String ldapUserBaseDN = "dc=iplanet,dc=com";
        // Create the record
        ctx.createSubcontext("cn=" + userid + "," + ldapUserBaseDN, record);
        provisioningStatus = true;
         catch(Exception e){
              * If exception abort the authentication.
             return ExecutionStatus.ABORT;
        if( provisioningStatus){
             * Success
            return ExecutionStatus.SUCCESS;
             * Failure.
            return ExecutionStatus.FAILURE;
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#initialize(java.util.Map)
    public ExecutionStatus initialize(PluginConfig config) {
        //success for the execution status
userRecordAttrList = (String)config.getParameter(UserProvisioningConstants.KEY_USER_RECORD_ATTRIBUTE_LIST);
useridAssertionAttr = (String)config.getParameter(UserProvisioningConstants.KEY_USERID_ATTRIBUTE_NAME);
        return ExecutionStatus.SUCCESS;
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#getDescription()
    public String getDescription() {
        return "Ldap Provisioning Plugin";
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#getMonitoringData()
    public Map < String, MonitoringData > getMonitoringData() {
        // TODO Auto-generated method stub
        return null;
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#getMonitoringStatus()
    public boolean getMonitoringStatus() {
        return monitoringStatus;
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#getName()
    public String getPluginName() {
        return "LDAP_Provisioning_plugin";
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#getVersion()
    public int getRevision() {
        return 10;
    /* (non-Javadoc)
     * @see oracle.security.am.plugin.GenericPluginService#setMonitoringStatus(boolean)
    public void setMonitoringStatus(boolean status) {
        monitoringStatus = status;
    private DirContext getContext() {
    try {
    DirContext context = null;
      String ldapURL = "ldap://myldap.example.com:389";
        String ldapUserBaseDN = "dc=iplanet,dc=com";
    Hashtable<String, String> env = new Hashtable <String, String> ();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, ldapURL);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.REFERRAL, "follow");
    String credential = "password";
    String secPrincipal = "cn=Directory Manager";
    env.put(Context.SECURITY_PRINCIPAL, secPrincipal);
    env.put(Context.SECURITY_CREDENTIALS, credential);
    context = new InitialDirContext (env);
    return context;
    } catch (NamingException ne) {
    throw new UserProvisioningException(ne);
    } catch (Throwable e) {
    throw new UserProvisioningException(e);

Example 17-2 Sample UserPlugin.xml

<Plugin type="User Provisioning">
<description>User provisioning</description>
  <Attribute type="string" length="100">KEY_USERID_ATTRIBUTE_NAME</Attribute>
  <Attribute type="string" length="200">KEY_USER_RECORD_ATTRIBUTE_LIST</Attribute>

Example 17-3 Sample MANIFEST.MF

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: ProvisioningPlugin
Bundle-SymbolicName: ProvisioningPlugin
Bundle-Version: 10
Bundle-Activator: oif.test.ProvisioningPlugin
Import-Package: org.osgi.framework;version="1.3.0",oracle.security.fed.plugins.fed.provisioning
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

17.4 Developing a User Provisioning Plug-in

This section provides steps to write a custom Identity Federation user provisioning plug-in. The following describes the actions a developer must take after the system architect identifies the business requirements for the custom plug-in and considers the user provisioning flow when a user is not mapped to a local user store.

This section contains the following topics:

17.4.1 Process Overview: Developing a Custom Plug-in

As Identity Federation leverages the Access Manager plug-in framework, the process is similar for both. For more information, see Section 3.1.2, "About Planning, the Authentication Model, and Plug-ins".

  1. Extend OIFUserProvisioningPlugin class and implement the following methods. For more information, see Section 3.5.1, "About Writing a Custom Authentication Plug-in".

    • Implement initialize method

    • Implement process method

  2. Develop plug-in code using appropriate Access Manager 11g interfaces and packages. For more information, see:

  3. Prepare metadata for the custom plug-in. For more information, see Section 3.4.2, "Sample Plug-in Configuration Metadata Requirements".

  4. Prepare the plug-in jar file and manifest and deliver to your deployment team. For more information, see:

  5. Proceed to Section 17.4.2, "Files Required for Compiling a Plug-in".

For information about deploying and managing custom authentication plug-ins, see Oracle Fusion Middleware Administrator's Guide for Oracle Access Management.

17.4.2 Files Required for Compiling a Plug-in

The following jar files are needed for compiling the custom user provisioning plug-in:

  • felix.jar

  • oam-plugin.jar

  • fed.jar

The file are located in DOMAIN_HOME/servers/managed_instance_name/tmp/_WL_user/oam_server_11.