AWS Cognito User Pools with mobile SDK for iOS using custom challenge
I was integrating AWS Cognito user pool to an iOS application. The sign-in feature is using a custom challenge for authentication, but there is a lack of documentation about how to use the iOS SDK. After many trial and errors, I have finally able to sign in success, so I’m going to document the steps as shown below:
Step 1: Create a CognitoUserPool
In AppDelegate, after didFinishLaunchingWithOptions, the user pool is initialised.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// setup service configuration
let serviceConfiguration = AWSServiceConfiguration(region: CognitoIdentityUserPoolRegion, credentialsProvider: nil
// create pool configuration
let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: CognitoIdentityUserPoolAppClientId, clientSecret: nil, poolId: CognitoIdentityUserPoolId)
// initialize user pool client
AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
// fetch the user pool client we initialized in above step
let pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)
self.storyboard = UIStoryboard(name: “Main”, bundle: nil)
pool.delegate = self
return true
}
Step 2: Implement the protocol delegate
extension AppDelegate: AWSCognitoIdentityCustomAuthentication{
func didCompleteStepWithError(_ error: Error?) {
}
func getCustomChallengeDetails(_ authenticationInput: AWSCognitoIdentityCustomAuthenticationInput, customAuthCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityCustomChallengeDetails>) {
}
func startCustomAuthentication() -> AWSCognitoIdentityCustomAuthentication {
if (self.navigationController == nil) {
self.navigationController = self.storyboard?.instantiateViewController(withIdentifier: “signinController”) as? UINavigationController
}
if (self.signInViewController == nil) {
self.signInViewController = self.navigationController?.viewControllers[0] as? SignInViewController
}
DispatchQueue.main.async {
self.navigationController!.popToRootViewController(animated: true)
if (!self.navigationController!.isViewLoaded
|| self.navigationController!.view.window == nil) {
self.window?.rootViewController?.present(self.navigationController!,
animated: true,
completion: nil)
}
}
return self.signInViewController!
}
}
Step 3: Handle the custom challenge inside the sign-in view controller
extension SignInViewController: AWSCognitoIdentityCustomAuthentication {
func getCustomChallengeDetails(_ authenticationInput: AWSCognitoIdentityCustomAuthenticationInput, customAuthCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityCustomChallengeDetails>) {
let authDetails = AWSCognitoIdentityCustomChallengeDetails(challengeResponses: [“USERNAME”:”YourUserName”, “ANSWER”: “123456”])
customAuthCompletionSource.set(result: authDetails)
}
public func didCompleteStepWithError(_ error: Error?) {
DispatchQueue.main.async {
if let error = error as? NSError {
print(“error”)
} else {
print(“success”)
self.dismiss(animated: true, completion: nil)
}
}
}
}
Step 4: After sign in success, you can get the username and user attribute:
self.user?.getDetails().continueOnSuccessWith { (task) -> AnyObject? in
DispatchQueue.main.async(execute: {
self.response = task.result
// With user details
print(response)
})
return nil
}
Please let me know if you have any questions. I hope AWS could update the documentation and provide a sample example code to save us time to understand the SDK through trial and error.