Mobilefirst server returns 403 error after processing session timeout in iOS application

I use adapter based authentication in apps with native iOS to connect my iOS app (swift) to the Mobilefirst server (7.0),

The authentication mechanism works fine, but the problem occurs when the session expires after 10 minutes.

Here you can see the part of the code where I handle authentication and 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, when the application is in the background, and then returns to the foreground and calls the protected adapter, this part of the code is executed:

 timeOutController.performSegueWithIdentifier("logOutDueToTimeOut", sender: nil) 

The login is loading with great success, and I can send the credentials for the login again. The problem is that my application can no longer authenticate to the Mobilefirst server by receiving 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 

The request does not seem to have a token or is invalid, but I do not receive the "authrequired" field in the JSON response, so I cannot authenticate again, as it was the first time the application was authenticated before any Mobilefirst session timeout.

Detailed step-by-step execution is the following:

  • The application displays the user login screen
  • User enters credentials
  • When a secure adapter is called during this process, the mobilefirst server returns a response named "authrequired = true". The isCustomResponse method is automatically called and returns true.
  • As isCustomResponse returns true, the handleChallenge method is called and, since the login viewController is the visible viewController, the first "If" statement starts authentication.
  • Authentication completes successfully, and now the user can navigate throughout the application, accessing all of his protected resources.
  • I put the application in the background for 10 minutes (the set timeout of the MobileFirst session on the server).
  • I placed the application in the foreground and started navigation again.
  • When MobileFirst expires, as soon as I try to call the secure adapter again, the mobilefirst server returns a response with the name "authrequired = true". The isCustomResponse method is automatically called again and returns true.
  • As isCustomResponse returns true, the handleChallenge method is called and, since the visible viewController is NOT a loginViewController, the third "If" statement is executed, again displaying the login screen.
  • User enters credentials.
  • The server returns a 403 response. The isCustomResponse method is automatically called, but returns false, because the response does not contain the "authrequired" field.

Any ideas on how to handle this?

+5
source share
1 answer

There are several issues that I see in the authentication flow.

  • Your actions begin with "The application shows the user login screen." Are you hard-coded to run the application from the login screen? Adapter-based authentication does not support proactive authentication. The call-only value should display the login screen. The usual way to do this is to invoke a protected resource at application startup time or use the login API to launch a call. Then your handleChallenge should display a login screen.
  • "How a secure adapter is invoked during this process." You invoke a secure resource in the middle of an authentication flow. Not good. Do not do that.
  • Your handleChallenge automatically sends credentials if the LoginViewController display controller is already on the screen. What if the user enters incorrect credentials? Wouldn't he send bad credentials in a loop? Usually, if the LoginViewController already on the screen, you just want to update the user interface, for example, "incorrect credentials, try again."
  • Clicking the login button should be what submitAdapterAuthentication . The task should not run submitAdapterAuthentication .
  • Before each incoming call, you need to answer before doing anything else. Value, as soon as handleChallenge is handleChallenge , you cannot try to make any other secure requests or make any other call.

As for your specific problem, this is what I think happens after the timeout:

  • handleChallenge that opens the login screen.
  • You wrote that β€œduring this process, aβ€œ secure adapter ”is called, which you cannot do because you are in the middle of a call.
  • The application goes into an unstable state.

If you follow the comments that I wrote above, you should be fine. But your application will require some architectural changes. The order in which events occur is important:

  • Make a secure request.
  • handleChallenge shows the login form.
  • The user clicks the submit button.
  • submitAdapterAuthentication

It doesn’t matter if this is the first run, preemptive or after a timeout, make sure that you follow the order of operations.

+2
source

All Articles