1
votes

I have defined an Adapter based authentication.

Doing a custom security test which works successfully.

But when I wanted to implement User Subscription based Push Notifications and added a mobile security test in authenticationConfig.xml I am facing lot of issues.

As I'm trying to deploy the app and test in android device. I have also included the mobile security test in android tag of application-descriptor.xml. But facing lot of issues to deploy the adapter itself after this.

Please refer to the below code snippets which I am using

authenticationConfig.xml

    <mobileSecurityTest name="MST1">
        <testUser realm="AdapterAuthRealm"/>
        <testDeviceId provisioningType="none"/>
    </mobileSecurityTest>

    <webSecurityTest name="WST1">
        <testUser realm="AdapterAuthRealm"/>
    </webSecurityTest>

    <customSecurityTest name="Master-Password">
        <test realm="AdapterAuthRealm" isInternalUserID="true"/>
    </customSecurityTest>

Authentication was running fine till I had only the customSecurityTest being defined.

After adding web and mobile security test, there is no response when I give the credentials and click login neither from GUI side nor from the console logs side.

I have also added security test in android tag in application-descriptor.xml as below

<android securityTest="MST1" version="1.0"> 
    <worklightSettings include="false"/>        
    <pushSender key="xxxxxxxxxxx" senderId="xxxxxxxxxxxxxxx"/>

    <security>
        <encryptWebResources enabled="false"/>
        <testWebResourcesChecksum enabled="false" ignoreFileExtensions="png, jpg, jpeg, gif, mp4, mp3"/>
        <publicSigningKey/>
        <packageName/>
    </security>
</android>

To be more precise. Let me add the following code snippet which is from the IBM MobileFirst Platform Foundation sample.

PushAdapter-impl.js

function wlCommonInit() {
    WL.Client.connect({onSuccess: connectSuccess, onFailure: connectFailure});
}

function connectSuccess() {
    WL.Logger.debug ("Successfully connected to MobileFirst Server.");
}

function connectFailure() {
    WL.Logger.debug ("Failed connecting to MobileFirst Server.");
    WL.SimpleDialog.show("Push Notifications", "Failed connecting to MobileFirst Server. Try again later.", 
            [{
                text : 'Reload',
                handler : WL.Client.reloadapp
            },
            {
                text: 'Close',
                handler : function() {}
            }]
        );
}

function isPushSupported() {
    var isSupported = false;
    if (WL.Client.Push){
        isSupported = WL.Client.Push.isPushSupported();
    }   
    alert(isSupported);
}

function isPushSubscribed() {
    var isSubscribed = false;
    if (WL.Client.Push){
        isSubscribed = WL.Client.Push.isSubscribed('myPush');
    }
    alert(isSubscribed);
}

//---------------------------- Set up push notifications -------------------------------
if (WL.Client.Push) {   
    WL.Client.Push.onReadyToSubscribe = function() {
        alert("onReadyToSubscribe");

        $('#SubscribeButton').removeAttr('disabled');
        $('#UnsubscribeButton').removeAttr('disabled');

        WL.Client.Push.registerEventSourceCallback(
            "myPush", 
            "PushAdapter", 
            "PushEventSource", 
            pushNotificationReceived);
    };
}

// --------------------------------- Subscribe ------------------------------------
function doSubscribe() {
    WL.Client.Push.subscribe("myPush", {
        onSuccess: doSubscribeSuccess,
        onFailure: doSubscribeFailure
    });
}

function doSubscribeSuccess() {
    alert("doSubscribeSuccess");
}

function doSubscribeFailure() {
    alert("doSubscribeFailure");
}

//------------------------------- Unsubscribe ---------------------------------------
function doUnsubscribe() {
    WL.Client.Push.unsubscribe("myPush", {
        onSuccess: doUnsubscribeSuccess,
        onFailure: doUnsubscribeFailure
    });
}

function doUnsubscribeSuccess() {
    alert("doUnsubscribeSuccess");
}

function doUnsubscribeFailure() {
    alert("doUnsubscribeFailure");
}

//------------------------------- Handle received notification ---------------------------------------
function pushNotificationReceived(props, payload) {
    alert("pushNotificationReceived invoked");
    alert("props :: " + JSON.stringify(props));
    alert("payload :: " + JSON.stringify(payload));
}

authenticationConfig.xml

