Exemplos de provedores de identidade Amazon Cognito usando SDK para Swift - AWS Exemplos de código do SDK

Há mais exemplos de AWS SDK disponíveis no repositório AWS Doc SDK Examples GitHub .

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Exemplos de provedores de identidade Amazon Cognito usando SDK para Swift

Os exemplos de código a seguir mostram como realizar ações e implementar cenários comuns usando o AWS SDK para Swift com o Amazon Cognito Identity Provider.

Ações são trechos de código de programas maiores e devem ser executadas em contexto. Embora as ações mostrem como chamar perfis de serviço individuais, você pode ver as ações no contexto em seus cenários relacionados.

Cenários são exemplos de código que mostram como realizar tarefas específicas chamando várias funções dentro de um serviço ou combinadas com outros Serviços da AWS.

Cada exemplo inclui um link para o código-fonte completo, em que você pode encontrar instruções sobre como configurar e executar o código.

Ações

O código de exemplo a seguir mostra como usar AdminGetUser.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }
  • Para obter detalhes da API, consulte AdminGetUsera referência da API AWS SDK for Swift.

O código de exemplo a seguir mostra como usar AdminInitiateAuth.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }
  • Para obter detalhes da API, consulte AdminInitiateAutha referência da API AWS SDK for Swift.

O código de exemplo a seguir mostra como usar AdminRespondToAuthChallenge.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 ?? "<unknown>")") } catch { print("*** Error responding to the MFA challenge.") return } }

O código de exemplo a seguir mostra como usar AssociateSoftwareToken.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }

O código de exemplo a seguir mostra como usar ConfirmSignUp.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }
  • Para obter detalhes da API, consulte ConfirmSignUpa referência da API AWS SDK for Swift.

O código de exemplo a seguir mostra como usar ResendConfirmationCode.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }

O código de exemplo a seguir mostra como usar SignUp.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 ?? "<none available>").") 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 }
  • Para obter detalhes da API, consulte SignUpa referência da API AWS SDK for Swift.

O código de exemplo a seguir mostra como usar VerifySoftwareToken.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

import AWSCognitoIdentityProvider /// 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 } }
  • Para obter detalhes da API, consulte VerifySoftwareTokena referência da API AWS SDK for Swift.

Cenários

O código de exemplo a seguir mostra como:

  • Inscrever e confirmar um usuário com nome de usuário, senha e endereço de e-mail.

  • Configurar a autenticação multifator associando uma aplicação de MFA ao usuário.

  • Faça login usando uma senha e um código de MFA.

SDK para Swift
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no AWS Code Examples Repository.

O arquivo Package.swift.

// 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: "http-config", // 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: "AWSS3", package: "aws-sdk-swift"), .product(name: "ArgumentParser", package: "swift-argument-parser") ], path: "Sources") ] )

O arquivo de código Swift.

// 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 import AWSCognitoIdentityProvider 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" } } } /// 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 } } /// 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 ?? "<none available>").") 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 } /// 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 } } /// 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 } } /// 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 } } /// 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 } } /// 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 } } /// 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 ?? "<unknown>")") } catch { print("*** Error responding to the MFA challenge.") return } } /// 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) } } }