3

I tried to implement all the Cognito SignUp/Confirm/SignIn Stuff in a CognitoController singleton class.

I think there are two functions where my problem probably is based:

The first function is to re-establish a session and is called from my main view controller which receives the callback and then proceeds to initialize the session or shows the signInViewController:

func handleSignInToExistingSession() {

    if AWSIdentityManager.default().identityId != nil { 
        if AWSFacebookSignInProvider.sharedInstance().token().result == nil {
            //print("AWSFacebookSignInProvider token: \(String(describing: AWSFacebookSignInProvider.sharedInstance().token().result))")
            AWSFacebookSignInProvider.sharedInstance().reloadSession()
            //print("AWSFacebookSignInProvider token reload possible: \(String(describing: AWSFacebookSignInProvider.sharedInstance().token().result))")
        }


        AWSSignInManager.sharedInstance().resumeSession(completionHandler: { (result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
            DispatchQueue.main.async(execute: {
                if error != nil {
                    self.signInExistingSessionError?(error! as NSError)
                } else if result != nil {
                    self.loginType = AWSFacebookSignInProvider.sharedInstance().isLoggedIn ? "facebook" : AWSCognitoUserPoolsSignInProvider.sharedInstance().isLoggedIn() ? "userpool" : "undefined"
                    self.signInExistingSessionCompleted?()
                }
                print("Result: \(String(describing: result)) \n Error:\(String(describing: error))")
            })
        })
    } else {
        self.signInExistingSessionError?(nil)
    }
}

The second function is to sign in a user and is called from the SignInViewController:

func handleSignInWithSignInProvider(_ signInProvider: AWSSignInProvider) {
    AWSSignInManager.sharedInstance().login(signInProviderKey: signInProvider.identityProviderName, completionHandler: {(result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
        DispatchQueue.main.async(execute: {
            if error != nil {
                self.signInError?(error! as NSError)
            } else {
                self.signInCompleted?(true)
            }
            return
        })
        //print("result = \(String(describing: result)), error = \(String(describing: error))")
    })
}

Everything works fine. But when I logout the session with this function which is called from the mainViewController:

func handleLogout() {
    if (AWSSignInManager.sharedInstance().isLoggedIn) {
        AWSSignInManager.sharedInstance().logout(completionHandler: {(result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
            DispatchQueue.main.async(execute: {
                self.presentSignedOutViewController()
                self.presentLoadingView()
            })
            //SessionController.sharedInstance.resetSession()
        })
        // print("Logout Successful: \(signInProvider.getDisplayName)");
    } else {
        assert(false)
    }
}

And try to log back in from the SignInViewController. I receive the message: "Obtaining an identity id in another thread failed or didn't complete within 5 seconds."

The full Message is: Error Domain=com.amazonaws.service.cognitoidentity.AWSCognitoCredentialsProviderHelper Code=0 "Obtaining an identity id in another thread failed or didn't complete within 5 seconds."

Then, if I tap the signInButton another time, it signs in. But the first time after logout the login won't work.

I wasn't able to find any information on this error message that made sense to me.

Thanks to anyone who has an idea how to fix this!

weka1
  • 737
  • 2
  • 9
  • 20

1 Answers1

2

Finally i was able to solve this problem.

The sample project that AWSMobileHub offers to help integrate the features two classes FacebookIdentityProfile and UserPoolsIdentityProfile which inherit from AWSIdentityProfile. The classes both have a function load() which is called automatically signs in with one of these providers. You are supposed to setup the user profile in this function.

What I did was calling a AWSDynamoDBObjectMapper.default().load(...) at first in this function to check if the user is already in my database and doesn't need any setup. I figured that this should work fine since it happens after the signup. And it worked fine with the initial sign in. But as soon as the user would sign out and sign back in, the AWSDynamoDBObjectMapper.default().load(...) and the cognito sign in would be executed parallel and somehow dynamodb would block cognito.

So what I had to do was moving the dynamodb request out of this function and make sure that it is not called before the sign in is finished.

weka1
  • 737
  • 2
  • 9
  • 20