Thursday, March 21, 2013

Resolving OIF Error "FED-15132: Unknown refID" when JSP based form login is used for OAM authentication

The Issues :- 
My OIF server is integrated with OAM for authentication. I used a JSP based form login to collect credential when User makes an IntitateSSO call. I started seeing this error in OIF logs. This is very much reproducible in clustered OAM and OIF servers.

FED-15132: Unknown refID
Cause: User previously accessed the Oracle Identity Federation server with a different host name than the one in the current request and cookies were not transmitted.
Action: Use the same hostname and fully qualified domain URL to access the Oracle Identity Federation 

FED-15128: An internal error occurred while processing the credentials Cause: The authentication engine did not return the required refID parameter.
Action: Check that the authentication flow correctly sent the refID parameter to the Oracle Identity Federation server 


Whats Going on under the hood :- 
The OIF servers is a J2EE application runs on weblogic server which creates a JSessionId. My custom jsp based form login is also another J2EE application deployed on OAM server. When this login page is invoked, it also create a JSession Id. To add a pinch of salt to this issue, I am using same load balancer address (e.g. sso.abc.com) to access multiple Weblogic applications. They all try to use the same JSessionId cookie, which is issued to domain=sso.abc.com path=/.  Now my custom form login session is clashing with OIF's session that is created inside OIF after successful authentication.

Solution :-
You may have already guessed it. Open the weblogic.xml file of you custom Login Form war file and add the followings .

<session-descriptor>
<cookie-name> MyJSessionId </cookie-name>
</session-descriptor>


Basically, you are instructing Weblogic server to create a custom JSessionId (MyJessionId) for your Form login to avoid clashing with OIF's session.

Thursday, February 7, 2013

FIXING BLUE SCREEN ERROR WHEN COMING FROM BOOK-MARKED LOGIN PAGE


This issue is very familiar to all OAM experts. End User very often bookmark the OAM-form login page thinking that it is an inseparable piece of their protected application.  So, when User comes from this bookmarked login page , he ends in the OAM default blue screen as OAM does not where to redirect the user after successful authentication.

DETAIL ISSUE DESCRIPTION:-
To understand this issue , lets understand the OAM (Oracle Access Manager) flows that protects web resources in lay man terms.

