I am experiencing a problem with authentication within an Android application, I am using Worklight version 5.0.6.
I have created a secure app using this authentication configuration:
<securityTests>
<mobileSecurityTest name="Sencha22-Mobile-SecurityTest">
<testDeviceId provisioningType="none"/>
<testUser realm="SampleAppRealm"/>
</mobileSecurityTest>
</securityTests>
<realms>
<realm loginModule="StrongDummy" name="SampleAppRealm">
<className>com.worklight.core.auth.ext.FormBasedAuthenticator</className>
</realm>
</realms>
<loginModules>
<loginModule name="StrongDummy">
<className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
</loginModule>
</loginModules>
I also have a ChallengeHandler with the following:
challengeHandler.submitLoginFormCallback = function(response) {
var isLoginFormResponse = challengeHandler.isCustomResponse(response);
if(isLoginFormResponse){
//login unsuccessful
Ext.Msg.alert('Error', "Login not successful", Ext.emptyFn);
}else{
//login successful, reload the app
WL.Client.reloadApp();
}
}
The WL.Client.reloadApp() statement is executing correctly after authentication occurs, however the function:
WL.Client.isUserAuthenticated("SampleAppRealm")
is ALWAYS returning NULL on Android.
The application works fine when viewed as Common Resources in Chrome.
Is there a problem with isUserAuthenticated on Android?
First of all, I don't think reloading application after authentication is a good idea.
Now. Authentication information is received from WL server once application connects to it. To connect to a WL server you need to either set connectOnStartup:true in initOptions.js or use WL.Client.connect() API. Since you're saying that problem occurs only on android my guess is that you have timing issue. Make sure that you're calling isUserAuthenticated API after client has successfully received a response from server.
isUserAuthenticated will always return true or false in 5.0.6 and is completely javascript based (so it should be consistent regardless of platform). I think something else is going on here to get you a NULL... are there any javascript exceptions? One way to check is to use a javascript debugging library on android devices such as weinre (add a javascript file to your html, then connect to a local server to debug console output: http://people.apache.org/~pmuellr/weinre/docs/latest/). See if there are any exceptions being thrown in the javascript output. As Anton said, you may also be experiencing a timing issue with your device.
Side note: Anton is correct: WL.Client.reloadApp() may clear the authentication state based on the device or browser's settings.
Related
I am creating app and I have added Android, Mobile webapp as an Worklight Environment that means I want to use same App as webapp(by using its URL). I am creating 2 seperate security test one is Mobile security test and other one is Web security test, but my Adapters procedure are common(for eg:procedure1), **So is it possible to apply two security test to one single procedure.**This is what I tried but it didn't worked.
Following is my Mobile security Test
<mobileSecurityTest name="BankingTest">
<testDeviceId provisioningType="none" />
<testUser realm="BankingRealm" />
<testDirectUpdate mode="perSession" />
</mobileSecurityTest>
Following is my Web security Test
<webSecurityTest name="BankingWebTest">
<testUser realm="BankingWebRealm"/>
</webSecurityTest>
Following is how procedure is protected in xml file
<procedure name="getDetail" securityTest="BankingTest"/>(Its working).
But when I tried
<procedure name="getDetail" securityTest="BankingTest"/>
<procedure name="getDetail" securityTest="BankingWebTest"/>
--OR--
<procedure name="getDetail" securityTest="BankingWebTest;BankingTest"/>
its not working.
My requirement is: I want to protect 1 same procedure with 2 different security test. So Please suggest me what is better approach and how.
I dont think that you can use more than one securityTest to protect the same procedure or resource.
I don't think that you need a separate realm for web and mobile.
Additionally, you cannot set more than one securityTest per procedure.
Consider not using two realms if not required and then use a custom securityTest instead of one for web and one for mobile.
I am trying to develope a simple hybrid app using an adapter based authentification.
All the examples I have found explain how to do it assuming that firstly we call a secured procedure to fire the authentication process.
I've been trying to develope a login calling directly to a "login adapter" to perform the authentication. I've tried using the "submitAdapterAuthentication" but the challenge handler is creating a infinite loop.
I did manage to make a login invoking the "login adapter" as a common procedure("WL.Client.invokeProcedure(...)"), but then I was not able to subscribe to a event source and I need PUSH notification functionality. I got always the next error:
Can't subscribe, notification token is not updated on the server
Is it posible to authenticate against Worklight Server calling directly to a "login adapter" using Adapter Based Authentificaton? How?
I think the approach of a direct login call makes sense but I haven't found any official solution to it.
If you want to invoke authentication process explicitly, you can use WL.Client.login(realm, options) API provided by Worklight.
http://pic.dhe.ibm.com/infocenter/wrklight/v6r0m0/index.jsp?topic=%2Fcom.ibm.worklight.help.doc%2Fapiref%2Fr_wl_client_login.html
Another option is to add a security test at the application level inside of application-descriptor.xml for each environment.
This will cause the app to ask for authentication immediately.
<iphone securityTest="nameOfMobileTest" bundleId="com.myApp" version="1.0>
....
</iphone>
<android securityTest="nameOfMobileTest" version="1.0">
....
</android>
Worklight 6.1.0.1, and using Chrome based simulator to start the mobile web application. Application and adapters deployed from WL studio to the WL development Server.
I have a secure adapter procedure(s) and I've tested with two configurations:
<procedure requestTimeoutInSeconds="20" name="getBaseData" securityTest="Connections-securityTest"/>
<procedure requestTimeoutInSeconds="20" name="getCommunityMembersOf" securityTest="Connections-securityTest"/>
and
<procedure connectAs="endUser" requestTimeoutInSeconds="20" name="getBasetData" securityTest="Connections-securityTest"/>
<procedure connectAs="endUser" requestTimeoutInSeconds="20" name="getCommunityMembersOf" securityTest="Connections-securityTest"/>
getBaseData simply creates the active user (including id + pwd for later use), and returns fixed data to the app.
getCommunityMemberOf is an https adapter that retrieves data from a backend server. This adapter retrieves the id + pwd from the active user and includes this information as input to the https request.
I start the first chrome simulator session with the javascript console showing that the application invoked procedure getBaseData. The credentials are collected and authenticated, and setActiveUser is completed. The application then invokes procedure getCommunityMembersOf and this procedure call processes with no authentication, as expected.
I start a second chrome simulator session for the same application and the javascript console shows that the invoke procedure getBaseData is not challenged, and is processed which seems to indicate that the authentication completed indicating simulator session #1 authentication also satisfied simulator session #2 authentication. This is a behavior I want to prevent and have both simulator session require authentication independently. Appreciate any advice about why this is happening, and what I can do to prevent this session sharing. Thank You.
Chrome is sharing the session between the different tabs, it has nothing to do with Worklight.
What you can do is open a new browser in incognito mode to prevent sharing the session. Or open a different kind of browser.
I am currently working on a Worklight 6.0 POC using the Header Authentication authentication/login module. When attempting to access a protected adapter in the app I receive the following error in the console:
403 (Forbidden)
TypeError: Object # has no method 'handleFailure'
I receive this error when testing the web version of the app via the console in chrome.
I also get a similar error when testing on the iPhone version of the app.
exception. TypeError: 'undefined' is not a function (evaluating 'handler.handleFailure(wlFailure[realm])')
Looking through the wlclient.js file within the AbstractChallengeHandler class/function I am not seeing a function definition for handleFailure which explains the above error. I assume there should be a definition for handleFailure or are there more configurations that are need for protecting an adapter resource using Header Authentication?
My reason for asking this question, is that I am trying to test my logic in the client side "ChallengeHandler" piece that I have created, and I am trying to understand why I am not able to see this type of error/response via the normal client side challenger.isCustomResponse/challenger.handleChallenge communication.
Code/configuration is below
Any advice/input is appreciated
authenticationConfig.xml
<securityTests>
<webSecurityTest name="WebSecurityTest">
<testUser realm="HeaderAuthRealm"/>
</webSecurityTest>
<mobileSecurityTest name="MobileTest">
<testUser realm="HeaderAuthRealm"/>
<testDeviceId provisioningType="none"/>
</mobileSecurityTest>
<customSecurityTest name="HeaderAuth-securityTest">
<test realm="HeaderAuthRealm" isInternalUserID="true" />
</customSecurityTest>
</securityTests>
<realms>
<realm name="HeaderAuthRealm" loginModule="HeaderLoginModule">
<className>com.worklight.core.auth.ext.HeaderAuthenticator</className>
</realm>
</realms>
<loginModules>
<loginModule name="HeaderLoginModule">
<className>com.worklight.core.auth.ext.HeaderLoginModule</className>
<parameter name="user-name-header" value="HeaderAuth_USER"/>
</loginModule>
</loginModules>
HeaderAuthRealmChallenger.js
var HeaderAuthRealmChallenger = WL.Client.createChallengeHandler("HeaderAuthRealm");
HeaderAuthRealmChallenger.isCustomResponse = function(response) {
if (response.responseJSON.isSuccessful) {
WL.Logger.info('AUTHENTICATION SUCCESS =).......');
return false;
}else{
return true;
}
};
HeaderAuthRealmChallenger.handleChallenge = function(response){
WL.Logger.info('AUTHENTICATION FAILED =(.......');
$('#login').css('display','block');
};
Documentation is currently missing on this and should be updated shortly.
I think that the authenticator you are using does not support regular ChallengeHandler, rather it uses WLChallengeHandler.
Here is a preview of the documentation on this:
WL.Client.createWLChallengeHandler() API
This method creates a challenge handler object to handle challenges
that are sent by the Worklight Server. A WLChallenge handler works
only with an authentication realm that is based on the Worklight
authentication protocol, that is, for which the server side
authenticator instance extends one of the Worklight provided
Authenticators, such as WorklightProtocolAuthenticator or
UsernamePasswordAuthenticator, or directly implements the
WorklightAuthenticator interface.
There must be only one challenge handler per realm. To comply with the
Worklight authentication protocol, the challenge that the realm
receives must be a JSON object.
Parameters realmName – The realm name that represents the
challenge, in the authenticationConfig.xml configuration file. Use
this name to identify the realm that requires authentication.
When you create a WLChallengeHandler, you must implement the following
methods:
handleChallenge() - This method is called when the Worklight Server returns a challenge for the realm.
processSuccess() - This method is called when the Worklight Server reports an authentication success.
handleFailure() - This method is called when the Worklight Server reports an authentication failure.
I have a button in my Worklight app which subscribes the app and user to a notification source in much the same way as the Notification sample at this URL: http://www.ibm.com/developerworks/mobile/worklight/getting-started.html#advanced
The problem is that when the device restarts / or the app shuts and I need to relogin - the isSubscribed function will return false - despite previously being true.
Is the client side meant to automatically save its subscriptions? What is the best practice for maintaining a subscription to a notification source across multiple device / app restarts?
This is my securityTests setup :
<securityTests>
<customSecurityTest name="WebServicesAdapters-securityTest">
<test isInternalUserID="true" realm="CustomAuthenticatorRealm"/>
</customSecurityTest>
<mobileSecurityTest name="PushApplication-strong-mobile-securityTest">
<testUser realm="CustomAuthenticatorRealm"/>
<testDeviceId provisioningType="none"/>
</mobileSecurityTest>
</securityTests>
This is a defect in Worklight v5.0.5.x, fixed in 5.0.6.
To work around it you can try using authentication that is not adapter-based. This will fail if protecting only the adapter, the application must be protected as well.