Saturday, December 10, 2016

OIM 11g PS3 : Creating Access Policies using OIM Client APIs

This post is about creating Access Policies in OIM programmatically using Java APIs provided by OIM. Access policies are used in OIM for automatic provisioning of target systems to users.

To start, there is a very good Oracle Blog on OIM Java APIs. Download the code through the link provided in the blog, this will help in setting up the initial code structure and creating connection with OIM. Provide the OIM connection details as per your environment in Client.java and see if you are able to connect.

Copy Authwl.conf

Client.java
 package oim.client;  
 import java.util.Hashtable;  
 import oracle.iam.platform.OIMClient;  
 //===================================================================  
 public abstract class Client  
 //===================================================================  
 {  

   private static final String OIM_URL = "t3://:14000"; // OIM 11g deployment  
   private static final String AUTH_CONF = ""; // "/app/oracle/product/ofm/Oracle_IAM1/server/config/authwl.conf"  
   private static final String APPSERVER_TYPE = "wls";  
   private static final String WEBLOGIC_NAME = "<OIM Managed Server Name>";  
   protected static final String OIM_USERNAME = "<OIM Admin Username>";  
   protected static final String OIM_PASSWORD = "<Password>";   
   protected static final String NULL = "(null)";  
   protected static final String NL = "\n";  
   protected static final String SP = "\t";  
   protected OIMClient _oimClientAuthen = null;  
   protected OIMClient _oimClientAnon = null;  
   //----------------------------------------------------------------  
   public Client() throws Exception  
   //----------------------------------------------------------------  
   {  
    Hashtable<String, String> env = new Hashtable<String, String>();  
    System.setProperty("java.security.auth.login.config", AUTH_CONF);  
    System.setProperty("APPSERVER_TYPE", APPSERVER_TYPE);  
    System.setProperty("weblogic.Name", WEBLOGIC_NAME);  
    env.put(OIMClient.JAVA_NAMING_FACTORY_INITIAL, "weblogic.jndi.WLInitialContextFactory");  
    env.put(OIMClient.JAVA_NAMING_PROVIDER_URL, OIM_URL);  
    _oimClientAuthen = new OIMClient(env);  
    _oimClientAuthen.login(OIM_USERNAME, OIM_PASSWORD.toCharArray());  
    _oimClientAnon = new OIMClient(env);  
    return;  
   }  
   //----------------------------------------------------------------  
   protected abstract void execute() throws Exception;  
   //----------------------------------------------------------------  

There are two types of OIM Java apis - Old Thor APIs & New Oracle APIs. I am not able to find any method under new Oracle APIs to create Access policy, so I used the old Thor API to do that. I used the new Oracle APIs to populate Access policy data, parent and child process forms, and assigning Access policies to role.

 package oim.client.policy;  
 import oim.client.Client;  
 //General Java Imports  
 import java.util.ArrayList;  
 import java.util.HashMap;  
 import java.util.List;  
 import java.util.Map;  
 //Thor APIs  
 import com.thortech.xl.vo.AccessPolicyResourceData;  
 import Thor.API.tcResultSet;  
 import Thor.API.Operations.tcAccessPolicyOperationsIntf;  
 import Thor.API.Operations.tcAccessPolicyOperationsIntf.PolicyNLAObjectActionType;  
 //OIM 11g R2 APIs  
 import java.util.Collections;  
 import oracle.iam.accesspolicy.api.AccessPolicyService;  
 import oracle.iam.provisioning.api.ApplicationInstanceService;  
 import oracle.iam.identity.rolemgmt.api.RoleManager;  
 import oracle.iam.identity.rolemgmt.vo.Role;  
 import oim.client.role.ClientRole;  
 import oracle.iam.identity.rolemgmt.api.RoleManagerConstants;  
 import oracle.iam.platform.entitymgr.vo.SearchCriteria;  
 import oracle.iam.platform.entitymgr.vo.SearchRule;  
 import oracle.iam.provisioning.exception.ApplicationInstanceNotFoundException;  
 import oracle.iam.provisioning.exception.GenericAppInstanceServiceException;  
 import oracle.iam.provisioning.vo.ApplicationInstance;  
 import oracle.iam.provisioning.vo.FormField;  
 import oracle.iam.provisioning.vo.FormInfo;  
 public abstract class ClientPolicy extends Client {  
   protected AccessPolicyService _service = null;  
   protected ApplicationInstanceService _appInstanceService = null;  
   protected tcAccessPolicyOperationsIntf _moAccesspolicyutility = null;  
   public RoleManager rmgr;  
   //----------------------------------------------------------------  
   public ClientPolicy() throws Exception  
   //----------------------------------------------------------------  
   {  
     super();  
     //Get all the services instances  
     _service = _oimClientAuthen.getService(AccessPolicyService.class);  
     _moAccesspolicyutility =  
         _oimClientAuthen.getService(tcAccessPolicyOperationsIntf.class);  
     rmgr = _oimClientAuthen.getService(RoleManager.class);  
     _appInstanceService =  
         _oimClientAuthen.getService(ApplicationInstanceService.class);  
     return;  
   }  
   /**  
    * Create Access Policy and return key  
    * @param policyName  
    * @param accessPolicy  
    * @param appInstanceName - Currently code works only for OUD App Instance  
    * @param groupList  
    * @return  
    */  
   public long createAccessPolicy(String policyName, String accessPolicy,  
                   String appInstanceName, List<String> groupList) {  
     long policyKey = 0;  
     try {  
       HashMap<String, String> attr = new HashMap<String, String>();  
       ApplicationInstance appInstance =  
         findApplicationInstanceByName(appInstanceName);  
       //Resource Objects and IT Resource Key and names  
       Long objKey = appInstance.getObjectKey();  
       String objName = appInstance.getObjectName();  
       String itResourceKey =  
         Long.toString(appInstance.getItResourceKey());  
       //Get Parent Form and Child Form  
       FormInfo parentForm = appInstance.getAccountForm();  
       long parentFormKey = parentForm.getFormKey();  
       String parentFormName = parentForm.getName();  
       FormInfo childFormGrp = appInstance.getChildForms().get(0);  
       long childFormGrpKey = childFormGrp.getFormKey();  
       String childFormGrpName = childFormGrp.getName();  
       //Access Policy attributes  
       //Check https://docs.oracle.com/cd/E52734_01/oim/OMJAV/Thor/API/Operations/tcAccessPolicyOperationsIntf.html  
       attr.put("Access Policies.Name", policyName); // Policy Name  
       attr.put("Access Policies.Description", accessPolicy);  
       attr.put("Access Policies.Retrofit Flag", "1"); // Retrofit Flag  
       //Resource Object Key to be provisioned  
       long[] provObjKeys = { objKey };   
       PolicyNLAObjectActionType[] actionIfPolNotApply = { PolicyNLAObjectActionType.REVOKE }; //Revoke If No Longer Applies Flag  
       long[] denyObjKeys = { }; //Object key of Resource to be denied  
       //Populate Parent Form Data  
       HashMap<String, String> parentFormData =  
         new HashMap<String, String>();  
       //Check the process form for the resource object to get the column names  
       //These field names are only applicable for OUD Application Instance  
       parentFormData.put("UD_LDAP_USR_SERVER", itResourceKey);  
       parentFormData.put("UD_LDAP_USR_ORGANIZATION",  
                 itResourceKey + "~" +  
                 "ou=People,dc=idmworks,dc=com");  
       //Set Parent Form Data  
       int groupLength =  
         groupList.size(); // Get the count of the no of groups or entititlements to be provisioned  
       AccessPolicyResourceData policyData[] =  
         new AccessPolicyResourceData[groupLength];  
       String groupPrefix = itResourceKey + "~";  
       //Populate Child Form Data  
       for (int i = 0, j = 0; i < groupLength; i++, j++) {  
         String groupName = groupPrefix + groupList.get(i).trim();  
         System.out.println(groupName);  
         policyData[j] =  
             new AccessPolicyResourceData(objKey, objName, parentFormKey,  
                            parentFormName, "P");  
         policyData[j].setFormData(parentFormData);  
         //Create a map to put child form fields values  
         HashMap childTableMap = new HashMap();  
         //For OUD App Instance - Child   
         childTableMap.put("UD_LDAP_GRP_GROUP_NAME", groupName);  
         policyData[j].addChildTableRecord(Long.toString(childFormGrpKey),  
                          "fChildName", "Add",  
                          childTableMap);  
       }  
       policyKey =  
           _moAccesspolicyutility.createAccessPolicy(attr, provObjKeys,  
                                actionIfPolNotApply,  
                                denyObjKeys,  
                                policyData);  
     } catch (Exception e) {  
       e.printStackTrace();  
     }  
     return policyKey;  
   }  

   /**  
    * Assign access policy to role  
    * @param roleName  
    * @param policyName  
    * @throws Exception  
    */  
   public void assignAccessPolicyToRole(String roleName,  
                      String policyName) throws Exception {  
     SearchCriteria criteria = null;  
     List<Role> roles = Collections.EMPTY_LIST;      
     // Search for roles by role name  
     criteria = new SearchCriteria(RoleManagerConstants.ROLE_NAME, roleName, SearchCriteria.Operator.EQUAL);  
     roles = rmgr.search(criteria, null, null);  
     if (roles.isEmpty()) {  
       System.out.println("Role not found");  
       return;  
     } else {  
       HashMap<String, Object> mapAttrs = new HashMap<String, Object>();  
       //Add the list of access polices to add  
       //Key: "Add" and Value - Access Policy Keys List  
       Map<String, List<String>> accessPoliciesMap =  
         new HashMap<String, List<String>>();  
       List<String> accessPoliciesAddList = new ArrayList<String>();  
       accessPoliciesAddList.add(Long.toString(getAccessPolicyKey(policyName)));  
       accessPoliciesMap.put("ADD", accessPoliciesAddList);  
       mapAttrs.put(RoleManagerConstants.ACCESS_POLICIES,  
              accessPoliciesMap);  
       Role role = new Role(mapAttrs);  
       rmgr.modify(RoleManagerConstants.ROLE_NAME, roleName, role);  
     }  
   }  
   /**  
    * Get Access policy key  
    * @param policyName  
    * @return  
    * @throws Exception  
    */  
   private long getAccessPolicyKey(String policyName) throws Exception {  
     HashMap attributeList = new HashMap();  
     attributeList.put("Access Policies.Name", policyName);  
     long policyKey = 0;  
     tcResultSet result =  
       _moAccesspolicyutility.findAccessPolicies(attributeList);  
     if (!result.isEmpty()) {  
       result.goToRow(0);  
       policyKey = result.getLongValue("Access Policies.Key");  
     }  
     return policyKey;  
   }  
   /**  
    * Find Application Instance By Name  
    * @param applicationInstanceName  
    * @return  
    * @throws ApplicationInstanceNotFoundException  
    * @throws GenericAppInstanceServiceException  
    */  
   private ApplicationInstance findApplicationInstanceByName(String applicationInstanceName) throws ApplicationInstanceNotFoundException,  
       GenericAppInstanceServiceException {  
     ApplicationInstance appInstance =  
       _appInstanceService.findApplicationInstanceByName(applicationInstanceName);  
     return appInstance;  
   }   
 }  






Thursday, December 8, 2016

Angular 2 : Router Guards

The guards are used to protect routes and to check if the navigation is permitted. Sometimes, these are called during the construction of router state or after that. It is used for security and authorization purposes. There are four types of guards -

  • canLoad/ canActivate - Checks if the router can be activated
  • canActivateChild - Similar to canActivate, except that it is called when a child of the route is activated, and not the route itself.
  • canDeactivate - This is different from all others and used for confirmation not permissions. Let's say you want to show confirmation message to user if user try to close the form with unsaved changes.
I am going to discuss in detail about canActivate. canActivate guard decides if route can be activated and it gets executed when navigating to that specific route. canLoad is called during the construction of the Router State and canActivate is called after that. That's the reason canActivate constructor takes router state also as an input but canLoad only takes Route as an input. You can define multiple guards for a route and those are called in the order they are defined in the RouterConfig file.

Here is the simple use case on how to use routing guards. Suppose, you have an application where both admin and normal user can login. There is some content which only admins can see and some which is specific to normal users. But both admin and user need to authenticate first to view any content.  I created one guard to check if the user is authenticated and then created two separate guards for user and admins extending the authentication guard.


Define the routes in the Application Routing file and use the canActivate property to specify the Guard class name.

 export const APP_ROUTES: Routes = [  
   { path: 'admin', component: AdminNavComponent, children: [...ADMIN_ROUTES] ,  
     canActivate: [CanActivateViaAdminGuard]},  
   { path: 'usr', component: UserNavComponent, children: [...USER_ROUTES] ,   
     canActivate: [CanActivateViaUserGuard]},  
 ];  
 export const ROUTING = RouterModule.forRoot(APP_ROUTES);  

Where CanActivateViaAdminGuard and CanActivateViaUserGuard are defined like this -

CanActivateViaAdminGuard

 @Injectable()  
 export class CanActivateViaAdminGuard extends CanActivateViaAuthGuard {  
  constructor(public authService : AuthService, public router: Router) {  
    super(authService, router);  
  }  
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> 
| boolean{  
    //Call CanActivateViaAuthGuard to check if authenticated  
    if(!super.canActivate(route,state)){  
      return false;  
    }  
    else{  
      //Check the user type through authService  
      if(!(this.authService.loggedInUser.type == "admin")){  
       this.router.navigate(['403-not-authorized']);  
       return false;  
      }  
      else{  
        return true;  
      }  
    }  
  }  
 }  

CanActivateViaUserGuard
 @Injectable()  
 export class CanActivateViaUserGuard extends CanActivateViaAuthGuard {  
  constructor(public authService : AuthService, public router: Router) {  
    super(authService, router);  
  }  
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> 
| boolean{  
    if(!super.canActivate(route,state)){  
      return false;  
    }  
    else{  
      if(!(this.authService.loggedInUser.type == "default")){  
       this.router.navigate(['403-not-authorized']);  
       return false;  
      }  
      else{  
        return true;  
      }  
    }  
  }  
 }  

CanActivateViaAuthGuard

 @Injectable()  
 export class CanActivateViaAuthGuard implements CanActivate {  
  constructor(public authService : AuthService, public router: Router) {}  
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean{  
   //Check if user logged in and current url is not login page  
   if (state.url !== '/auth/signin' && !this.authService.isLoggedIn()) {  
       this.router.navigate(['/auth/signin']);  
       return false;  
   }  
   return true;  
  }  
 }  

This is not the only way to implement it. You can also define multiple guards for a route like this -

{ path: 'admin', component: AdminNavComponent, children: [...ADMIN_ROUTES] ,  
     canActivate: [CanActivateViaAuthGuard, CanActivateViaAdminGuard]} 
}