1     (1) User access the protected resource (say https://MyApp.abc.com) thru browser.

2     (2) The request hits webserver where Webgate examines every URL pass thru it. It checks, if the requested URL is configured as a protected resource in OAM server. If yes, Webgate  takes the instruction from OAM server and show the configured  login page (https://sso.abc.com/oam-form/login.jsp). User then submits his/ her user-id and password thru the login page.

3    (3) OAM server validates the credential .  If authentication is successful,  OAM server then instructs the Webgate to redirect the user to “Originally Requested URL” (https://MyApp.abc.com).

Note that the login page mentioned in step 2 is a generic login page serve many other applications too. User often thinks that the login page is application (MyApp.abc.com) specific and book marks it. Ideally, user should bookmarks the application (MyApp.abc.com) home page only after successful authentication.
When User comes from the book marked login page , it starts the process from step 2 mentioned above. Webgate does not have the “Original Requested URL”, so it does not know where to redirect the user after successful authentication.  Thus,  Webgate fails to redirect to the protected resource after successful authentication and ends in dirty default blue screen.

SOLUTION :-
We cannot educate user about the OAM internal working mechanism. So lets accept the fact that some user will book mark the login page instead of the application home page.  I would like to thanks my colleague Adam Callen (http://idmrockstar.com/blog/) for the original idea.
If a user comes from a book-marked page, do the followings.

      (1)  Identify, if the user is coming from a book marked page.
2    (2) If No, (by checking if “#URL=*” exists)
a.       OAM server sends the “Oiginal Requested URL” as a parameter.
b.      Extract “Originally Requested URL” from request object and add this URL to the end of login page URL.  

Example :
The blue colored one is the default login page URL and we add the red colored URL when user comes for the first time

Now user may bookmark this page. Note that we injected the  additional URL “Original Requested URL” at the end of the login page URL. If user come from the book marked page we can extract this information later.  Note that the additional information added to the URL only after the page loading is complete.

3    (3) If yes,  (by checking if “#URL=*” exists)
a.       Extract “Originally Requested URL” (https://MyApp.abc.com/) from login page URL (https://sso.abc.com/oam-form/login.jsp#URL=https://MyApp.abc.com/)
b.      Now redirect the user to “Originally Requested URL” (https://MyApp.abc.com/) before the login page loads itself.
c.       Since the “Originally Requested URL” (https://MyApp.abc.com) is a protected resource, now the authentication process will go thru normal process as mentioned in step 2 above.

Here is the javascript that does all the above said trick.
function checkIfBookmarked() {    
    var hashString = location.hash ;     // https://sso.abc.com/oam-form/login.jsp#URL=https://MyApp.abc.com/   
    var extractedHash = "NotBookMarked"
    if (hashString.length > 0) {
        var extractedHash = location.hash.substring(0,5) ;               
    }                 

    // If the URL has a '#URL' value, that indicate user is coming from a book marked page.
    // #URL= contain the URL value of originally requested URL.
    // so extract the value and redirect the user to that originally requested URL.
    if (extractedHash == "#URL=") {       
        var remainingURL = location.hash.substring(5, location.hash.length) ;
        //alert("You fool.. You have bookmarked a common login page. Redirecting to " + remainingURL) ;      
        window.location.href = remainingURL ;               
    }
    else { 
       // user is not coming from a book marked page. We are good, but user may book mark it.
       // so embed the Originally Requested URL to as hash.       
        location.hash = 'URL=' + "<%=origRequestedUrl %>" ;                            
    }
}

Wednesday, October 10, 2012

Quick Tips: Finding the IAM component versions

It was little harder than I thought :(  My weblogic expert friend shared it.

For OIF and OAM :-

Assuming that you have installed OIF from Oracle_IDM2
$ export ORACLE_HOME=/opt/apps/Oracle/Middleware/Oracle_IDM2
$ export PATH=$PATH:/opt/apps/Oracle/Middleware/Oracle_IDM2/OPatch
$ opatch lsinventory -detail -invPtrLoc /opt/apps/Oracle/Middleware/Oracle_IDM2/oraInst.loc

For OHS  :-
opatch lsinventory -detail -invPtrLoc /opt/apps/OHS/Oracle_WT1/oraInst.loc

For WEBGATE :-
opatch lsinventory -detail -invPtrLoc /opt/apps/OHS/Oracle_OAMWebGate1/oraInst.loc -jdk /opt/apps/OHS/oracle_common/jdk/




Monday, October 1, 2012

Changing OIF server parameter using WLST

A quick reference on WLST usage. Here is an example of setting of an OIF server parameter (userldapconnectionreadtimeout') using WLST command.

$ export DOMAIN_HOME=..Directory/Oracle/Middleware/user_projects/domains/OIF_DOMAIN  
$ . Directory/opt/apps/Oracle/Middleware/Oracle_IDM2/fed/scripts/setOIFEnv.sh
$ java weblogic.WLST
wls:/offline> setConfigProperty('datastore','userldapconnectionreadtimeout', '120','long')
                   Please enter your username :weblogic
                   Please enter your password :
                   Please enter your server URL [t3://localhost:7001] :t3://oifServer.abc.com:7499

wls:/EPP_STAGE_SECURITY_DOMAIN/serverConfig> disconnect()

wls:offline >exit()

check for your change at :-
$ vi /opt/apps/Oracle/Middleware/user_projects/domains/EPP_STAGE_SECURITY_DOMAIN/config/fmwconfig/servers/wls_oif2/applications/OIF_11.1.1.2.0/configuration/config.xml

Monday, September 24, 2012

Making your OAM custom Login Form XSS safe

In real life OAM implementation we all use fancy login form , which is called from OAM authentication scheme. These custom login screen often use java scripts. The screen also contain at-least two input parameters 'Login-Name' and 'Password'.  So the screen is perfect play ground for XSS (Cross Site Scripting) attack. Here are few tips to make it XSS safe. For more information about XSS venerability check OWASP (https://www.owasp.org/index.php/XSS) website.

1. Make sure your authentication scheme has a challenge parameter called "ssoCookie=httponly". This will ensure that the java-script cannot read the OAM cookies.

2. The user input validation is must. For example evil user may enter "JohnDoe script alert(document.cookie); script" in the username field to test if the login form is venerable to XSS.

3. Always re-encode user output into safe code html, CSS, JS etc.  For example,  after safe encoding, your javascript should look like "<script> alert(document.cookie); <script>"
The OWASP ESAPI library to do this safe encoding.

Tuesday, May 29, 2012

OVD 11g Quick Tips

Finding OVD version :-
Open file ..../Oracle/Middleware/OVD_INST_1/config/OVD/ovd1/server.os_xml .
Look for section  "OVD_INST_1_OVD" .

Setting OVD Log (Alternative to console) :-
You can set OVD log level directly using console UI. But, you may get an error "JAVAX.EL.ELEXCEPTION: JAVA.LANG.NULLPOINTEREXCEPTION AT JAVAX.EL.BEANELRESOLVER" because of an  OVD 11.1.1.5 bug while doing it from em console.

Here is an alternative approach Doc
1. Stop OVD :
$ORACLE_INSTANCE/bin/opmnctl stopproc ias-component=ovd1

2. Open $ORACLE_INSTANCE/config/OVD/ovd1/ovd-logging.xml change such as to have
<loggers>
<logger name='com.octetstring.vde' level='TRACE:32' useParentHandlers='false' >
<handler name='OVDHandler'/ >
</logger >
<logger name='com.octetstring.accesslog' level='TRACE:32' useParentHandlers='false' >
<handler name='OVDAccessHandler'/ >
</logger >
</loggers>

3. Start OVD: $ORACLE_INSTANCE/bin/opmnctl startproc ias-component=ovd1


Setting Worker Tread :-

Does your OVD error log (.../ovd_inst/diagnostics/logs/OVD/ovd1/http-errors.log) shows occasional error message called “Low on Thread” or “Out of thread”. Check $OVD_HOME/config/OVD/listeners.os_xml for at least 50 worker threads in the LDAP listener.

look for entry
10 and change it to 50 
do it for "Admin Gateway", "LDAP Endpoint" and "LDAP SSL Endpoint".


Wednesday, January 11, 2012

OIM 11.1.1.5 User Manager API bug causes double provisioning

I wrote a Post Process Event Handler code, which provide value to a User's attribute during user creation. The event-handler code was using UserManagerment (oracle.iam.identity.usermgmt.api.UserManager) API.

public class GuidGenerationPostProcEventHandler implements oracle.iam.platform.kernel.spi.PostProcessHandler {
:
public EventResult execute(long processId, long eventId, Orchestration orchestration) { 
HashMap params = orchestration.getParameters();
String uid = this.getParamaterValue(params, Constants.USERID); 
oracle.iam.identity.usermgmt.vo.User user = new User(uid);
user.setAttribute("Micam Unique Id", generateUniqueId()); // generateUniqueId is a private method and returns some value 
try {
   usrMgrService = Platform.getService(UserManager.class);    
   usrMgrService.modify(Constants.USERID, uid, user);
catch (...) 
:
:
}
return ( new EventResult() );
    :
    :

The above said code worked as expected. It generated the value and populated the user attributes called "Micam Unique Id".  But, this code did some damage to my auto-provisioning set up to OID. I saw two auto-provisionings are initiated during user creation event instead of one. I could not figure out the cause. so I posted the query to oracle forum ( https://forums.oracle.com/forums/thread.jspa?threadID=2329154 ) and found the following answer from some of our smart users. 

There is a known issue in UserManagement APIs in OIM 11.1.15. Using the UsrMngmt APIs to update a User within an Orchestration will cause another user update orchestration to be initiated. The user update is also causing role membership rules to be evaluated, which in turn is triggering second provisioning. So solution is to use Entity Management (oracle.iam.platform.entitymgr.EntityManager) APIs instead . The new code snippet is given here, which works fine so far. 

public class GuidGenerationPostProcEventHandler implements oracle.iam.platform.kernel.spi.PostProcessHandler {
    :    
 public EventResult execute(long processId, long eventId, Orchestration orchestration) {        
        HashMap mapAttrs = new HashMap() ;
    mapAttrs.put("Micam Unique Id", generateUniqueId()); // generateUniqueId is a private method and returns some value 
    try {
   String userKey;     
   if (!orchestration.getOperation().equals("CREATE")) 
userKey = orchestration.getTarget().getEntityId();
   else {
    OrchestrationEngine orchEngine = Platform.getService(OrchestrationEngine.class);            
    userKey = (String) orchEngine.getActionResult(processID);
            }        
            
            entMgrService = Platform.getService(EntityManager.class);        
            entMgrService.modifyEntity(orchestration.getTarget().getType(), userKey, mapAttrs);                        
    }
    catch (..) {
    :      
    return ( new EventResult() );
     :
     :

As of writing this blog, there is no UserMgmt & EntityMgmt API documentations available from Oracle. So good luck.