I was integrating AWS Cognito user pool to an iOS application. The sign in feature is using 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 documentations and provide sample example code to save us time to understand the sdk through trial and error.