Search This Blog

Monday 9 September 2019

Java Code to Decrypt User Password and Fetch Security Question and Answers in OIM

OIM does not allow to Decrypt user password from User form now. So, as a workaround, we can fetch the password from Process form and Decrypt it using the below code:

package Retry_Failed;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.security.auth.login.LoginException;

import com.thortech.xl.dataaccess.tcDataBaseClient;
import com.thortech.xl.dataaccess.tcDataProvider;
import com.thortech.xl.dataaccess.tcDataSet;

import Thor.API.tcResultSet;
import Thor.API.Operations.tcFormInstanceOperationsIntf;
import Thor.API.Operations.tcUserOperationsIntf;
import Thor.API.Security.XLClientSecurityAssociation;
import oracle.iam.platform.OIMClient;
import oracle.iam.provisioning.api.ProvisioningService;
import oracle.iam.provisioning.vo.Account;

public class Decrypt

{
private static OIMClient oimClient;



public static void init() throws LoginException {
String hostName = "oim_hostname";
String port = "oim_port_no";
System.out.println("Creating client....");
String ctxFactory = "weblogic.jndi.WLInitialContextFactory";
String serverURL = "t3://" + hostName + ":" + port;
String username = "xelsysadm";
String password = "xelsysadm_Password";

System.setProperty("java.security.auth.login.config",
"Location of Local authwl.comf");
System.setProperty("APPSERVER_TYPE", "wls");
Hashtable env = new Hashtable();
env.put(OIMClient.JAVA_NAMING_FACTORY_INITIAL, ctxFactory);
env.put(OIMClient.JAVA_NAMING_PROVIDER_URL, serverURL);

oimClient = new OIMClient(env);
System.out.println("Logging in");

oimClient.login(username, password);
System.out.println("Log in successful");

}

public static void main(String args[]) throws Exception
{
init();
tcDataProvider dbProvider = null;
String userLogin = null;
Map<String, String> challengeQuestionAnswer = new HashMap<String, String>();
XLClientSecurityAssociation.setClientHandle(oimClient);//Needed for database client
        dbProvider = new tcDataBaseClient(); //Connection to OIM Schema
        tcDataSet dataSet = new tcDataSet(); //Stores the result set of an executed query
       
        tcDataSet dataSet_PCQ = new tcDataSet(); //Stores the result set of an executed query

        String query = "SELECT * FROM USR where USR_LOGIN in UPPER('USR_LOGIN of User to Decrypt password For')";

        dataSet.setQuery(dbProvider, query); //Set query and database provider
        dataSet.executeQuery(); //execute query and store results into dataSet object
        int records = dataSet.getTotalRowCount();
        String usr_key="";
        for(int i = 0; i < records; i++)
        {
            dataSet.goToRow(i); //move pointer to next record
            usr_key = dataSet.getString("USR_KEY");
//            String decryptPwd = tcCryptoUtil.decrypt(encPwd,"DBSecretKey");
            userLogin = dataSet.getString("USR_LOGIN");
            String userStatus = dataSet.getString("USR_STATUS");
            System.out.printf("User Login: %s\nStatus: %s\nKey: %s\n\n", userLogin, userStatus, usr_key);
//            System.out.printf("User Login: %s\nStatus: %s\nPassword: %s\n\n", userLogin, userStatus, decryptPwd); 
           
           
           
     
        }
       
//        }
        challengeQuestionAnswer = getChallengeQuesAns(usr_key);
        for (Entry<String, String> entry : challengeQuestionAnswer.entrySet()) {
System.out.println("Question : "+entry.getKey()+" Answer : "+entry.getValue());
}
long procInstKey = getProcessInstKeyOfRes("LDAP User", usr_key, new String[] { "Provisioned", "Enabled" }, oimClient, userLogin);
    String passkey = getLDAPPassword(oimClient, procInstKey);
    System.out.println("Entering into password:: " + passkey);
}


private static Map<String, String> getChallengeQuesAns(String usr_key) {
Map<String, String> challengeQuestionAnswers = new HashMap<String, String>();
try

{

tcUserOperationsIntf userOperationsIntf = (tcUserOperationsIntf) oimClient

.getService(tcUserOperationsIntf.class);

tcResultSet resultSet = userOperationsIntf

.getChallengeValuesForUser(Long.parseLong(usr_key));

if ((resultSet == null) || (resultSet.isEmpty())) {

System.out.println("ResultSet is Empty or null");

return challengeQuestionAnswers;

}

int rowCount = resultSet.getRowCount();

for (int j = 0; j < rowCount; j++) {

resultSet.goToRow(j);

String[] columnNames = resultSet.getColumnNames();

for (int i = 0; i < columnNames.length; i++) {

String question = resultSet.getStringValue("Users.Password Challenge Question.Question");

String answer = resultSet.getStringValue("Users.Password Challenge Question.Answer");

challengeQuestionAnswers.put(question, answer);

}

}

} catch (Exception e) {

e.printStackTrace();

}
return challengeQuestionAnswers;
}


public static long getProcessInstKeyOfRes(String res_Name, String userkey, String[] statusArray, OIMClient oimClient, String userLogin)
  throws Exception
{
  long longProcessInstanceKey = 0L;
  String methodName = "getProcessInstKeyOfRes():::";
 
  ProvisioningService ps = (ProvisioningService)oimClient.getService(ProvisioningService.class);
  try
  {
    System.out.println(methodName + "Entering into method:: " + methodName);
   
    List<Account> userAccount = ps.getAccountsProvisionedToUser(userkey);
    System.out.println(methodName + "size of list--->" + userAccount.size());
    System.out.println(userAccount);
   
   
    for (Account account : userAccount) {
//    System.out.println(account.getAppInstance()+"\n"+account.getAccountDescriptiveField());
//    account.get
//      if ((account.getAppInstance().toString().contains("Enterprise")) || (account.getAppInstance().toString().contains("ODSEE"))) {
    if (account.getAppInstance().toString().contains("ODSEE") && account.getAccountDescriptiveField().toString().contains(userLogin)){
        if ((Arrays.asList(statusArray).contains(account.getAccountStatus().toString())) && (account.getAccountType().toString().equalsIgnoreCase("Primary")))
        {
          System.out.println(methodName + " >>>>>> account.getAccountType() " + account.getAccountType());
          System.out.println(methodName + " >>>>>> account.getAccountStatus() " + account.getAccountStatus());
          System.out.println(methodName + " >>>>>> account.getProcessInstanceKey() " + account.getProcessInstanceKey());
          longProcessInstanceKey = Long.parseLong(account.getProcessInstanceKey().toString());
        }
      }
    }
    System.out.println(methodName + "longProcessInstanceKey --->" + longProcessInstanceKey);
  }
  catch (Exception e)
  {
    System.out.println(methodName + ".START().ERROR()-> " + e.getMessage());
    throw new Exception("ERROR");
  }
  return longProcessInstanceKey;
}



public static String getLDAPPassword(OIMClient oimClient, long procInstKey)
  throws Exception
{
  String ldapPassword = null;
  String methodName = "getLDAPPassword():::";
  String usrID = null;
  try
  {
    System.out.println(methodName + "Entering into method:: " + methodName);
    if (procInstKey > 0L)
    {
      tcFormInstanceOperationsIntf formInstanceOperationsIntf = (tcFormInstanceOperationsIntf)oimClient.getService(tcFormInstanceOperationsIntf.class);
      tcResultSet resultSet = formInstanceOperationsIntf.getProcessFormData(procInstKey);
      int rowCount = resultSet.getRowCount();
      System.out.println(methodName + "rowCount = " + rowCount);
      for (int j = 0; j < rowCount; j++)
      {
        resultSet.goToRow(j);
       
        ldapPassword = resultSet.getStringValue("UD_LDAP_USR_PASSWORD");
       
        usrID = resultSet.getStringValue("UD_LDAP_USR_USERID");
      }
    }
    System.out.println(methodName + "usrID = " + usrID);
    System.out.println(methodName + "Exiting method:: " + methodName);
  }
  catch (Exception e)
  {
    System.out.println(methodName + ".START().ERROR()-> " + e.getMessage());
    throw new Exception("ERROR");
  }
  return ldapPassword;
}


}