Specify, providers for the guards in the app module file -
 @NgModule({  
 //...  
 providers: [CanActivateViaAdminGuard, CanActivateViaAuthGuard, CanActivateViaUserGuard ]  
 //...  
 })

export class AppModule {

}  

Finally, in the boot.ts file
 platformBrowserDynamic().bootstrapModule(AppModule);  


Tuesday, November 8, 2016

OIM Certification : Key Features

This post just cover the key features for OIM Certification module for quick review.

Certification Features

  1. Reviewing user entitlements within enterprise to ensure users have not acquired entitlements that they are not authorized to have.
  2. Four Types – 
    • User
    •  Entitlement 
    • Application Instance
    • Roles
  3. User Centric (Manager attestation)/Role Centric (Role owner, App Instance/System Owners)
  4. Two Phased Review. First by Org Certifier/Manager/ Any User and then respective roles/entitlement owner
  5. Configurable risk definition and scheduled task based periodic risk aggregation (Risk Aggregation Job)
  6. Certifications can be scheduled, monitored, delegated, audited.
  7. Incremental certification also possible
  8. Two Global Admin Roles
    • Certification Administrator
    • Certification Viewer
  9. Supports both online and offline user certifications. Excel DI based support for offline user certification.
  10. Closed-loop remediation can be initiated. It can be challenged, tracked till closure.
  11. Generate user certifications or application instance certifications based on event.
  12. Generate certification reports.

 Certification Configuration

  1. Set system properties –
    • Identity Auditor Feature Set Availability – True
    • Display Certification or Attestation – Certification
  2. Mark catalog item certifiable and set Certifier user for each catalog items (Application Instance, Roles, Entitlements)
  3. Setting User Attributes for Certification Snapshot
  4. Setting Risk Level for individual entities
  5. Allow Multi Phase Review option  - Only for User Certification
  6. Allow Reassignment - A new certification object is created containing the reassigned line items. The new assignee is the primary reviewer for the new certification object.
  7. Allow Delegation - When delegation is enabled, there is a verification stage, in which the certification is routed to the primary reviewer with all the decisions of the delegates as well as the primary reviewer's own decisions for final sign off.
  8. Prevent Self Certification - Prevent reviewers from being able to certify their own access. When this option is enabled, the User Manager option is selected by default.
  9. Perform Closed Loop Remediation – Automatically revoke the account or disable user based on decision.
  10. Alternate Reviewer – Only in case of Prevent Self Certification
  11. Set Risk levels in roles, entitlements and app instances. Calculate risk level for certifications.


