diff --git a/.doc_gen/metadata/cognito-identity-provider_metadata.yaml b/.doc_gen/metadata/cognito-identity-provider_metadata.yaml
index c53fb773998..2d04ef9b80f 100644
--- a/.doc_gen/metadata/cognito-identity-provider_metadata.yaml
+++ b/.doc_gen/metadata/cognito-identity-provider_metadata.yaml
@@ -163,6 +163,15 @@ cognito-identity-provider_SignUp:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.signup
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.SignUp
services:
cognito-identity-provider: {SignUp}
cognito-identity-provider_AdminGetUser:
@@ -223,6 +232,15 @@ cognito-identity-provider_AdminGetUser:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.admin_get_user
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.AdminGetUser
services:
cognito-identity-provider: {AdminGetUser}
cognito-identity-provider_ResendConfirmationCode:
@@ -283,6 +301,15 @@ cognito-identity-provider_ResendConfirmationCode:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.resend_confirmation
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.ResendConfirmationCode
services:
cognito-identity-provider: {ResendConfirmationCode}
cognito-identity-provider_ConfirmSignUp:
@@ -343,6 +370,15 @@ cognito-identity-provider_ConfirmSignUp:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.confirm_signup
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.ConfirmSignUp
services:
cognito-identity-provider: {ConfirmSignUp}
cognito-identity-provider_ListUsers:
@@ -453,6 +489,15 @@ cognito-identity-provider_AdminInitiateAuth:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.admin_initiate_auth
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.AdminInitiateAuth
services:
cognito-identity-provider: {AdminInitiateAuth}
cognito-identity-provider_AssociateSoftwareToken:
@@ -513,6 +558,15 @@ cognito-identity-provider_AssociateSoftwareToken:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.associate_software_token
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.AssociateSoftwareToken
services:
cognito-identity-provider: {AssociateSoftwareToken}
cognito-identity-provider_VerifySoftwareToken:
@@ -573,6 +627,15 @@ cognito-identity-provider_VerifySoftwareToken:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.verify_software_token
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.VerifySoftwareToken
services:
cognito-identity-provider: {VerifySoftwareToken}
cognito-identity-provider_AdminRespondToAuthChallenge:
@@ -633,6 +696,15 @@ cognito-identity-provider_AdminRespondToAuthChallenge:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.cognito.cognito_client
- cpp.example_code.cognito.admin_respond_to_auth_challenge
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description:
+ snippet_tags:
+ - swift.cognito-identity-provider.import
+ - swift.cognito-identity-provider.AdminRespondToAuthChallenge
services:
cognito-identity-provider: {AdminRespondToAuthChallenge}
cognito-identity-provider_ConfirmDevice:
@@ -947,6 +1019,17 @@ cognito-identity-provider_Scenario_SignUpUserWithMfa:
snippet_tags:
- cpp.example_code.cognito.client_configuration
- cpp.example_code.getting_started_with_user_pools
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/cognito-identity-provider
+ excerpts:
+ - description: The Package.swift file.
+ snippet_tags:
+ - swift.cognito-identity-provider.scenario.package
+ - description: The Swift code file.
+ snippet_tags:
+ - swift.cognito-identity-provider.scenario
services:
cognito-identity-provider: {ConfirmSignUp, ConfirmDevice, AssociateSoftwareToken, AdminGetUser, ListUsers, ResendConfirmationCode,
RespondToAuthChallenge, AdminRespondToAuthChallenge, SignUp, InitiateAuth, AdminInitiateAuth, VerifySoftwareToken}
diff --git a/swift/example_code/cognito-identity-provider/README.md b/swift/example_code/cognito-identity-provider/README.md
new file mode 100644
index 00000000000..86fbbdabe62
--- /dev/null
+++ b/swift/example_code/cognito-identity-provider/README.md
@@ -0,0 +1,118 @@
+# Amazon Cognito Identity Provider code examples for the SDK for Swift
+
+## Overview
+
+Shows how to use the AWS SDK for Swift to work with Amazon Cognito Identity Provider.
+
+
+
+
+_Amazon Cognito Identity Provider handles user authentication and authorization for your web and mobile apps._
+
+## ⚠ Important
+
+* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
+* Running the tests might result in charges to your AWS account.
+* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
+* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
+
+
+
+
+## Code examples
+
+### Prerequisites
+
+For prerequisites, see the [README](../../README.md#Prerequisites) in the `swift` folder.
+
+
+
+
+
+### Single actions
+
+Code excerpts that show you how to call individual service functions.
+
+- [AdminGetUser](scenario/Sources/entry.swift#L98)
+- [AdminInitiateAuth](scenario/Sources/entry.swift#L247)
+- [AdminRespondToAuthChallenge](scenario/Sources/entry.swift#L377)
+- [AssociateSoftwareToken](scenario/Sources/entry.swift#L298)
+- [ConfirmSignUp](scenario/Sources/entry.swift#L215)
+- [ResendConfirmationCode](scenario/Sources/entry.swift#L180)
+- [SignUp](scenario/Sources/entry.swift#L131)
+- [VerifySoftwareToken](scenario/Sources/entry.swift#L334)
+
+### Scenarios
+
+Code examples that show you how to accomplish a specific task by calling multiple
+functions within the same service.
+
+- [Sign up a user with a user pool that requires MFA](scenario/Package.swift)
+
+
+
+
+
+## Run the examples
+
+### Instructions
+
+To build any of these examples from a terminal window, navigate into its
+directory, then use the following command:
+
+```
+$ swift build
+```
+
+To build one of these examples in Xcode, navigate to the example's directory
+(such as the `ListUsers` directory, to build that example). Then type `xed.`
+to open the example directory in Xcode. You can then use standard Xcode build
+and run commands.
+
+
+
+
+
+
+#### Sign up a user with a user pool that requires MFA
+
+This example shows you how to do the following:
+
+- Sign up and confirm a user with a username, password, and email address.
+- Set up multi-factor authentication by associating an MFA application with the user.
+- Sign in by using a password and an MFA code.
+
+
+
+
+
+
+
+
+### Tests
+
+⚠ Running tests might result in charges to your AWS account.
+
+
+To find instructions for running these tests, see the [README](../../README.md#Tests)
+in the `swift` folder.
+
+
+
+
+
+
+## Additional resources
+
+- [Amazon Cognito Identity Provider Developer Guide](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html)
+- [Amazon Cognito Identity Provider API Reference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)
+- [SDK for Swift Amazon Cognito Identity Provider reference](https://sdk.amazonaws.com/swift/api/awscognitoidentityprovider/latest/documentation/awscognitoidentityprovider)
+
+
+
+
+---
+
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/swift/example_code/cognito-identity-provider/scenario/Package.swift b/swift/example_code/cognito-identity-provider/scenario/Package.swift
new file mode 100644
index 00000000000..ef3fa21c2a8
--- /dev/null
+++ b/swift/example_code/cognito-identity-provider/scenario/Package.swift
@@ -0,0 +1,47 @@
+// swift-tools-version: 5.9
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// (swift-tools-version has two lines here because it needs to be the first
+// line in the file, but it should also appear in the snippet below)
+//
+// snippet-start:[swift.cognito-identity-provider.scenario.package]
+// swift-tools-version: 5.9
+//
+// The swift-tools-version declares the minimum version of Swift required to
+// build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "cognito-scenario",
+ // Let Xcode know the minimum Apple platforms supported.
+ platforms: [
+ .macOS(.v13),
+ .iOS(.v15)
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ .package(
+ url: "https://github.com/awslabs/aws-sdk-swift",
+ from: "1.0.0"),
+ .package(
+ url: "https://github.com/apple/swift-argument-parser.git",
+ branch: "main"
+ )
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products
+ // from dependencies.
+ .executableTarget(
+ name: "cognito-scenario",
+ dependencies: [
+ .product(name: "AWSCognitoIdentityProvider", package: "aws-sdk-swift"),
+ .product(name: "ArgumentParser", package: "swift-argument-parser")
+ ],
+ path: "Sources")
+
+ ]
+)
+// snippet-end:[swift.cognito-identity-provider.scenario.package]
diff --git a/swift/example_code/cognito-identity-provider/scenario/Sources/entry.swift b/swift/example_code/cognito-identity-provider/scenario/Sources/entry.swift
new file mode 100644
index 00000000000..a38f5511f99
--- /dev/null
+++ b/swift/example_code/cognito-identity-provider/scenario/Sources/entry.swift
@@ -0,0 +1,568 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// snippet-start:[swift.cognito-identity-provider.scenario]
+// An example demonstrating various features of Amazon Cognito. Before running
+// this Swift code example, set up your development environment, including
+// your credentials.
+//
+// For more information, see the following documentation:
+// https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html
+//
+// TIP: To set up the required user pool, run the AWS Cloud Development Kit
+// (AWS CDK) script provided in this GitHub repo at
+// resources/cdk/cognito_scenario_user_pool_with_mfa.
+//
+// This example performs the following functions:
+//
+// 1. Invokes the signUp method to sign up a user.
+// 2. Invokes the adminGetUser method to get the user's confirmation status.
+// 3. Invokes the ResendConfirmationCode method if the user requested another
+// code.
+// 4. Invokes the confirmSignUp method.
+// 5. Invokes the initiateAuth to sign in. This results in being prompted to
+// set up TOTP (time-based one-time password). (The response is
+// “ChallengeName”: “MFA_SETUP”).
+// 6. Invokes the AssociateSoftwareToken method to generate a TOTP MFA private
+// key. This can be used with Google Authenticator.
+// 7. Invokes the VerifySoftwareToken method to verify the TOTP and register
+// for MFA.
+// 8. Invokes the AdminInitiateAuth to sign in again. This results in being
+// prompted to submit a TOTP (Response: “ChallengeName”:
+// “SOFTWARE_TOKEN_MFA”).
+// 9. Invokes the AdminRespondToAuthChallenge to get back a token.
+
+import ArgumentParser
+import AWSClientRuntime
+import Foundation
+
+// snippet-start:[swift.cognito-identity-provider.import]
+import AWSCognitoIdentityProvider
+// snippet-end:[swift.cognito-identity-provider.import]
+
+struct ExampleCommand: ParsableCommand {
+ @Argument(help: "The application clientId.")
+ var clientId: String
+ @Argument(help: "The user pool ID to use.")
+ var poolId: String
+ @Option(help: "Name of the Amazon Region to use")
+ var region = "us-east-1"
+
+ static var configuration = CommandConfiguration(
+ commandName: "cognito-scenario",
+ abstract: """
+ Demonstrates various features of Amazon Cognito.
+ """,
+ discussion: """
+ """
+ )
+
+ /// Prompt for an input string of at least a minimum length.
+ ///
+ /// - Parameters:
+ /// - prompt: The prompt string to display.
+ /// - minLength: The minimum number of characters to allow in the
+ /// response. Default value is 0.
+ ///
+ /// - Returns: The entered string.
+ func stringRequest(_ prompt: String, minLength: Int = 1) -> String {
+ while true {
+ print(prompt, terminator: "")
+ let str = readLine()
+
+ guard let str else {
+ continue
+ }
+ if str.count >= minLength {
+ return str
+ } else {
+ print("*** Response must be at least \(minLength) character(s) long.")
+ }
+ }
+ }
+
+ /// Ask a yes/no question.
+ ///
+ /// - Parameter prompt: A prompt string to print.
+ ///
+ /// - Returns: `true` if the user answered "Y", otherwise `false`.
+ func yesNoRequest(_ prompt: String) -> Bool {
+ while true {
+ let answer = stringRequest(prompt).lowercased()
+ if answer == "y" || answer == "n" {
+ return answer == "y"
+ }
+ }
+ }
+
+ // snippet-start:[swift.cognito-identity-provider.AdminGetUser]
+ /// Get information about a specific user in a user pool.
+ ///
+ /// - Parameters:
+ /// - cipClient: The Amazon Cognito Identity Provider client to use.
+ /// - userName: The user to retrieve information about.
+ /// - userPoolId: The user pool to search for the specified user.
+ ///
+ /// - Returns: `true` if the user's information was successfully
+ /// retrieved. Otherwise returns `false`.
+ func adminGetUser(cipClient: CognitoIdentityProviderClient, userName: String,
+ userPoolId: String) async -> Bool {
+ do {
+ let output = try await cipClient.adminGetUser(
+ input: AdminGetUserInput(
+ userPoolId: userPoolId,
+ username: userName
+ )
+ )
+
+ guard let userStatus = output.userStatus else {
+ print("*** Unable to get the user's status.")
+ return false
+ }
+
+ print("User status: \(userStatus)")
+ return true
+ } catch {
+ return false
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.AdminGetUser]
+
+ // snippet-start:[swift.cognito-identity-provider.SignUp]
+ /// Create a new user in a user pool.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CognitoIdentityProviderClient` to use.
+ /// - clientId: The ID of the app client to create a user for.
+ /// - userName: The username for the new user.
+ /// - password: The new user's password.
+ /// - email: The new user's email address.
+ ///
+ /// - Returns: `true` if successful; otherwise `false`.
+ func signUp(cipClient: CognitoIdentityProviderClient, clientId: String, userName: String, password: String, email: String) async -> Bool {
+ let emailAttr = CognitoIdentityProviderClientTypes.AttributeType(
+ name: "email",
+ value: email
+ )
+
+ let userAttrsList = [emailAttr]
+
+ do {
+ _ = try await cipClient.signUp(
+ input: SignUpInput(
+ clientId: clientId,
+ password: password,
+ userAttributes: userAttrsList,
+ username: userName
+ )
+
+ )
+
+ print("=====> User \(userName) signed up.")
+ } catch _ as AWSCognitoIdentityProvider.UsernameExistsException {
+ print("*** The username \(userName) already exists. Please use a different one.")
+ return false
+ } catch let error as AWSCognitoIdentityProvider.InvalidPasswordException {
+ print("*** Error: The specified password is invalid. Reason: \(error.properties.message ?? "").")
+ return false
+ } catch _ as AWSCognitoIdentityProvider.ResourceNotFoundException {
+ print("*** Error: The specified client ID (\(clientId)) doesn't exist.")
+ return false
+ } catch {
+ print("*** Unexpected error: \(error)")
+ return false
+ }
+
+ return true
+ }
+ // snippet-end:[swift.cognito-identity-provider.SignUp]
+
+ // snippet-start:[swift.cognito-identity-provider.ResendConfirmationCode]
+ /// Requests a new confirmation code be sent to the given user's contact
+ /// method.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CognitoIdentityProviderClient` to use.
+ /// - clientId: The application client ID.
+ /// - userName: The user to resend a code for.
+ ///
+ /// - Returns: `true` if a new code was sent successfully, otherwise
+ /// `false`.
+ func resendConfirmationCode(cipClient: CognitoIdentityProviderClient, clientId: String,
+ userName: String) async -> Bool {
+ do {
+ let output = try await cipClient.resendConfirmationCode(
+ input: ResendConfirmationCodeInput(
+ clientId: clientId,
+ username: userName
+ )
+ )
+
+ guard let deliveryMedium = output.codeDeliveryDetails?.deliveryMedium else {
+ print("*** Unable to get the delivery method for the resent code.")
+ return false
+ }
+
+ print("=====> A new code has been sent by \(deliveryMedium)")
+ return true
+ } catch {
+ print("*** Unable to resend the confirmation code to user \(userName).")
+ return false
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.ResendConfirmationCode]
+
+ // snippet-start:[swift.cognito-identity-provider.ConfirmSignUp]
+ /// Submit a confirmation code for the specified user. This is the code as
+ /// entered by the user after they've received it by email or text
+ /// message.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CognitoIdentityProviderClient` to use.
+ /// - clientId: The app client ID the user is signing up for.
+ /// - userName: The username of the user whose code is being sent.
+ /// - code: The user's confirmation code.
+ ///
+ /// - Returns: `true` if the code was successfully confirmed; otherwise `false`.
+ func confirmSignUp(cipClient: CognitoIdentityProviderClient, clientId: String,
+ userName: String, code: String) async -> Bool {
+ do {
+ _ = try await cipClient.confirmSignUp(
+ input: ConfirmSignUpInput(
+ clientId: clientId,
+ confirmationCode: code,
+ username: userName
+ )
+ )
+
+ print("=====> \(userName) has been confirmed.")
+ return true
+ } catch {
+ print("=====> \(userName)'s code was entered incorrectly.")
+ return false
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.ConfirmSignUp]
+
+ // snippet-start:[swift.cognito-identity-provider.AdminInitiateAuth]
+ /// Begin an authentication session.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CongitoIdentityProviderClient` to use.
+ /// - clientId: The app client ID to use.
+ /// - userName: The username to check.
+ /// - password: The user's password.
+ /// - userPoolId: The user pool to use.
+ ///
+ /// - Returns: The session token associated with this authentication
+ /// session.
+ func initiateAuth(cipClient: CognitoIdentityProviderClient, clientId: String,
+ userName: String, password: String,
+ userPoolId: String) async -> String? {
+ var authParams: [String: String] = [:]
+
+ authParams["USERNAME"] = userName
+ authParams["PASSWORD"] = password
+
+ do {
+ let output = try await cipClient.adminInitiateAuth(
+ input: AdminInitiateAuthInput(
+ authFlow: CognitoIdentityProviderClientTypes.AuthFlowType.adminUserPasswordAuth,
+ authParameters: authParams,
+ clientId: clientId,
+ userPoolId: userPoolId
+ )
+ )
+
+ guard let challengeName = output.challengeName else {
+ print("*** Invalid response from the auth service.")
+ return nil
+ }
+
+ print("=====> Response challenge is \(challengeName)")
+
+ return output.session
+ } catch _ as UserNotFoundException {
+ print("*** The specified username, \(userName), doesn't exist.")
+ return nil
+ } catch _ as UserNotConfirmedException {
+ print("*** The user \(userName) has not been confirmed.")
+ return nil
+ } catch {
+ print("*** An unexpected error occurred.")
+ return nil
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.AdminInitiateAuth]
+
+ // snippet-start:[swift.cognito-identity-provider.AssociateSoftwareToken]
+ /// Request and display an MFA secret token that the user should enter
+ /// into their authenticator to set it up for the user account.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CognitoIdentityProviderClient` to use.
+ /// - authSession: The authentication session to request an MFA secret
+ /// for.
+ ///
+ /// - Returns: A string containing the MFA secret token that should be
+ /// entered into the authenticator software.
+ func getSecretForAppMFA(cipClient: CognitoIdentityProviderClient, authSession: String?) async -> String? {
+ do {
+ let output = try await cipClient.associateSoftwareToken(
+ input: AssociateSoftwareTokenInput(
+ session: authSession
+ )
+ )
+
+ guard let secretCode = output.secretCode else {
+ print("*** Unable to get the secret code")
+ return nil
+ }
+
+ print("=====> Enter this token into Google Authenticator: \(secretCode)")
+ return output.session
+ } catch _ as SoftwareTokenMFANotFoundException {
+ print("*** The specified user pool isn't configured for MFA.")
+ return nil
+ } catch {
+ print("*** An unexpected error occurred getting the secret for the app's MFA.")
+ return nil
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.AssociateSoftwareToken]
+
+ // snippet-start:[swift.cognito-identity-provider.VerifySoftwareToken]
+ /// Confirm that the user's TOTP authenticator is configured correctly by
+ /// sending a code to it to check that it matches successfully.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CongnitoIdentityProviderClient` to use.
+ /// - session: An authentication session previously returned by an
+ /// `associateSoftwareToken()` call.
+ /// - mfaCode: The 6-digit code currently displayed by the user's
+ /// authenticator, as provided by the user.
+ func verifyTOTP(cipClient: CognitoIdentityProviderClient, session: String?, mfaCode: String?) async {
+ do {
+ let output = try await cipClient.verifySoftwareToken(
+ input: VerifySoftwareTokenInput(
+ session: session,
+ userCode: mfaCode
+ )
+ )
+
+ guard let tokenStatus = output.status else {
+ print("*** Unable to get the token's status.")
+ return
+ }
+ print("=====> The token's status is: \(tokenStatus)")
+ } catch _ as SoftwareTokenMFANotFoundException {
+ print("*** The specified user pool isn't configured for MFA.")
+ return
+ } catch _ as CodeMismatchException {
+ print("*** The specified MFA code doesn't match the expected value.")
+ return
+ } catch _ as UserNotFoundException {
+ print("*** The specified username doesn't exist.")
+ return
+ } catch _ as UserNotConfirmedException {
+ print("*** The user has not been confirmed.")
+ return
+ } catch {
+ print("*** Error verifying the MFA token!")
+ return
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.VerifySoftwareToken]
+
+ // snippet-start:[swift.cognito-identity-provider.AdminRespondToAuthChallenge]
+ /// Respond to the authentication challenge received from Cognito after
+ /// initiating an authentication session. This involves sending a current
+ /// MFA code to the service.
+ ///
+ /// - Parameters:
+ /// - cipClient: The `CognitoIdentityProviderClient` to use.
+ /// - userName: The user's username.
+ /// - clientId: The app client ID.
+ /// - userPoolId: The user pool to sign into.
+ /// - mfaCode: The 6-digit MFA code currently displayed by the user's
+ /// authenticator.
+ /// - session: The authentication session to continue processing.
+ func adminRespondToAuthChallenge(cipClient: CognitoIdentityProviderClient, userName: String,
+ clientId: String, userPoolId: String, mfaCode: String,
+ session: String) async {
+ print("=====> SOFTWARE_TOKEN_MFA challenge is generated...")
+
+ var challengeResponsesOb: [String: String] = [:]
+ challengeResponsesOb["USERNAME"] = userName
+ challengeResponsesOb["SOFTWARE_TOKEN_MFA_CODE"] = mfaCode
+
+ do {
+ let output = try await cipClient.adminRespondToAuthChallenge(
+ input: AdminRespondToAuthChallengeInput(
+ challengeName: CognitoIdentityProviderClientTypes.ChallengeNameType.softwareTokenMfa,
+ challengeResponses: challengeResponsesOb,
+ clientId: clientId,
+ session: session,
+ userPoolId: userPoolId
+ )
+ )
+
+ guard let authenticationResult = output.authenticationResult else {
+ print("*** Unable to get authentication result.")
+ return
+ }
+
+ print("=====> Authentication result (JWTs are redacted):")
+ print(authenticationResult)
+ } catch _ as SoftwareTokenMFANotFoundException {
+ print("*** The specified user pool isn't configured for MFA.")
+ return
+ } catch _ as CodeMismatchException {
+ print("*** The specified MFA code doesn't match the expected value.")
+ return
+ } catch _ as UserNotFoundException {
+ print("*** The specified username, \(userName), doesn't exist.")
+ return
+ } catch _ as UserNotConfirmedException {
+ print("*** The user \(userName) has not been confirmed.")
+ return
+ } catch let error as NotAuthorizedException {
+ print("*** Unauthorized access. Reason: \(error.properties.message ?? "")")
+ } catch {
+ print("*** Error responding to the MFA challenge.")
+ return
+ }
+ }
+ // snippet-end:[swift.cognito-identity-provider.AdminRespondToAuthChallenge]
+
+ /// Called by ``main()`` to run the bulk of the example.
+ func runAsync() async throws {
+ let config = try await CognitoIdentityProviderClient.CognitoIdentityProviderClientConfiguration(region: region)
+ let cipClient = CognitoIdentityProviderClient(config: config)
+
+ print("""
+ This example collects information about a user, then creates that user in the
+ specified user pool. Then, it enables Multi-Factor Authentication (MFA) for that
+ user by associating an authenticator application (such as Google Authenticator
+ or a password manager that supports TOTP). Then, the user uses a code from their
+ authenticator application to sign in.
+
+ """)
+
+ let userName = stringRequest("Please enter a new username: ")
+ let password = stringRequest("Enter a password: ")
+ let email = stringRequest("Enter your email address: ", minLength: 5)
+
+ // Submit the sign-up request to AWS.
+
+ print("==> Signing up user \(userName)...")
+ if await signUp(cipClient: cipClient, clientId: clientId,
+ userName: userName, password: password,
+ email: email) == false {
+ return
+ }
+
+ // Check the user's status. This time, it should come back "unconfirmed".
+
+ print("==> Getting the status of user \(userName) from the user pool (should be 'unconfirmed')...")
+ if await adminGetUser(cipClient: cipClient, userName: userName, userPoolId: poolId) == false {
+ return
+ }
+
+ // Ask the user if they want a replacement code sent, such as if the
+ // code hasn't arrived yet. If the user responds with a "yes," send a
+ // new code.
+
+ if yesNoRequest("==> A confirmation code was sent to \(userName). Would you like to send a new code (Y/N)? ") {
+ print("==> Sending a new confirmation code...")
+ if await resendConfirmationCode(cipClient: cipClient, clientId: clientId, userName: userName) == false {
+ return
+ }
+ }
+
+ // Ask the user to enter the confirmation code, then send it to Amazon
+ // Cognito to verify it.
+
+ let code = stringRequest("==> Enter the confirmation code sent to \(userName): ")
+ if await confirmSignUp(cipClient: cipClient, clientId: clientId, userName: userName, code: code) == false {
+ // The code didn't match. Your application may wish to offer to
+ // re-send the confirmation code here and try again.
+ return
+ }
+
+ // Check the user's status again. This time it should come back
+ // "confirmed".
+
+ print("==> Rechecking status of user \(userName) in the user pool (should be 'confirmed')...")
+ if await adminGetUser(cipClient: cipClient, userName: userName, userPoolId: poolId) == false {
+ return
+ }
+ // Check the challenge mode. Here, it should be "mfaSetup", indicating
+ // that the user needs to add MFA before using it. This returns a
+ // session that can be used to register MFA, or nil if an error occurs.
+
+ let authSession = await initiateAuth(cipClient: cipClient, clientId: clientId,
+ userName: userName, password: password,
+ userPoolId: poolId)
+ if authSession == nil {
+ return
+ }
+
+ // Ask Cognito for an MFA secret token that the user should enter into
+ // their authenticator software (such as Google Authenticator) or
+ // password manager to configure it for this user account. This
+ // returns a new session that should be used for the new stage of the
+ // authentication process.
+
+ let newSession = await getSecretForAppMFA(cipClient: cipClient, authSession: authSession)
+ if newSession == nil {
+ return
+ }
+
+ // Ask the user to enter the current 6-digit code displayed by their
+ // authenticator. Then verify that it matches the value expected for
+ // the session.
+
+ let mfaCode1 = stringRequest("==> Enter the 6-digit code displayed in your authenticator: ",
+ minLength: 6)
+ await verifyTOTP(cipClient: cipClient, session: newSession, mfaCode: mfaCode1)
+
+ // Ask the user to authenticate now that the authenticator has been
+ // configured. This creates a new session using the user's username
+ // and password as already entered.
+
+ print("\nNow starting the sign-in process for user \(userName)...\n")
+
+ let session2 = await initiateAuth(cipClient: cipClient, clientId: clientId,
+ userName: userName, password: password, userPoolId: poolId)
+ guard let session2 else {
+ return
+ }
+
+ // Now that we have a new auth session, `session2`, ask the user for a
+ // new 6-digit code from their authenticator, and send it to the auth
+ // session.
+
+ let mfaCode2 = stringRequest("==> Wait for your authenticator to show a new 6-digit code, then enter it: ",
+ minLength: 6)
+ await adminRespondToAuthChallenge(cipClient: cipClient, userName: userName,
+ clientId: clientId, userPoolId: poolId,
+ mfaCode: mfaCode2, session: session2)
+ }
+}
+
+/// The program's asynchronous entry point.
+@main
+struct Main {
+ static func main() async {
+ let args = Array(CommandLine.arguments.dropFirst())
+
+ do {
+ let command = try ExampleCommand.parse(args)
+ try await command.runAsync()
+ } catch {
+ ExampleCommand.exit(withError: error)
+ }
+ }
+}
+// snippet-end:[swift.cognito-identity-provider.scenario]
diff --git a/swift/example_code/cognito-identity-provider/scenario/test.sh b/swift/example_code/cognito-identity-provider/scenario/test.sh
new file mode 100755
index 00000000000..e69de29bb2d