<securityTests>
    <webSecurityTest name="PushApplication-web-securityTest">
        <testUser realm="PushAppRealm"/>
    </webSecurityTest>
    <mobileSecurityTest name="PushApplication-strong-mobile-securityTest">
        <testUser realm="PushAppRealm"/>
        <testDeviceId provisioningType="none"/>
    </mobileSecurityTest>
    <customSecurityTest name="SubscribeServlet">
        <test realm="wl_directUpdateRealm" step="1"/>
        <test isInternalUserID="true" realm="SubscribeServlet"/>
    </customSecurityTest>
</securityTests>      

<realms>
    <realm loginModule="PushAppLoginModule" name="PushAppRealm">
         <className>
              com.worklight.core.auth.ext.FormBasedAuthenticator
         </className>                   
    </realm>
</realms>


<loginModule name="PushAppLoginModule">
        <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
    </loginModule>

As we can see they are using a Form based Authenticator approach. Please let me know the concept if it can be implemented using the Adapter based authentication. Else it would be really helpful if you club the Adapter based authentication for the above push notifications implementation.

1
Lots of text, no code whatsoever. Add a sample app where we can see this failing. Also mention what is failing/not working exactly. - Idan Adar
As I placed the question initially by phone, was unable to place the code snippet. Please refer above. - Senthil
This is not enough. Can you provide the Whole project to debug? - Idan Adar
I can understand. I have a few restriction's in posting the entire project as it's an official content. But I can tell you the scenario what I am looking for. - Senthil
I understand the scenario. Try to create a smaller-scale app without your private content. - Idan Adar

1 Answers

2
votes

You can implement event source push notifications using the adapter based authenticator. I took the event source push notifications sample and integrated the adapter based authentication sample into it. All you need to do is add the following changes to adjust the sample:

authenticationConfig.xml

Add a security test, realm and login module:

<mobileSecurityTest name="PushSecurityTest">
    <testUser realm="AuthRealm" />
    <testDeviceId provisioningType="none" />
</mobileSecurityTest>

<realm loginModule="AuthLoginModule" name="AuthRealm">
    <className>com.worklight.integration.auth.AdapterAuthenticator</className>
    <parameter name="login-function" value="PushAdapter.onAuthRequired" />
    <parameter name="logout-function" value="PushAdapter.onLogout" />
</realm>

<loginModule name="AuthLoginModule">
    <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
</loginModule>

PushAppRealmChallengeHandler.js

Change the challenge handler methods:

var pushAppRealmChallengeHandler = WL.Client.createChallengeHandler("AuthRealm");

pushAppRealmChallengeHandler.isCustomResponse = function(response) {
    if (!response || !response.responseJSON || response.responseText === null) {
        return false;
    }
    if (typeof(response.responseJSON.authRequired) !== 'undefined'){
        return true;
    } else {
        return false;
    }
};

pushAppRealmChallengeHandler.handleChallenge = function(response) {
    var authRequired = response.responseJSON.authRequired;

    if (authRequired == true){
        $("#AppBody").hide();
        $("#AuthBody").show();
        $('#passwordInputField').val('');

        if (response.responseJSON.errorMessage)
            alert(response.responseJSON.errorMessage);

    } else if (authRequired == false){
        $("#AppBody").show();
        $("#AuthBody").hide();
        pushAppRealmChallengeHandler.submitSuccess();
    }

};



$('#loginButton').bind('click', function () {
    var username = $("#usernameInputField").val();
    var password = $("#passwordInputField").val();

    var invocationData = {
        adapter : "PushAdapter",
        procedure : "submitAuthentication",
        parameters : [ username, password ]
    };

    pushAppRealmChallengeHandler.submitAdapterAuthentication(invocationData, {});

});

I chose to add the adapter procedures to the existing one (you can also add another one):

PushAdapter.xml

Add the submitAuthentication procedure:

<procedure name="submitAuthentication" securityTest="wl_unprotected" />

PushAdapter-impl.js

Add the following procedures:

function onAuthRequired(headers, errorMessage){
    errorMessage = errorMessage ? errorMessage : null;

    return {
        authRequired: true,
        errorMessage: errorMessage
    };
}

function submitAuthentication(username, password){
    if (username==="user" && password === "password"){

        var userIdentity = {
                userId: username,
                displayName: username, 
                attributes: {
                    foo: "bar"
                }
        };

        WL.Server.setActiveUser("AuthRealm", userIdentity);

        return { 
            authRequired: false 
        };
    }

    return onAuthRequired(null, "Invalid login credentials");
}

function getSecretData(){
    return {
        secretData: "Very very very very secret data"
    };
}

function onLogout(){
    WL.Logger.debug("Logged out");
}

Note: My code samples are based on the Getting Started 7.1 samples. If you use a different MobileFirst version, just change the name accordingly.