Tuesday 14 May 2019

Java Code to Connect to Active Directory and fetch details

package ActiveDirectoryConnect;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;


public class ADTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws NamingException {
     
        final String AdServer = "ldap://ad.your-server.com:389";
        final String ADSearchBase = "dc=ad,dc=my-domain,dc=com";
     
        final String ADUsername = "myADUsername";
        final String ADPassword  = "myADPassword ";
     
        final String ADAccountToLookup  = "myOtherADUsername";
     
     
        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        if(ADUsername != null) {
            env.put(Context.SECURITY_PRINCIPAL, ADUsername);
        }
        if(ADPassword  != null) {
            env.put(Context.SECURITY_CREDENTIALS, ADPassword );
        }
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, AdServer);

        //ensures that objectSID attribute values
        //will be returned as a byte[] instead of a String
        env.put("java.naming.ldap.attributes.binary", "objectSID");
     
        // the following is helpful in debugging errors
        //env.put("com.sun.jndi.ldap.trace.ber", System.err);
     
        LdapContext ctx = new InitialLdapContext(env, null);
     
        ADTest ldap = new ADTest();
     
        //1) lookup the ldap account
        SearchResult srLdapUser = ldap.findAccountByAccountName(ctx, ADSearchBase, ADAccountToLookup );
     
        //2) get the SID of the users primary group
        String primaryGroupSID = ldap.getPrimaryGroupSID(srLdapUser);
     
        //3) get the users Primary Group
        String primaryGroupName = ldap.findGroupBySID(ctx, ADSearchBase, primaryGroupSID);
    }
 
    public SearchResult findAccountByAccountName(DirContext ctx, String ADSearchBase, String accountName) throws NamingException {

        String searchFilter = "(&(objectClass=user)(sAMAccountName=" + accountName + "))";

        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        NamingEnumeration<SearchResult> results = ctx.search(ADSearchBase, searchFilter, searchControls);

        SearchResult searchResult = null;
        if(results.hasMoreElements()) {
             searchResult = (SearchResult) results.nextElement();

            //make sure there is not another item available, there should be only 1 match
            if(results.hasMoreElements()) {
                System.err.println("Matched multiple users for the accountName: " + accountName);
                return null;
            }
        }
     
        return searchResult;
    }
 
    public String findGroupBySID(DirContext ctx, String ADSearchBase, String sid) throws NamingException {
     
        String searchFilter = "(&(objectClass=group)(objectSid=" + sid + "))";

        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
     
        NamingEnumeration<SearchResult> results = ctx.search(ADSearchBase, searchFilter, searchControls);

        if(results.hasMoreElements()) {
            SearchResult searchResult = (SearchResult) results.nextElement();

            //make sure there is not another item available, there should be only 1 match
            if(results.hasMoreElements()) {
                System.err.println("Matched multiple groups for the group with SID: " + sid);
                return null;
            } else {
                return (String)searchResult.getAttributes().get("sAMAccountName").get();
            }
        }
        return null;
    }
 
    public String getPrimaryGroupSID(SearchResult srLdapUser) throws NamingException {
        byte[] objectSID = (byte[])srLdapUser.getAttributes().get("objectSid").get();
        String strPrimaryGroupID = (String)srLdapUser.getAttributes().get("primaryGroupID").get();
     
        String strObjectSid = decodeSID(objectSID);
     
        return strObjectSid.substring(0, strObjectSid.lastIndexOf('-') + 1) + strPrimaryGroupID;
    }
 

    public static String decodeSID(byte[] sid) {
     
        final StringBuilder strSid = new StringBuilder("S-");

        // get version
        final int revision = sid[0];
        strSid.append(Integer.toString(revision));
     
        //next byte is the count of sub-authorities
        final int countSubAuths = sid[1] & 0xFF;
     
        //get the authority
        long authority = 0;
        //String rid = "";
        for(int i = 2; i <= 7; i++) {
           authority |= ((long)sid[i]) << (8 * (5 - (i - 2)));
        }
        strSid.append("-");
        strSid.append(Long.toHexString(authority));
     
        //iterate all the sub-auths
        int offset = 8;
        int size = 4; //4 bytes for each sub auth
        for(int j = 0; j < countSubAuths; j++) {
            long subAuthority = 0;
            for(int k = 0; k < size; k++) {
                subAuthority |= (long)(sid[offset + k] & 0xFF) << (8 * k);
            }
         
            strSid.append("-");
            strSid.append(subAuthority);
         
            offset += size;
        }
     
        return strSid.toString(); 
    }
}

