Question

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.

Was it helpful?

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...

OTHER TIPS

it looks like your login page (landingPage) is visible when the app starts, and that the first time logindone gets clicked, there is no authentication in progress (yet). This won't work the way you are expecting.

Make a different page the default page for your app. Take the call to processLogin() out of your click handler. I would also put the transition to mainPage in the success case of submitLoginFormCallback().

Now, put a call to WL.Client.login() in wlCommonInit(). (this will trigger authentication) Put the call to processLogin() in the success callback for the call to WL.Client.login()

I faced this problem when I was using IP Address for testing and DNS entry was present in the code, i.e. my URL was mydomain.com and IP is 123.123.123.123 , now if I built the application using 123.123.123.123 , I have to click the login button twice.

The solution I found was to add mydomain.com in my hosts / DNS server and after that I built the application for mydomain.com.

Worked perfectly for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top