(Note: this is related to this question I posted, but since my original question was answered and I am now encountering a different issue, I am posting this as a new question.)
I am setting up registration and login for an iOS app which uses DynamoDB and AWS Cognito. I eventually got the registration login process to work, but I've noticed that whenever I log out and then immediately try to log back in, the app fails to do so and I get the error message Invalid login token. Can't pass in a Cognito token. Only after I close and relaunch the app can I successfully log in again.
I primarily used this example project to set up registration, but when I was implementing the sign-in method, I had some trouble converting from Objective-C to Swift. I wasn't able to get the login process from the example to work, so I instead set up an explicit login method:
if locked { return }
trimRegistrationValues()
let name = usernameField.text!
let user = pool!.getUser(name)
lock()
user.getSession(name, password: passwordField.text!, validationData: nil, scopes: nil).continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: {
(task:AWSTask!) -> AnyObject! in
if task.error != nil {
self.sendErrorPopup("ERROR: Unable to sign in. Error description: " + task.error!.description)
} else {
print("Successful Login")
let loginKey = "cognito-idp.us-east-1.amazonaws.com/" + USER_POOL_ID
var logins = [NSString : NSString]()
self.credentialsProvider!.identityProvider.logins().continueWithBlock { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("ERROR: Unable to get logins. Description: " + task.error!.description)
} else {
if task.result != nil{
let prevLogins = task.result as! [NSString:NSString]
print("Previous logins: " + String(prevLogins))
logins = prevLogins
}
logins[loginKey] = name
let manager = IdentityProviderManager(tokens: logins)
self.credentialsProvider!.setIdentityProviderManagerOnce(manager)
self.credentialsProvider!.getIdentityId().continueWithBlock { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("ERROR: Unable to get ID. Error description: " + task.error!.description)
} else {
print("Signed in user with the following ID:")
print(task.result)
dispatch_async(dispatch_get_main_queue()){
self.performSegueWithIdentifier("mainViewControllerSegue", sender: self)
}
}
return nil
}
}
return nil
}
}
self.unlock()
return nil
})
Currently, the code in my AppDelegate class for setting up Cognito looks like this:
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId:APP_CLIENT_ID, clientSecret: APP_CLIENT_SECRET, poolId: USER_POOL_ID)
let pool = AWSCognitoIdentityUserPool(forKey:USER_POOL_NAME)
pool.delegate = self
self.storyboard = UIStoryboard(name: "Main", bundle: nil)
self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: IDENTITY_POOL_ID, identityProviderManager:pool)
let serviceConfiguration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider!)
AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: USER_POOL_NAME)
let manager = IdentityProviderManager(tokens: [NSString:NSString]())
self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: IDENTITY_POOL_ID, identityProviderManager: manager)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = serviceConfiguration
startPasswordAuthentication()
The viewDidLoad() method in the login ViewController only contains this line regarding the Cognito values I use for logging in:
if pool == nil{
pool = AWSCognitoIdentityUserPool(forKey:USER_POOL)
}
In the prepareForSegue() case from the login ViewController to the first view the user sees after logging in, I set the user by calling:
destination.user = pool!.getUser(usernameField.text!)
In the method for signing out from this view, I call user!.signOut().
I've noticed that many Cognito example projects call credentialsProvider.clearKeychain() after signing out, but this did not solve the issue for me. I've been having trouble finding many examples showing specifically how to log out through Cognito. I've also heard that AWS credentials expire after an hour after signing into an app like this. What is the proper way to handle credentials if I want to solve this problem and avoid other situations that might force my users to relaunch the app in order to sign in?