Saturday, November 5, 2016

Oracle Mobile and Social 11g R2 PS2: Integration with Social Identities (FB, Google)

This post is regarding OAM Mobile and social capabilities to integrate with popular social identities like Facebook and Google. I tried it on OAM 11g R2 PS2 and found some roadblocks. There are couple of good blogs on OAM setup for mobile and social but still I faced issues due to some missing steps and existing defects. In this post, I am compiling all the issues that I faced and workarounds for those.
Issues Faced
1. OAuth Implementation Class Mismatch
Facebook now support OAuth 2.0 instead of 1.0 but still OAM points to the old implementation classes. Google also moved from OpenId to OAuth 2.0. You will see below error in the OAM diagnostics logs -
security.idaas.rp.RPException:&nbsp;java.lang.ClassNotFoundException:oracle.security.idaas.rp.oauth.provider.FacebookImpl
Solution: To fix this issue, delete the Google and Facebook from the Internet Identity providers section and recreate it with the correct Implementation Class and Authorization/Access token URL pointing to OAuth2. You can see the detailed steps in Oracle Support Note 1960829.1.
Snapshots of Identity Providers Config after changes -



Note: Don't create the new identity provider without deleting the existing one. There is a existing bug related to this. Refer Oracle Support Note - 1998417.1.
2. Error in redirection to protected resource
After entering end-user registration details and clicking 'Register' the user is redirected back to the social login page instead of being redirected to the requested resource. The issue in this case is the user not able to register in the local IDS repository due to some reason. The most common reason is that the 'Registration Service Details with Application User Attribute Mapping' within the application profile is misconfigured and the LDAP server is not receiving all of the mandatory attributes needed to create an entry.
For Ex: OAM Server Logs
<Error> <oracle.igf.ovd> <IGF00029> <Missing mandatory name attribute>
One way to troubleshoot this issue is to check if proper permissions are given to return required attributes. For Facebook App, go to App Review to check the approved items -


