If we keep our WL apps in background for a while, they seem to be lost connection with the MF server. I thought this could be related with features defined in application-descriptor.xml as there's a accessTokenExpiration attribute with a value of 3600, and the MF server logged errors below:
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'46ejj4elqjtg3vrn8j4qaql8es', client token:'2kvma3lscib0h1q5dlu7mak818'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'k8irk7mftj0j4ostbbba7smqto', client token:'mptvg1t1l4n8e7qfr1ratrcf30'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'dhfjgut9aku08hcm88rlb9rjo2', client token:'46ejj4elqjtg3vrn8j4qaql8es'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'mdva1p1nt428oii6nvd91n7vu5', client token:'46ejj4elqjtg3vrn8j4qaql8es'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'jmbvd7ocaoj4gb709n0b3mh62g', client token:'dhfjgut9aku08hcm88rlb9rjo2'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'tv1t1blffk8sekc1422oq6s64a', client token:'mdva1p1nt428oii6nvd91n7vu5'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'sh06en0ihc0i7dvd77fpkrj57s', client token:'jmbvd7ocaoj4gb709n0b3mh62g'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'6070lc7pafqusf4jslhsh8a49b', client token:'tv1t1blffk8sekc1422oq6s64a'. [project Dummy]
[ERROR ] FWLSE4007E: Received bad token from client. Server token:'vhds5i92t64pkfn3htdcjr3749', client token:'6070lc7pafqusf4jslhsh8a49b'. [project Dummy]
So it's a too short time that connection expires. And how can we can make a "remember me" function between MobileFirst and the client that unless the end-users quit the app, otherwise they will always being logged in?
Session timeout
In the server\conf\worklight.properties file, take a look at the property named serverSessionTimeout.
The default is 10 minutes which means that if the server does not get any request from that client within 10 minutes, the session will expire with everything attached to it. As long as the user is active, the session is renewed. Keep in mind that a longer session timeout may increase the server's memory usage.
There is also a feature called heartbeat, that sends a ping to the server to keep the session alive, but this only works when your application is in the foreground.
If your application is native, I guess you could implement your own heartbeat to keep it alive.
Token expiration
In the application-descriptor.xml, the element accessTokenExpiration will define the default OAuth token expiration for this specific application. The default is 3600 seconds (1 hour). Which means that from the moment the user logs in, they have 1 hour of trusted access, whether or not they are active.
Realm expiration
In the authenticationConfig.xml file, each loginModule has a expirationInSeconds property. Similar to the one above, it will define how long is the user trusted after they logged-in to this specific login module / realm. When the expiration happens, the server will send a new challenge for the associated realm.
In 7.0, -1 means the user is trusted until serverSessionTimeout happens. In 7.1, -1 is no longer a valid value.
If any of the above is expired, the client may need to get a new token. Depending on the expiration of each loginModule, the user may or may not receive a new challenge.
Remember Me Sample
The RememberMe sample (https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-1/foundation/advanced-topics/remember-me/) uses the idea of storing the unique Client-ID to an external database to automatically login the user when his session has expired.
You can configure expiration tokes in the server\conf\worklight.properties file.
There is also a "Remember Me" tutorial and sample application, based on MobileFirst Platform 7.1: https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-1/foundation/advanced-topics/remember-me/
Related
Using the ADAL library with a government account, the authorization token request fails due to a server timeout. The token is needed to make EWS calls to the server. The authority being used is "https://logon.microsoftonline.us". The resource is "https://outlook.office.us".
There is no issue when retrieving a token from a public tenant (our company tenant) and our product. We receive the token using ""https://logon.microsoftonline.com". The resource is "https://outlook.office.com".
We can access the server with the same credentials at "https://owa.us.af.mil/f5-w-{REDACTED}/adfs/ls/?client-request-id={REDACTED}". But ADAL times out with "https://federation.us.af.mil/adfs/ls/?login_hint={REDACTED}.af.mil&client-request-id={REDACTED}&username={REDACTED}.af.mil&wa=wsignin1.0&wtrealm={REDACTED}"
Does the government server have the proper ADFS configuration? If so, what would be the probable solution?
Is our tenant setup correctly? Do we need a public tenant for public app access and a government tenant for government clients? Or can those be interchangeable?
We setup a public and a government AAD app to handle token requests. We thought that could have been the issue. No change. I also did several variations on the authority and resources used in the request. No change. I even tapped into ADAL and use our HTTPS protocol instead of the standard Apple HTTPS protocol.
Below is the context setup and token call method used.
let authContext = ADAuthenticationContext(authority: authority, validateAuthority: true, error: &error)
authContext?.credentialsType = AD_CREDENTIALS_EMBEDDED
authContext?.acquireToken(withResource: self.resource, clientId: self.clientId, redirectUri: self.redirectUri,
userId: self.userID!, completionBlock: { result in })
The token request will always timeout at this point:
ADAL 2.7.5 iOS Sim 12.1 [2018-12-12 17:14:38 - F06F784C-7F5B-4231-BE34-714AF8204357] -webAuthDidFailWithError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x600002fa5380 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "The request timed out." UserInfo={NSErrorFailingURLStringKey=https://federation.us.af.mil/adfs/ls/?login_hint={REDACTED}.af.mil&client-request-id={REDACTED}&username={REDACTED}.af.mil&wa=wsignin1.0&wtrealm={REDACTED}
The user experiences a pop up window with a blank screen. The window would normally show text asking for permission to use the app. A timeout message hits about 60 seconds later.
apologies for the delayed response on this. Instead of outlook.office365.us, the resource you should be using is either portal.apps.mil or outlook-dod.office365.us.
Does that help?
Suppose that case when the client app has re-registered with the gcm itself but the server is unaware of this and now the server is sending notification to that particular client what I want is the notification should not be sent with the old registration id. How can this be done?
If your server sends a message to an invalid Registration token, it will probably receive a NotRegistered error response. You should handle this error accordingly by removing the corresponding token. As per the documentaion I linked above:
For all these cases, remove this registration token from the app server and stop using it to send messages.
INFO: com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
{
"error" : "invalid_grant"
}
my code is
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(js)
.setServiceAccountId(emailId)
.setServiceAccountScopes(scopes)
.setServiceAccountPrivateKeyFromP12File(new File(privateKeyPath)).build();
System.out.println("SERVICE ACCOUNT SERVLET CALLED");
credential.refreshToken();
this method is running fine but suddenly it starts to give error.
Possible reasons:
1) I was having a similar problem caused by the time on my server being incorrect. Make sure your system clock is synchronized.
2) You should reuse the access token you get after the first successful authentication. You will get an invalid_grant error if your previous token has not expired yet. Cache it somewhere so you can reuse it.
3) Make sure that you pass the access token, and not refresh token as that fails. When you run, it turns the OAUth2 refresh token into an access token and passes that to the service. If you pass the raw refresh token, this is not acceptable for API access without turning it into a short-lived access token.
4) You might have reached the refresh token limit. Certain Google APIs have this, some explanation you can find here: https://developers.google.com/compute/docs/authentication
5) You also can revoke it. Go to your Google API Console ( https://code.google.com/apis/console/ ) and revoke your Client Secret under Client ID for installed applications. Be sure to also update your code with the new Client Secret
My problem is as follows :
I have an application protected by a mobile security test involving a LDAP server. The corresponding realm is called LDAPrealm. I use the form-based authenticator + custom LDAP login module.
When the connection to the worklight server is lost and then re-established, I see that the current user is not authenticated in the LDAP realm anymore.
What I want is be able to re authenticate the user without having him enter credentials again.
However, since the user is still authenticated for other realms included by default in the mobile security test, the worklight server does not challenge the client again for credentials, which is causing j_security_check error when trying to submit credentials.
As a side note those credentials are stored in the encrypted json store for offline authentication and use of the app.
So my question is :
Is it possible to force the server to challenge the client again for this LDAPrealm and use submitLoginForm to re-log in?
More generally, is there a way to clear a user+device from all realms before trying to log in again?
Edit reasons : previous error was caused by a typo
In the case where the user first logs in online then loses connection then get connection again, calling
WL.Client.logout("LDAPRealm",{onSuccess:stealthed_relog});
and calling WL.Client.connect() later in stealthed_relog before sending credentials seems to wield the desired behaviour.
However, when the user logs in offline and then gets connection, when I try to use WL.Client.connect(), it says another instance of WL.Client.connect has already been called.
edit : for the log offline case, the application get challenged automatically shortly after that the connected event fires (cause of heartbeat? I do not really know), so you just have to use
login_clientside.submitLoginForm();
to successfully log in again.
If someone has a better way to implement auto-reconnecting in worklight with ldap server, feel free to post it and I'll unaccept my answer.
While debugging, we observe following behavior:
1) When trying to get encryption key from server then error on both (iOS or Android) platform
response [https://xxxx.xxxx.com:443/worklight/apps/services/random]
success: Exception thrown by application class
'com.ibm.ws.webcontainer.session.impl.HttpSessionContextImpl.checkSecurity():685'
SESN0008E: A user authenticated as anonymous has
attempted to access a session owned by user:NewRealm/CN=test
user,OU=Temporary Users,OU=Acc,DC=xxxx,DC=com.
2) When trying to read a stored value error on android is [Logcat]
Android Message: Uncaught 9 at
file:///data/data/com.xxxx.xxxxapp/files/www/default/wlclient/js/encryptedcache.js:63
Where try to call WL.EncryptedCache.read
Worklight version used is 5.0.5 Consumer Edition (with Oracle 11i) on
Windows 2008 R2
WebSphere Liberty profile
Worklight server is sitting behind IBM Datapower XI52. All SSL calls to the server are going via DP.
Authenticator - WebSphereFormBasedAuthenticator & LoginModule - WASLTPAModule
The following is not really an answer, since I'm not familiar with authentication (LTPA, FormBasedAuth, Data Power, etc.)... just a couple of comments that could help you debug/isolate the issue.
Looks like a problem with authentication:
A user authenticated as anonymous has attempted to access a session
owned by user:NewRealm/CN=test user,OU=Temporary
Users,OU=Acc,DC=xxxx,DC=com.
Not with the Encrypted Offline Cache (EOC).
EOC will try to get a random token calling the following function:
WL.EncryptedCache.secureRandom(function (data) {
console.log(data);
});
It should output something like this:
response [/apps/services/random] success: 9053bdcfd902aac3dfb59a9874c9cf55223b7d17
9053bdcfd902aac3dfb59a9874c9cf55223b7d17
You can view the functions source code typing the following in a JS console:
WL.EncryptedCache.secureRandom
If you're using Google Chrome developer tools there's a checkbox for Log XMLHttpRequests when you click on the gear icon > General > Console.
You can also try to request the URL directly. Assuming the host is localhost, port is 10080 and project name is wlproj:
http://localhost:10080/wlproj/apps/services/random
9053bdcfd902aac3dfb59a9874c9cf55223b7d17
You can view HTTP traffic with Wireshark or Charles Proxy.
I imagine this will fix the EOC issue for you, if you don't mind generating the random token locally (less security, AFAIK):
WL.EncryptedCache.secureRandom = function(callback){callback(Math.random()+"")}
For example:
Notice it never goes to the server, everything is done locally.
A user authenticated as anonymous has attempted to access a session owned by user:NewRealm/CN=test user,OU=Temporary Users,OU=Acc,DC=xxxx,DC=com.
This usually means that there is a conflict with the session sent by the user (the session cookie) belongs to a user (in this case), but the LTPA token sent as a cookie was not sent or was not valid. There could be a few causes of this. This best way is to do a trace between datapower and the worklight server to make sure an LTPA token is even being sent to the worklight server. If it is, verify all of the LTPA requirements are met (synchronized time, same private key on both machines).