Tuesday 13 June 2017

Creating Connection using OIMClient in Local and Calling API to Perform Task

To Connect OIM from Local, we need below piece of code along with the list of jars which are as below: 

commons-logging.jar
spring.jar oimclient.jar
jrf-api.jar
wlfullclient.jar

Please navigate to /Oracle_IDM1/server/client in side zip file oimclient.zip, extract oimclient.zip. It will contain all the major jar files that we need to establish connection. Use the below code to create the connection. 

 public void OIMConnection(){ 
         //Function to Connection to OIM
        OIMClient oimClient = null; System.setProperty("java.security.auth.login.config",                    "D:/designconsole/config/authwl.conf"); 
        //Update path of authwl.conf(its can be found inside designconsole) file according to your environment System.setProperty("weblogic.Name", "wls_oim1"); 
        System.setProperty("APPSERVER_TYPE", "wls"); 
        HashTable env = new HashTable(); 
        env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");                         env.put(Context.PROVIDER_URL, "t3://localhost:14000"); //Update localhost with your OIM      machine IP 
try { 
           oimClient.login("xelsysadm", "Password".toCharArray()); //Update password of Admin with your                environment password 
           System.out.print("Successfully Connected with OIM "); 
       } 
catch (LoginException e) 

          System.out.print("Login Exception"+ e); 
 } 

