Search code examples
ibm-mobilefirstworklight-adaptersworklight-security

IBM Worklight 5.0.6 - Two clicks required for login instead of one


I am using the Form-based authentication and challenge handler (sample codes) in my App. The problem is, it is not authenticating users on a single click on the login button - I have to click two times. Why?

I have protected all adapter functions.

My challenge handler :

var myAppRealmChallengeHandler = WL.Client.createChallengeHandler("myAppRealm");
myAppRealmChallengeHandler.isCustomResponse = function(response) {
     if (!response || response.responseText === null) {
        return false;
    }
    var indicatorIdx = response.responseText.search('j_security_check');
    WL.Logger.debug("indicatorIdx =" + indicatorIdx);
    if (indicatorIdx >= 0){ return true; }  
    return false; 
};
myAppRealmChallengeHandler.handleChallenge = function(response) {
    $.mobile.changePage("#landingPage" , { transition: "slide"});
    WL.Logger.debug("Login Again");
};

myAppRealmChallengeHandler.submitLoginFormCallback = function(response) {
    var isLoginFormResponse = myAppRealmChallengeHandler.isCustomResponse(response);
    WL.Logger.debug("submitLoginFormCallback " + isLoginFormResponse + " responseText " + response.responseText);
    if (isLoginFormResponse){
        myAppRealmChallengeHandler.handleChallenge(response);
    } else {
        myAppRealmChallengeHandler.submitSuccess();
    }
};
$('#logindone').bind('click', function () {
        var reqURL = '/j_security_check';
        var options = {};
            options.parameters = {
                j_username : $.trim($('#fldloginUserID').val().toLowerCase()),
                j_password : $.trim($('#fldloginUserPassword').val())
            };
            options.headers = {};
            myAppRealmChallengeHandler.submitLoginForm(reqURL, options, myAppRealmChallengeHandler.submitLoginFormCallback);
    processLogin();
});

authenticationConfig.xml

<securityTests>
        <mobileSecurityTest name="myMobileSecurity">
            <testUser realm="myAppRealm"/>
            <testDeviceId provisioningType="none"/>
        </mobileSecurityTest>       
        <customSecurityTest name="PushApplication-custom-securityTest">                             
            <test isInternalUserID="true" realm="PushAppRealm"/>   
        </customSecurityTest>       
        <customSecurityTest name="myAppSecurityTestCustom">                             
            <test isInternalUserID="true" realm="myAppRealm"/>   
        </customSecurityTest>       
        <customSecurityTest name="WorklightConsole">
            <test realm="WorklightConsole" isInternalUserID="true"/>
        </customSecurityTest>
</securityTests>    
<realms>
        <realm loginModule="StrongRC" name="myAppRealm">
            <className>com.worklight.core.auth.ext.FormBasedAuthenticator</className>
            <!--<parameter name="login-page" value="login.html"/>-->
        </realm>
        <realm loginModule="PushAppLoginModule" name="PushAppRealm">                                                
            <className>com.worklight.core.auth.ext.BasicAuthenticator</className>   
            <parameter name="basic-realm-name" value="PushAppRealm"/>                                                  
        </realm>
        <realm loginModule="Console" name="WorklightConsole">
            <className>com.worklight.core.auth.ext.FormBasedAuthenticator</className>
            <onLoginUrl>/console</onLoginUrl>
        </realm>
</realms>
<loginModules>
         <loginModule name="PushAppLoginModule">
            <className>com.rc.services.RCAuthModule</className>
        </loginModule>      
        <loginModule name="StrongRC">
            <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
        </loginModule>      
        <loginModule name="Console">
            <className>com.worklight.core.auth.ext.SingleIdentityLoginModule</className>
        </loginModule>
</loginModules>

my processLogin() function

function processLogin(userid,password){ 
    var userid = $("#fldloginUserID").val();
    var password = $("#fldloginUserPassword").val();    
    WL.Logger.debug("Authenticating user credentials...");
    var invocationData = {  adapter: "LDAPAdapter", procedure: "ValidateUsers", parameters: [userid, password]};    
    WL.Client.invokeProcedure(invocationData, { 
        onSuccess: checkUserAccountStatus,  
        onFailure: function(){  hideBusyIndicator();
            showPopUp(msg_en.LoginFailed_MsgTitle , msg_en.LoginFailed_MsgDescription_2);
        } ,timeout : 30000  });
}

function checkUserAccountStatus(response){
    WL.Logger.debug("Checking user account status...");
    xmlDoc = $.parseXML(response.invocationResult.result);
    $xml = $( xmlDoc ); 
    if (!response ||!response.invocationResult || !response.invocationResult.result ||
            $xml.find("isUserValidated").text()=="false" ) { hideBusyIndicator();  
            showPopUp(msg_en.LoginFailed_MsgTitle, msg_en.LoginFailed_MsgDescription_2);
    else { getUserDetails(response.invocationResult.result); }  
}

function getUserDetails($xml){
 ...doing something over retrieved data from LDAP ,like saving in local var......
 ....
 ...then calling another adapter....
    if($xml.find("LDAPuserID").text() > 0){                 
            var invocationData = {adapter: "MQAdapter",procedure: "ListSummariesDetails", parameters: [$xml.find("LDAPuserID").text() ] };
            WL.Client.invokeProcedure(invocationData, {
                onSuccess: getSecretSuccessData_Callback,
                onFailure: function(){ hideBusyIndicator();
                    showPopUp(msg_en.SystemError_Title , msg_en.SystemError_Description);
                } ,timeout : 30000 });
        }   
}

function getSecretSuccessData_Callback(response){
...... now do something over retrived data
...let the user go in the main page of the App after login screen
    $.mobile.changePage("#mainPage" , { transition: "slide"});
}

The ValidateUsers and ListSummariesDetails adapter functions are protected using myAppSecurityTestCustom which is given above.


Solution

  • This question was answered via a PMR the customer opened in IBM. They have since changed the implementation to using Adapter-based authentication as that is the authentication flow that fits their app structure. This question is somewhat outdated by now...