Authentication Service throws Procedure invocation error post upgrade from MFP 6.3 to MFP 7.1 - ibm-mobilefirst

Authentication adapter throwing "Procedure invocation error" sometimes. Tried clearing cache and cookies but still the same. So we tried to login from different system for same user and it works. This is quite confusing as once we try with different ID in browser where issue occurred, it works and then it works with Member ID which has issue as well. Auth required is not coming in response when issue occurs.
we have tried to look into logs and found WorklightAuthenticationException from Authentication Adapter while trying security test procedure.
Authentication Adapter code:
var result = WL.Server.invokeHttp(input);
WL.Logger.info("Authentication service : " + JSON.stringify(result));
authResponse = prepareJSONResponse(result,channelId);
WL.Logger.info('Formatted response -> ' + JSON.stringify(authResponse));
if(result.isSuccessful == false){
WL.Logger.info("Error: " + result.errorMessage);
return onAuthRequired(null, "Error in connecting to server. Please try again later.");
}
if(typeof authResponse.errorMessage != 'undefined'){
WL.Logger.info("Error is defined" +authResponse.errorMessage);
return onAuthRequired(null, authResponse);
}
WL.Logger.info("Authentication service success: " + JSON.stringify(result));
WL.Logger.info("userIdentity Parameters: " + inputParams.CorpId);
var userIdentity = {
userId: inputParams.CorpId,
displayName: inputParams.CorpId,
attributes: {
foo: "bar"
}
};
WL.Logger.info("userIdentity::"+JSON.stringify(userIdentity));
WL.Server.setActiveUser("SingleStepAuthRealm", userIdentity);
return {
authRequired: false
};

It is happening due to the requests going from one node to another node. Handled it in Load balancer to send requests to specific node based on cookies and post that it works fine.

The description mentions about clearing cache and cookies and using browser.
Browser based environments are not supported in session independent mode. These work only in session dependent mode. As such, it is imperative that session based affinity be enabled to ensure the requests land in the same JVM for authentication state to be preserved.
More details can be found here : Session-independent mode

Related

Windows authentication fail with "401 Unauthorized"

I have a MVC client accessing a Web API protected by IDS4. They all run on my local machine and hosted by IIS. The app works fine when using local identity for authentication. But when I try to use Windows authentication, I keep getting "401 Unauthorized" error from the dev tool and the login box keeps coming back to the browser.
Here is the Windows Authentication IIS setting
and enabled providers
It's almost like that the user ID or password was wrong, but that's nearly impossible because that's the domain user ID and password I use for logging into the system all the time. Besides, according to my reading, Windows Authentication is supposed to be "automatic", which means I will be authenticated silently without a login box in the first place.
Update
I enabled the IIS request tracing and here is the result from the log:
As you can see from the trace log item #29, the authentication (with the user ID I typed in, "DOM\Jack.Backer") was successful. However, some authorization item (#48) failed after that. And here is the detail of the failed item:
What's interesting is that the ErrorCode says that the operation (whatever it is) completed successfully, but still I received a warning with a HttpStatus=401 and a HttpReason=Unauthorized. Apparently, this is what failed my Windows Authentication. But what is this authorization about and how do I fix it?
In case anyone interested - I finally figured this one out. It is because the code that I downloaded from IndentityServer4's quickstart site in late 2020 doesn't have some of the important pieces needed for Windows authentication. Here is what I had to add to the Challenge function of the ExternalController class
and here is the ProcessWindowsLoginAsync function
private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl)
{
var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
if (result?.Principal is WindowsPrincipal wp)
{
var props = new AuthenticationProperties()
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", AccountOptions.WindowsAuthenticationSchemeName },
}
};
var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));
if (AccountOptions.IncludeWindowsGroups)
{
var wi = wp.Identity as WindowsIdentity;
var groups = wi.Groups.Translate(typeof(NTAccount));
var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
id.AddClaims(roles);
}
await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props);
return Redirect(props.RedirectUri);
}
else
{
return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
}
}
Now my windows authentication works with no issues.

Unable to Register IOS device to Mobile First 8