Also, FB provides a tool to generate Access Token where you can also check the returned attributes. Go to Tools and Support -> Graph API Explorer


One more thing to mention, OOB FB internet Identity Provider configuration has listed some attributes which are now not returned by FB like country, language etc. Remove those attributes from Social Identity -> Facebook -> Users Attributes Returned section, otherwise you might get error -

If using OAM 11.1.2.2.x then the Authenitcation Module - TAPModule should also have been updated to replace the TAPAssertionPlugin with TAPUserAuthenticationPlugin
3. Facebook OAuth Error - App Domain not registered
This error comes if you have not registered the App Domain in your FB App in a correct format. Go to FB App -> Settings and set the App Domain to <host name without http/https>. Also click on Add Platform and select website and enter URL http://OAM-Host:<port>.

Also, make sure to add the Facebook Login product and provide valid OAuth redirect URIs -
  • http://oamserver_host:14100/oic_rp/return
  • http://oamserver_host:14100/oic_rp/popup
  • http://oamserver_host:14100/oic_rp/init

Finally, click on App Review, check the permissions and make the app public.

4. Attributes and properties that are often missed
Make sure to add below profile properties in the Application Profile -
1. app.passwd.field - Encrypts the password on the registration page. Add password as the value. To mask the password with asterisks (*) on the registration page, add the app.passwd.field property and add password as the value.
2.oic.app.idp.oauth.token - Instructs Mobile and Social to include the OAuth Access Token as part of the final redirect to the application. Add true as the value. Only applies if the User selected an OAuth provider (Facebook, Twitter, LinkedIn).


