I'm using Adapter-based authentication in native iOS applications to connect my native ios application (swift) to the Mobilefirst server (7.0).
The mechanism of authentication is working fine but the problem comes when the session expires after 10 minutes.
Here you can see the part of the code where I handle the authentication and the session timeout:
override func isCustomResponse(response: WLResponse!) -> Bool {
if response != nil && response.responseJSON != nil {
let responseJson: NSDictionary = response.responseJSON as NSDictionary
if responseJson.objectForKey("authRequired") != nil{
return responseJson.objectForKey("authRequired") as! Bool
}
}
return false
}
override func handleChallenge(response: WLResponse!) {
NSLog("A login form should appear")
if self.vc.navigationController?.visibleViewController!.isKindOfClass(LoginViewController) == true {
NSLog("Already the login form")
dispatch_async(dispatch_get_main_queue()) {
let loginController : LoginViewController! = self.vc.navigationController?.visibleViewController as? LoginViewController
let myInvocationData = WLProcedureInvocationData(adapterName: "AuthenticationJavaAdapter", procedureName: "authenticate")
myInvocationData.parameters = [loginController.userID, loginController.userPass]
self.submitAdapterAuthentication(myInvocationData, options: nil)
}
} else if (self.vc.navigationController?.visibleViewController!.isKindOfClass(SignUpViewController) == true) {
NSLog("Already the signup form")
dispatch_async(dispatch_get_main_queue()) {
NSLog("AuthenticationJavaAdapter")
let sigupController : SignUpViewController! = self.vc.navigationController?.visibleViewController as? SignUpViewController
let myInvocationData = WLProcedureInvocationData(adapterName: "AuthenticationJavaAdapter", procedureName: "authenticate")
myInvocationData.parameters = [sigupController.userID, sigupController.userPass]
self.submitAdapterAuthentication(myInvocationData, options: nil)
}
}else { //TEST
NSLog("A login form is not there yet")
//After 10 minutes this will execute, it will perform a unwind segue to the login
//timeOutController is a global var declared in LoginViewController
timeOutController.performSegueWithIdentifier("logOutDueToTimeOut", sender: nil)
}
}
When the session expires being the application in background and then comes back to foreground and calls a protected adapter, this part of code is executed:
timeOutController.performSegueWithIdentifier("logOutDueToTimeOut", sender: nil)
The login view loads with success and I can submit again the credentials to login in. The problem is that my application is not longer able to authenticate to the Mobilefirst server, getting this error:
[DEBUG] [WL_REQUEST] -[WLRequest requestFinished:] in WLRequest.m:385 :: no token present
2016-05-13 12:58:29.241 BNNDesignCollection[46327:318014] [DEBUG] [WL_PUSH] -[WLPush updateToken:] in WLPush.m:410 :: Server token is (null)
....
....
....
2016-05-13 12:58:29.352 BNNDesignCollection[46327:318014] [DEBUG] [WL_AFHTTPCLIENTWRAPPER_PACKAGE] -[WLAFHTTPClientWrapper requestFailed:error:] in WLAFHTTPClientWrapper.m:335 :: Response Status Code : 403
2016-05-13 12:58:29.352 BNNDesignCollection[46327:318014] [DEBUG] [WL_AFHTTPCLIENTWRAPPER_PACKAGE] -[WLAFHTTPClientWrapper requestFailed:error:] in WLAFHTTPClientWrapper.m:336 :: Response Error : Expected status code in (200-299), got 403
It seems that the request does not have a token or is invalid, but I don't get the "authrequired" field in the JSON response so that i can't authenticate again as I did the first time the application authenticates before any Mobilefirst session timeout.
The detailed step by step execution is this one:
Any ideas on how to handle this?
There are several problems that I can see with your authentication flow.
login
API to trigger the challenge. Your handleChallenge
should then display the login screen.handleChallenge
automatically submits the credentials if the LoginViewController
view controller is already on screen. What if the user enters incorrect credentials? Wouldn't it send the bad credentials in a loop? Usually, if LoginViewController
is already on-screen, you just want to update the UI, for example "wrong credentials, try again".submitAdapterAuthentication
. A challenge should not trigger submitAdapterAuthentication
.handleChallenge
is called, you cannot attempt to make any other protected requests or trigger some other challenge. Regarding your specific issue, this is what I think happens after the timeout:
handleChallenge
is called, which opens the login screen.If you follow the comments I wrote above, you should be OK. But it will require some architectural changes to your application. The order in which events happen is important:
handleChallenge
shows the login form.submitAdapterAuthentication
It does not matter if it's the first run, pre-emptive or after time out, make sure you follow the order of operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With