I am able to see the iOS device under devices tab in MF, registered to my application. but pushing a notification fails with the below error:
An error occurred while the notification was sent. Internal server error. No devices found.
Upon reviewing IOS code, I noticed the below issue while invoking MFPPush.sharedInstance.registerDevice(nil)
Cannot retrieve a valid authorization header for header. Check resource and authorization server configuration.
I am using the code from the git sample. Below is the snippet throwing the error:
#IBAction func registerDevice(_ sender: AnyObject) {
print("Attempting Device registration with Mobile First")
WLAuthorizationManager.sharedInstance().obtainAccessToken(forScope: "push.mobileclient") { (token, error) -> Void in
if (error != nil) {
print("Did not recieve an access token from server: " + error.debugDescription)
} else {
WLClient.sharedInstance()?.setDeviceDisplayName("White Ipad", withCompletionHandler: { (error) in
if error == nil{
print("device display name is set")
}else{
print("error setting device name: " + error.debugDescription)
}
})
print("Recieved the following access token value: " + (token?.value ?? "no token"))
MFPPush.sharedInstance().registerDevice(nil) { (response, error) -> Void in
if error == nil {
self.enableButtons()
self.showAlert("Registered successfully with Mobile First")
print(response?.description ?? "")
} else {
self.showAlert("Registration failed with Mobile First. Error \(error?.localizedDescription)")
print(error?.localizedDescription ?? "")
}
}
}
}
}
Mobile First Config: I have followed the documentation and configured the UserLogin security check from the sample git project and have removed scope to push.mobileclient under security.
Reading the OAuth Security in MF, i understand the that token is necessary to access resources, but I am unable to figure out how to attach the token in registerDevice().
It seems to be you haven't configured Push Notifications properly in MobileFirst Server.
Make sure that you have added push.mobileclient scope in Security tab of your application. If you are not using any security check, you can add scope like below.
Check whether your application is configured valid iOS provisioning profile enabled with Push Capability
Make sure that you have uploaded valid sandbox/production certificates in Push tab of your particular app in MFP Operations Console.
More details : here
Make sure your app is enabled Push Capability in the project setting and also check you sending device token to MF Server using MFPPush.sharedInstance().sendDeviceToken(deviceToken) API in didRegisterForRemoteNotificationsWithDeviceToken method of AppDelegate file
-

Enable/Disable logging in Worklight application

We are developing a WL application using WL enterprise 6.2.0.1. We have four environments (Dev/QA/UAT and PROD).
Our application is logging the user credentials on the Server (file:SystemOut.log) which is ok for Dev environment. However, when we need to move the build to QA and UAT we need to disable the logging since it is a security point of view and we can't proceed to PROD.
What we did is we added the following code to the initOptions.js:
var bEnableConsoleLog = false; // Enable Disable the logging
var wlInitOptions = {
...
...
...
logger : {
enabled : bEnableConsoleLog},};
var disableLogging = function() {
WL.Logger.info("##### LOG ENABLED ?? => " + bEnableConsoleLog);
if (bEnableConsoleLog == false)
{
WL.Logger.config({
enabled : false,
level : 'info'
});
console.log = function() {
}.bind(console.log);
console.error = function() {
}.bind(console.error);
}
};
if (window.addEventListener) {
window.addEventListener('load', function() {
WL.Client.init(wlInitOptions);
disableLogging();
}, false);
} else if (window.attachEvent) {
window.attachEvent('onload', function() {
WL.Client.init(wlInitOptions);
disableLogging();
});
}
disableLogging();
WL.Logger
.info("######################## WL.Logger.info ENABLED ############################");
console
.log("######################## console.log ENABLED ############################");
console
.error("######################## console.error ENABLED ############################");
By Setting the value var bEnableConsoleLog = (true/false); we thought we can enable or disable the logging, but it seems still logging the credentials.
Is there a way to resolve this?
I don't think there is an 'enabled' option on WL.Logger.config based on the WL.Logger API reference. There is a 'capture' option which you can set to false, which will disable saving the client logs and sending them to the server.
If your client is logging the user credentials in a log statement then that information should only be sent based on 'capture' being true (the default) and the log statement you use being at the 'level' value or above. Given your WL.Logger.config() above, that means WL.Logger.info() would be sent to the server and WL.Logger.debug() would not. For more information see Configuring the Worklight Logger.
Note that all of this pertains only to WL.Logger calls made by the client. If you are logging the user credentials in your server-side code (for example using Java logger) then what is logged will be based on the log levels configured on the server; the client log configuration will have no effect.