In the Service Provider Configuration page for UserProfile, add an attribute in the attributes section called “proxyAuth” and set it to “false”. This step is required for OUD. See Oracle Docs.

Update OAM default store to IDSPROFILE-xxx identity store. This is used to check if logged in user already have an account in the local IDS repository and based on this show New User Registration page.


4. Local Authentication Failed Error
User has an option to login through local account instead of social login flow if . If you face any issue with this then some of the first things to check is -
Check if user account created in IDS repository. You can check it by connecting to LDAP or you can use the REST api endpoint configured in Mobile Services -> Service Profile -> Service Endpoint. For Ex: http://<host>:port/oic_rest/rest/ userprofile?pageSize=<N> where pageSize determine the no of results

Redirected to below error page, even if you are entering the correct password as entered on the user registration page-

Error from the OAM logs -
Wrong Password[[security.idaas.rest.provider.common.exception.RESTOAMAuthenticationException: Wrong Password
at oracle.security.idaas.rest.provider.token.OAMSDKTokenServiceProvider.checkUserSession(OAMSDKTokenServiceProvider.java:1784)

at oracle.security.idaas.rest.provider.token.OAMSDKTokenServiceProvider.authenticate(OAMSDKTokenServiceProvider.java:1670)
This error means OAMSDKTokenServiceProvider is trying to authenticate against OAM system ID store instead of IDS repository. You need to change the Auth Scheme for OIC Authentication policy defined in OOB IAM Suite Agent. Refer Oracle Support Note 1946340.1 for details.
Curious how it's related to OIC Authentication policy ??
Mobile and Social provides pre-configured Authentication Service Providers, for each token type (Access Manager and JWT). This Service Provider can issue
a Client Token which is used for authentication. A Service Profile defines a Service Endpoint URL for a Service Provider on the Mobile and Social server. For more details Oracle Doc.
Basically, under Social Identities -> Application Profile -> Authentication Service Endpoint is defined which is by default points to /oamauthentication.

Under Mobile Services -> Service Providers, you will see OAMAuthentication Service Provider and the corresponding Service Profile that points to rest service end point - http://<host>:port/oic_rest/rest/oamauthentication. Service Provider implementation class is OAMSDKTokenServiceProvider which you see in the logs.
One more thing to notice is, OAMAuthenitcation Service Provider is attached to accessgate-oic. So, in case of local authentication /OICAuthentication resource is accessed which is protected through OIC Authentication Policy. Sometimes, this issue comes if there is a mismatch in the Webgate Encrypted Password defined in SP and Access gate password in Webgate definition.


Open Issues

  1.  OAMMS AND FACEBOOK INTEGRATION WITH OAM UNSOLICITED LOGIN (Bug 20229995)
  2. Social Login doesn't work if both OAM and OIM are in the same domain which is not recommended - (Oracle Support Note-1601516.1)
  3. After supplying local login credentials the browser shows an HTTP404 error and redirected to  http://oamserver_host:14100/oic_rp/null. The 'oic_rp/null' is a symptom of bugs 21930668 and 19821179. This bug is fixed in the 11.1.2.3.x release of OAM. (Not checked the fix)
  4. OAM 11gR2 Social Login With Google IdP Always Prompts for Offline Access Consent (Doc ID 2066795.1)
I will continue the discussion on Oracle Mobile and Social and will write about OAMMS-SDK in the next post.

Tuesday, July 5, 2016

Common Errors while configuring OIM Flat File GTC Connector

Recently, I was creating OIM Flat File GTC Connector and in the process of configuring it right faced some errors. There are some good sources on basic configuration steps already on web so not going to explain it again. For detailed steps check below blogs -

  • http://rite-oim.blogspot.com/2013/07/flat-file-reconciliation-oim-11g.html
  • http://www.iamidm.com/2012/09/oim-11g-r2-lab-3-flat-file-recon-to.html


Here are some of the issues I faced during configuration -

1. Flat File used for feeding must have first line as some comment instead of actual header attributes. For Ex:
# GTC Flat File Feed
login|firstname|lastname|eMail|organization
PDIAZ|Petric|Diaz|p.diaz@oracle.com|Xellerate Users

2. While creating mapping between Reconciliation Staging table and OIM table, select matching only checkbox for User Login Attribute.











3. Map the Role attribute to the "Code" that exist in the lookup "Lookup.Users.Role". For Ex: I was providing the "Employee" as the value for "Role" but in "Lookup.Users.Role" there is no code exists for "Employee" and code value is actually "EMP".














So, either use the codes that are already available or create new ones based on the requirement. If the code doesn't exist then you will see the error -
"Notes:ERROR: Given User Employee Type in the Column: RECON_USR_EMP_TYPE is Invalid" in the Reconciliation Event Management screen (System Configuration -> Scheduler -> Event Management -> Search Reconciliation Events).

4. If you see below errors in OIM server diagnostics logs -

Thor.API.Exceptions.tcAPIException: oracle.iam.reconciliation.exception.ReconciliationException: Invalid Profile - OIM_FLATFILE_RECON_GTC

Caused by: org.xml.sax.SAXParseException; cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' 

for type 'matchingRuleType'.

It can come due to various reasons like recon profile or rules not created. Always regenerate the recon profile if you make any changes in the GTC connector config or mapping rules.

5. For below error in OIM server diagnostics logs -

MisfireHandler: Error handling misfires: Unexpected runtime exception: null OIM

See blog - http://yourhelperall.blogspot.com/2013/05/reconciliation-issue-misfirehandler.html


Monday, April 4, 2016

Challenge Parameters in OAM Authenitcation Scheme

Some of the common challenge Parameters used in OAM Authnetication Scheme are -  


  • ssoCookie - It is a good practice to mark all OAM cookie as Secure and Http-only. This can be done in individual authentication scheme. The exact OAM-11g-R1 syntax is "ssoCookie=Secure;httponly" in Challenge-Parameters field.

    • httponly - By marking the cookie as httpOnly, you are ensuring that the cookie can only be used for http protocol. It is not accessible via non-HTTP methods like JavaScript. Hackers can steal cookies via cross-site scripting if this setting is not in place.
    • secure - This configuration limit the cookie transmission thru the encrypted(https) channel only. This is an additional security on the top of httponly configuration

  • enablePersistentLogin= true - Required for persistent login feature in OAM 11g R2

  • overrideRetryLimit=1 - OverrideRetryLimit property that you define in the "Challenge Parameters" section in the authentication scheme associated with the application domain overrides DefaultRetryLimit. The Challenge Parameters had  the property:  OverrideRetryLimit =1 which led to the behaviour.

  • filterOAMAuthnCookie - For 11g WebGate, a user-defined parameter (filterOAMAuthnCookie (default true)) can be used to prevent the OAMAuthnCookie from being passed to downstream applications for security consideration. If you do want to pass the cookie on, then set the filterOAMAuthnCookie parameter to false.



Monday, February 22, 2016

Using JavaScript in ADF - Part I

I would like share my experience on using Javascript in ADF. I have seen many times developer makes some common mistake while using Javascript with ADF without properly understanding it. At the time of development, may be all look good in terms of functionality but sometimes it introduces performance and maintenance issues. ADF Faces is an Ajax-enabled rich JavaServer Faces component framework that uses JavaScript to render client-side components, implement rich component functionality, validate user input and convert user data input. ADF exposes public javascript APIs which developer can use instead of directly doing DOM manipulation. DOM manipulation is something which developer should not start with before looking all other options provided by ADF public Javascript APIs.

In ADF, The majority of the UI components are rendered in HTML, that is generated on the server side for the request.  Every ADF UI component is represented by two types of javascript classes - a public component object and an internal peer object. The public objects is used by the developers when programming on the ADF Faces client side. Peer objects help in rendering logic and hide the browser specific DOM implementation code. For every ADF UI component object, there will be the corresponding object in server. But, it's not necessary always to have a ADF javascript object on the client side, we will go in detail on this later.

JS is all about functions and objects. Even functions are objects in JS and you can assign properties to the functions as you do for objects. JS has first-class functions meaning it supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables. JS supports prototypal inheritance which is different than classical inheritance. Each ADF UI component has a corresponding JS object  and has a root object as AdfObject. Each ADF UI JS object follow the name convention and prefix by "Adf" and the corresponding server component doesn't have the prefix. For Ex: AdfRichPopup

Client Side JS Object Heirarchy


Server Side Java Class Heirarchy



Public methods that are exposed by the component JS object can be used to manipulate the component properties and do operations. For most of the action listeners and events both server side and client side operations exists but it may not be the case everytime. For Ex: To show, hide and cancel a popup both server and client side operation exist. The popupOpening is a client only event that can be canceled. If this event is canceled in a client-side listener, the popup will not be shown. The PopupFetchEvent is one of two server-side popup events but doesn't have a corresponding client event. The custom client event listeners can invoke JavaScript that raises a CustomEvent that is handled by a af:serverListener. See the Javadocs - http://docs.oracle.com/cd/E21764_01/apirefs.1111/e10684/oracle/adf/view/rich/component/rich/RichPopup.html for details.

Enough theory, let's see some examples where we can apply these concepts -  

1. Never use ADF Internal JavaScript objects 
JS doesn't have any package structures like Java classes. Based on the hierarchical object  structure it create package like structure to access the object. ADF Faces  make these things simple by applying the naming conventions and make it look like Java so it's easy to understand. In ADF Faces, two package structures are used: oracle.adf.view.js and oracle.adfinternal.view.js. The oracle.adfinternal.view.js package contains those JavaScript objects that should only be used internally by the ADF Faces component framework. I have seen many times developers using internal packages and then blaming the framework later when it doesn't work when you migrate to new releases or if some patches applied. Changes to internal packages are applied without any notice.

For Ex: AdfPanelStretchLayout




Internal JS Object


 
 2. Finding ADF Component on the Client 

I have seen many times developers using JQuery/JS to find the ADF component by id in the DOM by looking at the generated HTML For Ex: document.getElementById("itemId"). This is not the correct approach because the HTML generated may change based on the ADF UI component implementation.

As I mentioned before, the component hierarchy on the server is same as the hierarchy of ADF Faces components on the client. But, it's not necessary to have the client object for every ADF Faces component but will have the server side generated html. To make sure, client object exist there are two ways to do that -

  • By setting clientComponent=true property on UI Component declaratively using property inspector
  • If the UI component has af:clientListener attached to it then automatically it client object is generated

After making sure ADF client object exist, move on to find the component by Id using ADF Javascript objects. AdfPage.PAGE object exposes three methods to find the component -
  • findComponent
  • findComponentByAbsoluteId
  • findComponentByAbsoluteLocator
Check this blog for details on finding component by Id - https://blogs.oracle.com/groundside/entry/pattern_for_obtaining_adf_component

Reference - http://www.oracle.com/technetwork/developer-tools/jdev/1-2011-javascript-302460.pdf