// To use Platform API, use oimclient.getService(Service Name) instead of Platform.getService(Service Name)

 userManager = oimClient.getService(UserManager.class); } Now call the above method and use it to fetch detail from OIM running it locally.

Wednesday 17 February 2016

Custom Prepopulate Adapter to pre-populate fields on Process Form in OIM 11gR2 PS3

Prepopulate adapters are used to populate the fields on a resource or Process form in Oracle Identity Manager. By having the resource form fields populated by prepopulate adapters, the provisioning process of a resource account to a user can be handled with ease rather than having someone manually enter values for the resource form fields. In Oracle Identity Manager, prepopulate adapters are triggered on the initial assignment of the resource account to a user.


Custom Java Code for PrePopulate Adapters

In the below code we consider and example where we want to Concatenate below 4 fields from User Profile:

1. Postal Address
2. Postal Code
3. Street
4. State

to populate the field Street in Process Form.

package com.prepopulate.custom;

import java.util.logging.Logger;

public class fieldPrePopulate{

        private static final Logger logger = Logger.getLogger("com.prepopulate.custom");
String Space = " ";
        
        public static String StreetAddressGenerator(String PostalAddress, String Street, String PostalCode, String State){
            String StreetAddress = PostalAddress.concat(Space.concat(PostalCode.concat(Space.concat(Street.concat(State)))));
            logger.info("Concatenatedd Street Address: "+StreetAddress);
            return StreetAddress;
        }
}

Similarly you can write your own code to populate certain field on Process Form as per your requirement.

After writing Java methods for your prepopulate adapters, you have to create a JAR file of your Java code, and upload it to OIM as a JavaTasks JAR type (Place the JAR file in $MW_HOME/Oracle_IDM1/server/JavaTasks directory or upload to OIM database using UploadJars.sh script located in $MW_HOME/Oracle_IDM1/server/bin directory. The latter approach is recommended in a production environment).


Creating Adapter


1. Log in to design console. Design console can be started by executing $MW_HOME/Oracle_IDM1/designconsole/xlclient.sh script.


2. On the left panel, expand Development Tools, and select Adapter Factory.



3. Specify Adapter Name, Adapter Type, Description. Then save.



4. On the Variable List sub-tab, add the variables for your adapter as shown in the below screenshots. Typically, these variables are the input to your Java method.


                              Click Add



5. On the Adapter Tasks sub-tab, create a task that calls your Java method.


Click Add




Click Continue

Provide the details like Task Name, API Source and Methods as per screenshot

Map the Input Parameters to the variables created in Variables tab above

Map Output Parameter to Return Variable as shown in Screenshot and then click Save and close the pop-up

Java Task attached to adapter

6. Click Build to compile the adapter. Then save.

Attaching PrePopulate Adapter to Form Field

1. On the left panel of design console, expand Development Tools, and select Form Designer.



2. Select your process form that you will attach the prepopulate adapter to, and create a new version.



Ensure "Latest Version" and "Current Version" are using the version you created.

3. On the Pre-Populate sub-tab, attach your prepopulate adapter to a form field.
Click on Add to Add the PrePopulate Adapter by selecting the Adapter from the list 


 Map the fields in Adapter to User Definition Fields as shown in screenshot


4. Make version active.

Validate PrePopulate Adapter


Assign resource account to a user. After submitting the resource process form instance, the prepopulate adapters should kick in and populate the form fields.