IBM Worklight : WL.Client.getUserName Fails to retrieve userIdentity immediately after authentication

I have done adapter based authentication and there is no problem in authentication and it works fine. I have faced some issues in getting the active users useridentity.The code may explain you a bit more
adapterAuthRealmChallengeHandler.handleChallenge = function(response){
var authRequired = response.responseJSON.authRequired;
if (authRequired == true){
if (response.responseJSON.errorMessage)
alert(response.responseJSON.errorMessage);
} else if (authRequired == false){
adapterAuthRealmChallengeHandler.submitSuccess();
setTimeout(function(){pageTransitionCall();},10000); //this code only works
pageTransitionCall(); //This throws null error in console
}
};
function pageTransitionCall(){
console.log(WL.Client.getUserName("AdapterAuthRealm"));
}
As you can see i was trying to get the active userName of the realm. The WL.Client.getUserName("AdapterAuthRealm") only works after some time interval only and i am not sure about the time interval. By adapter code is as below
function submitAuthentication(username, password,userCred){
if (username==="worklight" && password === "worklight"){
WL.Logger.info("if");
var userIdentity = {
userId: userCred,
displayName: userCred,
attributes: {
foo: "bar"
},
loginName : userCred,
userName : userCred
};
WL.Server.setActiveUser("AdapterAuthRealm", userIdentity);
WL.Logger.info(JSON.stringify(userIdentity));
return {
authRequired: false
};
}
else
{
WL.Logger.info("else");
return onAuthRequired(null, "Invalid login credentials");
}
}
My doubt is why does the client cant retrieve the activeuser. And i am sure that my code is correct and active user is set and i can see in the server log.After the setactvieruser is set only i have return false in the adpter and why cant the client retrieve the user at instant and why it needs delay to retrieve. i have verified in both Worklight V6.0 and also Worklight V6.1.i have created the Ipad environment.
The info that contains logged in userId (basically any userIdentity data) is not returned immediately after adapter authentication but only when an original request succeeds. Consider this
You're making request#1 to the server (let's say invoke procedure)
You're getting response with authRequired:true
You're submitting auth data
You're getting authRequred:false
You're calling submitSuccess()
WL framework automatically re-invokes request#1
You're getting response for request#1
userIdentity data will be returned in step7 and not in step4. Basically once you start authentication flow you're considered out of the original invocation context. You need to finish the flow and tell WL framework that auth has completed. Once you do - WL framework will reinvoke the original request. WL server add userIdentity data to the response and WL client will update userName, displayName etc properties.
In case you need user data before that, e.g. right away once auth is complete, you can add custom properties to your submitAuthentication function response, e.g.
WL.Server.setActiveUser("AdapterAuthRealm", userIdentity);
return {
authRequired: false,
loginName: userIdentity.loginName
};
this will make sure that loginName will be returned to your handleChallenge function. you can retrieve it there and do whatever you want with it.

Login module in Titanium

Any one has experience in development of Login module with ProviderService.Src.
I need to develop a login module with the webservice using Titanium Appcelerator. It needs to take two strings (Username & Password) and return true/false. I need to send entered login and password via web service and receive true/false. The webservice is
http://46.18.8.42/FareBids.Service/FareBids.ServiceLayer.ProviderService.svc
Please some one guide me how to create a Login module with it? I got information which says me to use SUDS. Can some one help me on this with code(if possible)
Help would really be appreciated. Thanks.
Use a webservice http client. This should do it, you will have to tune this to your specific webservice and obviously collect data from the user, but how to do that is well documented in the most basic Titanium tutorials.
var loginSrv = Ti.Network.createHTTPClient({
onload : function(e) {
// If the service returns successfully : true, or false
var isUserAllowed = this.responseText;
},
onerror : function(e) {
// Web service failed for some reason
Ti.API.info(this.responseText);
Ti.API.info('webservice failed with message : ' + e.error);
}
});
loginSrv.open('POST', 'http://46.18.8.42/FareBids.Service/FareBids.ServiceLayer.ProviderService.svc');
// you may have to change the content type depending on your service
loginSrv.setRequestHeader("Content-Type", "application/json");
var sendObj = {loginid : 'someid', pwd : 'somepassword'};
loginSrv.send(obj);