diff --git a/cspell.json b/cspell.json index 8aa9138f087..c2c0df0f66b 100644 --- a/cspell.json +++ b/cspell.json @@ -1616,7 +1616,8 @@ "jamba", "webauthn", "knowledgebases", - "rehype" + "rehype", + "assetlinks" ], "flagWords": ["hte", "full-stack", "Full-stack", "Full-Stack", "sudo"], "patterns": [ diff --git a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/multi-step-sign-in/index.mdx b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/multi-step-sign-in/index.mdx index 4604f7441da..d19dc10329e 100644 --- a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/multi-step-sign-in/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/multi-step-sign-in/index.mdx @@ -1067,102 +1067,111 @@ The `nextStep` property is of enum type `AuthSignInStep`. Depending on its value ```java try { - AWSCognitoAuthSignInOptions options = AWSCognitoAuthSignInOptions.builder().authFlowType(AuthFlowType.USER_SRP_AUTH).build(); - Amplify.Auth.signIn( - "username", - "password", - options, - result -> - { - AuthNextSignInStep nextStep = result.getNextStep(); - switch (nextStep.getSignInStep()) { - case CONFIRM_SIGN_IN_WITH_TOTP_CODE: { - Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code"); - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - break; - } - case CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION: { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); - Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); - // Prompt the user to select the MFA type they want to setup - // Then invoke `confirmSignIn` api with the MFA type - break; - } - case CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP: { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); - // Prompt the user to enter the email address they would like to use to receive OTPs - // Then invoke `confirmSignIn` api with the email address - break; - } - case CONTINUE_SIGN_IN_WITH_TOTP_SETUP: { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP"); - Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app" + nextStep.getTotpSetupDetails().getSharedSecret()); - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - break; - } - case CONTINUE_SIGN_IN_WITH_MFA_SELECTION: { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type"); - Log.i("AuthQuickstart", "Allowed MFA type" + nextStep.getAllowedMFATypes()); - // Prompt the user to select the MFA type they want to use - // Then invoke `confirmSignIn` api with the MFA type - break; - } - case CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE: { - Log.i("AuthQuickstart", "SMS code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); - Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); - // Prompt the user to enter the SMS MFA code they received - // Then invoke `confirmSignIn` api with the code - break; - } - case CONFIRM_SIGN_IN_WITH_OTP: { - Log.i("AuthQuickstart", "OTP code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); - Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); - // Prompt the user to enter the OTP MFA code they received - // Then invoke `confirmSignIn` api with the code - break; - } - case CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE: { - Log.i("AuthQuickstart", "Custom challenge, additional info: " + nextStep.getAdditionalInfo()); - // Prompt the user to enter custom challenge answer - // Then invoke `confirmSignIn` api with the answer - break; - } - case CONFIRM_SIGN_IN_WITH_NEW_PASSWORD: { - Log.i("AuthQuickstart", "Sign in with new password, additional info: " + nextStep.getAdditionalInfo()); - // Prompt the user to enter a new password - // Then invoke `confirmSignIn` api with new password - break; - } - case DONE: { - Log.i("AuthQuickstart", "SignIn complete"); - // User has successfully signed in to the app - break; - } - } - }, - error -> { - if (error instanceof UserNotConfirmedException) { - // User was not confirmed during the signup process. - // Invoke `confirmSignUp` api to confirm the user if - // they have the confirmation code. If they do not have the - // confirmation code, invoke `resendSignUpCode` to send the - // code again. - // After the user is confirmed, invoke the `signIn` api again. - Log.i("AuthQuickstart", "Signup confirmation required" + error); - } else if (error instanceof PasswordResetRequiredException) { - // User needs to reset their password. - // Invoke `resetPassword` api to start the reset password - // flow, and once reset password flow completes, invoke - // `signIn` api to trigger signIn flow again. - Log.i("AuthQuickstart", "Password reset required" + error); - } else { - Log.e("AuthQuickstart", "SignIn failed: " + error); - } - } - - ); + Amplify.Auth.signIn( + "hello@example.com", + "password", + result -> + { + AuthNextSignInStep nextStep = result.getNextStep(); + switch (nextStep.getSignInStep()) { + case CONFIRM_SIGN_IN_WITH_TOTP_CODE: { + Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code"); + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + break; + } + case CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION: { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); + Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); + // Prompt the user to select the MFA type they want to setup + // Then invoke `confirmSignIn` api with the MFA type + break; + } + case CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP: { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); + // Prompt the user to enter the email address they would like to use to receive OTPs + // Then invoke `confirmSignIn` api with the email address + break; + } + case CONTINUE_SIGN_IN_WITH_TOTP_SETUP: { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP"); + Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app" + nextStep.getTotpSetupDetails().getSharedSecret()); + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + break; + } + case CONTINUE_SIGN_IN_WITH_MFA_SELECTION: { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type"); + Log.i("AuthQuickstart", "Allowed MFA type" + nextStep.getAllowedMFATypes()); + // Prompt the user to select the MFA type they want to use + // Then invoke `confirmSignIn` api with the MFA type + break; + } + case CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION: { + Log.i("AuthQuickstart", "Available authentication factors for this user: " + result.getNextStep().getAvailableFactors()); + // Prompt the user to select which authentication factor they want to use to sign-in + // Then invoke `confirmSignIn` api with that selection + break; + } + case CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE: { + Log.i("AuthQuickstart", "SMS code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); + Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); + // Prompt the user to enter the SMS MFA code they received + // Then invoke `confirmSignIn` api with the code + break; + } + case CONFIRM_SIGN_IN_WITH_OTP: { + Log.i("AuthQuickstart", "OTP code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); + Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); + // Prompt the user to enter the OTP MFA code they received + // Then invoke `confirmSignIn` api with the code + break; + } + case CONFIRM_SIGN_IN_WITH_PASSWORD: { + Log.i("AuthQuickstart", "Received next step as confirm sign in with password"); + // Prompt the user to enter their password + // Then invoke `confirmSignIn` api with that password + break; + } + case CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE: { + Log.i("AuthQuickstart", "Custom challenge, additional info: " + nextStep.getAdditionalInfo()); + // Prompt the user to enter custom challenge answer + // Then invoke `confirmSignIn` api with the answer + break; + } + case CONFIRM_SIGN_IN_WITH_NEW_PASSWORD: { + Log.i("AuthQuickstart", "Sign in with new password, additional info: " + nextStep.getAdditionalInfo()); + // Prompt the user to enter a new password + // Then invoke `confirmSignIn` api with new password + break; + } + case DONE: { + Log.i("AuthQuickstart", "SignIn complete"); + // User has successfully signed in to the app + break; + } + } + }, + error -> { + if (error instanceof UserNotConfirmedException) { + // User was not confirmed during the signup process. + // Invoke `confirmSignUp` api to confirm the user if + // they have the confirmation code. If they do not have the + // confirmation code, invoke `resendSignUpCode` to send the + // code again. + // After the user is confirmed, invoke the `signIn` api again. + Log.i("AuthQuickstart", "Signup confirmation required" + error); + } else if (error instanceof PasswordResetRequiredException) { + // User needs to reset their password. + // Invoke `resetPassword` api to start the reset password + // flow, and once reset password flow completes, invoke + // `signIn` api to trigger signIn flow again. + Log.i("AuthQuickstart", "Password reset required" + error); + } else { + Log.e("AuthQuickstart", "SignIn failed: " + error); + } + } + ); } catch (Exception error) { Log.e("AuthQuickstart", "Unexpected error occurred: " + error); } @@ -1173,91 +1182,103 @@ try { ```kotlin -val options = AWSCognitoAuthSignInOptions.builder().authFlowType(AuthFlowType.USER_SRP_AUTH).build() try { - Amplify.Auth.signIn( - "username", - "password", - options, - { result -> - val nextStep = result.nextStep - when(nextStep.signInStep){ - AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE -> { - Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code") - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - } - AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); - Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); - // Prompt the user to select the MFA type they want to setup - // Then invoke `confirmSignIn` api with the MFA type - } - AuthSignInStep.CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); - // Prompt the user to enter the email address they would like to use to receive OTPs - // Then invoke `confirmSignIn` api with the email address - } - AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP") - Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app ${nextStep.totpSetupDetails.sharedSecret}") - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - } - AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SELECTION -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type") - Log.i("AuthQuickstart", "Allowed MFA types ${nextStep.allowedMFATypes}") - // Prompt the user to select the MFA type they want to use - // Then invoke `confirmSignIn` api with the MFA type - } - AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE -> { - Log.i("AuthQuickstart", "SMS code sent to ${nextStep.codeDeliveryDetails?.destination}") - Log.i("AuthQuickstart", "Additional Info ${nextStep.additionalInfo}") - // Prompt the user to enter the SMS MFA code they received - // Then invoke `confirmSignIn` api with the code - } - AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP -> { - Log.i("AuthQuickstart", "OTP code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); - Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); - // Prompt the user to enter the OTP MFA code they received - // Then invoke `confirmSignIn` api with the code - } - AuthSignInStep.CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE -> { - Log.i("AuthQuickstart","Custom challenge, additional info: ${nextStep.additionalInfo}") - // Prompt the user to enter custom challenge answer - // Then invoke `confirmSignIn` api with the answer - } - AuthSignInStep.CONFIRM_SIGN_IN_WITH_NEW_PASSWORD -> { - Log.i("AuthQuickstart", "Sign in with new password, additional info: ${nextStep.additionalInfo}") - // Prompt the user to enter a new password - // Then invoke `confirmSignIn` api with new password - } - AuthSignInStep.DONE -> { - Log.i("AuthQuickstart", "SignIn complete") - // User has successfully signed in to the app - } - } + Amplify.Auth.signIn( + "hello@example.com", + "password", + { result -> + val nextStep = result.nextStep + when(nextStep.signInStep){ + AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE -> { + Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code") + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION -> { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup") + Log.i("AuthQuickstart", "Allowed MFA types for setup ${nextStep.allowedMFATypes}") + // Prompt the user to select the MFA type they want to setup + // Then invoke `confirmSignIn` api with the MFA type + } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP -> { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA") + // Prompt the user to enter the email address they would like to use to receive OTPs + // Then invoke `confirmSignIn` api with the email address + } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP -> { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP") + Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app ${nextStep.totpSetupDetails?.sharedSecret}") + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SELECTION -> { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type") + Log.i("AuthQuickstart", "Allowed MFA types ${nextStep.allowedMFATypes}") + // Prompt the user to select the MFA type they want to use + // Then invoke `confirmSignIn` api with the MFA type + } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION -> { + Log.i("AuthQuickstart", "Available authentication factors for this user: ${result.nextStep.availableFactors}") + // Prompt the user to select which authentication factor they want to use to sign-in + // Then invoke `confirmSignIn` api with that selection + } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE -> { + Log.i("AuthQuickstart", "SMS code sent to ${nextStep.codeDeliveryDetails?.destination}") + Log.i("AuthQuickstart", "Additional Info ${nextStep.additionalInfo}") + // Prompt the user to enter the SMS MFA code they received + // Then invoke `confirmSignIn` api with the code + } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP -> { + Log.i("AuthQuickstart", "OTP code sent to ${nextStep.codeDeliveryDetails?.destination}") + Log.i("AuthQuickstart", "Additional Info ${nextStep.additionalInfo}") + // Prompt the user to enter the OTP MFA code they received + // Then invoke `confirmSignIn` api with the code + } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD -> { + Log.i("AuthQuickstart", "Received next step as confirm sign in with password") + // Prompt the user to enter their password + // Then invoke `confirmSignIn` api with that password + } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE -> { + Log.i("AuthQuickstart","Custom challenge, additional info: ${nextStep.additionalInfo}") + // Prompt the user to enter custom challenge answer + // Then invoke `confirmSignIn` api with the answer + } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_NEW_PASSWORD -> { + Log.i("AuthQuickstart", "Sign in with new password, additional info: ${nextStep.additionalInfo}") + // Prompt the user to enter a new password + // Then invoke `confirmSignIn` api with new password + } + AuthSignInStep.DONE -> { + Log.i("AuthQuickstart", "SignIn complete") + // User has successfully signed in to the app + } + } - } - ) { error -> - if (error is UserNotConfirmedException) { - // User was not confirmed during the signup process. - // Invoke `confirmSignUp` api to confirm the user if - // they have the confirmation code. If they do not have the - // confirmation code, invoke `resendSignUpCode` to send the - // code again. - // After the user is confirmed, invoke the `signIn` api again. - Log.i("AuthQuickstart", "Signup confirmation required", error) - } else if (error is PasswordResetRequiredException) { - // User needs to reset their password. - // Invoke `resetPassword` api to start the reset password - // flow, and once reset password flow completes, invoke - // `signIn` api to trigger signIn flow again. - Log.i("AuthQuickstart", "Password reset required", error) - } else { - Log.e("AuthQuickstart", "Unexpected error occurred: $error") - } - } + } + ) { error -> + when (error) { + is UserNotConfirmedException -> { + // User was not confirmed during the signup process. + // Invoke `confirmSignUp` api to confirm the user if + // they have the confirmation code. If they do not have the + // confirmation code, invoke `resendSignUpCode` to send the + // code again. + // After the user is confirmed, invoke the `signIn` api again. + Log.e("AuthQuickstart", "Signup confirmation required", error) + } + is PasswordResetRequiredException -> { + // User needs to reset their password. + // Invoke `resetPassword` api to start the reset password + // flow, and once reset password flow completes, invoke + // `signIn` api to trigger signIn flow again. + Log.e("AuthQuickstart", "Password reset required", error) + } + else -> { + Log.e("AuthQuickstart", "Unexpected error occurred: $error") + } + } + } } catch (error: Exception) { Log.e("AuthQuickstart", "Unexpected error occurred: $error") } @@ -1268,13 +1289,10 @@ try { ```kotlin -val options = - AWSCognitoAuthSignInOptions.builder().authFlowType(AuthFlowType.USER_SRP_AUTH).build() try { val result = Amplify.Auth.signIn( - "username", - "password", - options + "hello@example.com", + "password" ) val nextStep = result.nextStep when (nextStep.signInStep) { @@ -1284,19 +1302,19 @@ try { // Then invoke `confirmSignIn` api with the code } AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); - Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup") + Log.i("AuthQuickstart", "Allowed MFA types for setup ${nextStep.allowedMFATypes}") // Prompt the user to select the MFA type they want to setup // Then invoke `confirmSignIn` api with the MFA type } AuthSignInStep.CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP -> { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA") // Prompt the user to enter the email address they would like to use to receive OTPs // Then invoke `confirmSignIn` api with the email address } AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP -> { Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP") - Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app ${nextStep.totpSetupDetails.sharedSecret}") + Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app ${nextStep.totpSetupDetails?.sharedSecret}") // Prompt the user to enter the TOTP code generated in their authenticator app // Then invoke `confirmSignIn` api with the code } @@ -1306,6 +1324,11 @@ try { // Prompt the user to select the MFA type they want to use // Then invoke `confirmSignIn` api with the MFA type } + AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION -> { + Log.i("AuthQuickstart", "Available authentication factors for this user: ${result.nextStep.availableFactors}") + // Prompt the user to select which authentication factor they want to use to sign-in + // Then invoke `confirmSignIn` api with that selection + } AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE -> { Log.i("AuthQuickstart", "SMS code sent to ${nextStep.codeDeliveryDetails?.destination}") Log.i("AuthQuickstart", "Additional Info ${nextStep.additionalInfo}") @@ -1318,16 +1341,18 @@ try { // Prompt the user to enter the OTP MFA code they received // Then invoke `confirmSignIn` api with the code } + AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD -> { + Log.i("AuthQuickstart", "Received next step as confirm sign in with password") + // Prompt the user to enter their password + // Then invoke `confirmSignIn` api with that password + } AuthSignInStep.CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE -> { - Log.i("AuthQuickstart", "Custom challenge, additional info: ${nextStep.additionalInfo}") + Log.i("AuthQuickstart","Custom challenge, additional info: ${nextStep.additionalInfo}") // Prompt the user to enter custom challenge answer // Then invoke `confirmSignIn` api with the answer } AuthSignInStep.CONFIRM_SIGN_IN_WITH_NEW_PASSWORD -> { - Log.i( - "AuthQuickstart", - "Sign in with new password, additional info: ${nextStep.additionalInfo}" - ) + Log.i("AuthQuickstart", "Sign in with new password, additional info: ${nextStep.additionalInfo}") // Prompt the user to enter a new password // Then invoke `confirmSignIn` api with new password } @@ -1337,23 +1362,27 @@ try { } } } catch (error: Exception) { - if (error is UserNotConfirmedException) { - // User was not confirmed during the signup process. - // Invoke `confirmSignUp` api to confirm the user if - // they have the confirmation code. If they do not have the - // confirmation code, invoke `resendSignUpCode` to send the - // code again. - // After the user is confirmed, invoke the `signIn` api again. - Log.i("AuthQuickstart", "Signup confirmation required", error) - } else if (error is PasswordResetRequiredException) { - // User needs to reset their password. - // Invoke `resetPassword` api to start the reset password - // flow, and once reset password flow completes, invoke - // `signIn` api to trigger signIn flow again. - Log.i("AuthQuickstart", "Password reset required", error) - } else { - Log.e("AuthQuickstart", "Unexpected error occurred: $error") - } + when (error) { + is UserNotConfirmedException -> { + // User was not confirmed during the signup process. + // Invoke `confirmSignUp` api to confirm the user if + // they have the confirmation code. If they do not have the + // confirmation code, invoke `resendSignUpCode` to send the + // code again. + // After the user is confirmed, invoke the `signIn` api again. + Log.e("AuthQuickstart", "Signup confirmation required", error) + } + is PasswordResetRequiredException -> { + // User needs to reset their password. + // Invoke `resetPassword` api to start the reset password + // flow, and once reset password flow completes, invoke + // `signIn` api to trigger signIn flow again. + Log.e("AuthQuickstart", "Password reset required", error) + } + else -> { + Log.e("AuthQuickstart", "Unexpected error occurred: $error") + } + } } ``` @@ -1362,98 +1391,108 @@ try { ```java - -AWSCognitoAuthSignInOptions options = AWSCognitoAuthSignInOptions.builder().authFlowType(AuthFlowType.USER_SRP_AUTH).build(); -RxAmplify.Auth.signIn("username", "password", options).subscribe( - result -> - { - AuthNextSignInStep nextStep = result.getNextStep(); - switch (nextStep.getSignInStep()) { - case CONFIRM_SIGN_IN_WITH_TOTP_CODE: { - Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code"); - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - break; - } - case CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION: { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); - Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); - // Prompt the user to select the MFA type they want to setup - // Then invoke `confirmSignIn` api with the MFA type - break; - } - case CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP: { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); - // Prompt the user to enter the email address they would like to use to receive OTPs - // Then invoke `confirmSignIn` api with the email address - break; - } - case CONTINUE_SIGN_IN_WITH_TOTP_SETUP: { - Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP"); - Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app" + nextStep.getTotpSetupDetails().getSharedSecret()); - // Prompt the user to enter the TOTP code generated in their authenticator app - // Then invoke `confirmSignIn` api with the code - break; - } - case CONTINUE_SIGN_IN_WITH_MFA_SELECTION: { - Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type"); - Log.i("AuthQuickstart", "Allowed MFA type" + nextStep.getAllowedMFATypes()); - // Prompt the user to select the MFA type they want to use - // Then invoke `confirmSignIn` api with the MFA type - break; - } - case CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE: { - Log.i("AuthQuickstart", "SMS code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); - Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); - // Prompt the user to enter the SMS MFA code they received - // Then invoke `confirmSignIn` api with the code - break; - } - case CONFIRM_SIGN_IN_WITH_OTP: { - Log.i("AuthQuickstart", "OTP code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); - Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); - // Prompt the user to enter the OTP MFA code they received - // Then invoke `confirmSignIn` api with the code - break; - } - case CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE: { - Log.i("AuthQuickstart", "Custom challenge, additional info: " + nextStep.getAdditionalInfo()); - // Prompt the user to enter custom challenge answer - // Then invoke `confirmSignIn` api with the answer - break; - } - case CONFIRM_SIGN_IN_WITH_NEW_PASSWORD: { - Log.i("AuthQuickstart", "Sign in with new password, additional info: " + nextStep.getAdditionalInfo()); - // Prompt the user to enter a new password - // Then invoke `confirmSignIn` api with new password - break; - } - case DONE: { - Log.i("AuthQuickstart", "SignIn complete"); - // User has successfully signed in to the app - break; - } +RxAmplify.Auth.signIn("hello@example.com", "password").subscribe( + result -> + { + AuthNextSignInStep nextStep = result.getNextStep(); + switch (nextStep.getSignInStep()) { + case CONFIRM_SIGN_IN_WITH_TOTP_CODE: { + Log.i("AuthQuickstart", "Received next step as confirm sign in with TOTP code"); + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + break; + } + case CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION: { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting an MFA method to setup"); + Log.i("AuthQuickstart", "Allowed MFA types for setup" + nextStep.getAllowedMFATypes()); + // Prompt the user to select the MFA type they want to setup + // Then invoke `confirmSignIn` api with the MFA type + break; + } + case CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP: { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up email MFA"); + // Prompt the user to enter the email address they would like to use to receive OTPs + // Then invoke `confirmSignIn` api with the email address + break; + } + case CONTINUE_SIGN_IN_WITH_TOTP_SETUP: { + Log.i("AuthQuickstart", "Received next step as continue sign in by setting up TOTP"); + Log.i("AuthQuickstart", "Shared secret that will be used to set up TOTP in the authenticator app" + nextStep.getTotpSetupDetails().getSharedSecret()); + // Prompt the user to enter the TOTP code generated in their authenticator app + // Then invoke `confirmSignIn` api with the code + break; + } + case CONTINUE_SIGN_IN_WITH_MFA_SELECTION: { + Log.i("AuthQuickstart", "Received next step as continue sign in by selecting MFA type"); + Log.i("AuthQuickstart", "Allowed MFA type" + nextStep.getAllowedMFATypes()); + // Prompt the user to select the MFA type they want to use + // Then invoke `confirmSignIn` api with the MFA type + break; + } + case CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION: { + Log.i("AuthQuickstart", "Available authentication factors for this user: " + result.getNextStep().getAvailableFactors()); + // Prompt the user to select which authentication factor they want to use to sign-in + // Then invoke `confirmSignIn` api with that selection + break; + } + case CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE: { + Log.i("AuthQuickstart", "SMS code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); + Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); + // Prompt the user to enter the SMS MFA code they received + // Then invoke `confirmSignIn` api with the code + break; + } + case CONFIRM_SIGN_IN_WITH_OTP: { + Log.i("AuthQuickstart", "OTP code sent to " + nextStep.getCodeDeliveryDetails().getDestination()); + Log.i("AuthQuickstart", "Additional Info :" + nextStep.getAdditionalInfo()); + // Prompt the user to enter the OTP MFA code they received + // Then invoke `confirmSignIn` api with the code + break; + } + case CONFIRM_SIGN_IN_WITH_PASSWORD: { + Log.i("AuthQuickstart", "Received next step as confirm sign in with password"); + // Prompt the user to enter their password + // Then invoke `confirmSignIn` api with that password + break; + } + case CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE: { + Log.i("AuthQuickstart", "Custom challenge, additional info: " + nextStep.getAdditionalInfo()); + // Prompt the user to enter custom challenge answer + // Then invoke `confirmSignIn` api with the answer + break; + } + case CONFIRM_SIGN_IN_WITH_NEW_PASSWORD: { + Log.i("AuthQuickstart", "Sign in with new password, additional info: " + nextStep.getAdditionalInfo()); + // Prompt the user to enter a new password + // Then invoke `confirmSignIn` api with new password + break; + } + case DONE: { + Log.i("AuthQuickstart", "SignIn complete"); + // User has successfully signed in to the app + break; } - }, - error -> { - if (error instanceof UserNotConfirmedException) { - // User was not confirmed during the signup process. - // Invoke `confirmSignUp` api to confirm the user if - // they have the confirmation code. If they do not have the - // confirmation code, invoke `resendSignUpCode` to send the - // code again. - // After the user is confirmed, invoke the `signIn` api again. - Log.i("AuthQuickstart", "Signup confirmation required" + error); - } else if (error instanceof PasswordResetRequiredException) { - // User needs to reset their password. - // Invoke `resetPassword` api to start the reset password - // flow, and once reset password flow completes, invoke - // `signIn` api to trigger signIn flow again. - Log.i("AuthQuickstart", "Password reset required" + error); - } else { - Log.e("AuthQuickstart", "SignIn failed: " + error); - } } + }, + error -> { + if (error instanceof UserNotConfirmedException) { + // User was not confirmed during the signup process. + // Invoke `confirmSignUp` api to confirm the user if + // they have the confirmation code. If they do not have the + // confirmation code, invoke `resendSignUpCode` to send the + // code again. + // After the user is confirmed, invoke the `signIn` api again. + Log.i("AuthQuickstart", "Signup confirmation required" + error); + } else if (error instanceof PasswordResetRequiredException) { + // User needs to reset their password. + // Invoke `resetPassword` api to start the reset password + // flow, and once reset password flow completes, invoke + // `signIn` api to trigger signIn flow again. + Log.i("AuthQuickstart", "Password reset required" + error); + } else { + Log.e("AuthQuickstart", "SignIn failed: " + error); + } + } ); ``` @@ -1465,7 +1504,11 @@ RxAmplify.Auth.signIn("username", "password", options).subscribe( If the next step is `CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE`, Amplify Auth has sent the user a random code over SMS, and is waiting to find out if the user successfully received it. To handle this step, your app's UI must prompt the user to enter the code. After the user enters the code, your implementation must pass the value to Amplify Auth `confirmSignIn` API. -Note: the signIn result also includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery such as the partial phone number of the SMS recipient. + + +**Note:** The result also includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery such as the partial phone number of the SMS recipient. + + @@ -1572,7 +1615,21 @@ After the user enters the code, your implementation must pass the value to Ampli If the next step is `CONFIRM_SIGN_IN_WITH_EMAIL_MFA_CODE`, Amplify Auth has sent the user a random code to their email address and is waiting to find out if the user successfully received it. To handle this step, your app's UI must prompt the user to enter the code. After the user enters the code, your implementation must pass the value to Amplify Auth `confirmSignIn` API. -Note: the signIn result also includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery such as the partial email address of the recipient. + + +**Note:** The result also includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery such as the partial email address of the recipient. + + + +## Confirm sign-in with OTP + +If the next step is `CONFIRM_SIGN_IN_WITH_OTP`, Amplify Auth has sent the user a random code to the medium of the user's choosing (e.g. SMS or email) and is waiting for the user to verify that code. To handle this step, your app's UI must prompt the user to enter the code. After the user enters the code, pass the value to the `confirmSignIn` API. + + + +**Note:** The result includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery, such as the partial email address of the recipient, which can be used to prompt the user on where to look for the code. + + ## Continue sign-in with MFA Selection @@ -1592,6 +1649,12 @@ Once the authenticator app is set up, the user can generate a TOTP code and prov If the next step is `CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION`, the user must select the MFA method to setup. Amplify Auth currently supports SMS, TOTP, and email as MFA methods. After the user selects an MFA method, your implementation must pass the selected MFA method to Amplify Auth using `confirmSignIn` API. +## Continue sign-in with First Factor Selection + +If the next step is `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION`, the user must select an authentication factor to use either because they did not specify one or because the one they chose is not supported (e.g. selecting SMS when they don't have a phone number registered to their account). Amplify Auth currently supports SMS, email, password, and webauthn as authentication factors. After the user selects an authentication method, your implementation must pass the selected authentication method to Amplify Auth using `confirmSignIn` API. + +Visit the [sign-in documentation](/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/#sign-in-with-passwordless-methods) to see examples on how to call the `confirmSignIn` API. + ## Confirm sign-in with custom challenge If the next step is `CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE`, Amplify Auth is awaiting completion of a custom authentication challenge. The challenge is based on the Lambda trigger you setup when you configured a [custom sign in flow](/[platform]/build-a-backend/auth/customize-auth-lifecycle/custom-auth-flows/#sign-in-a-user). To complete this step, you should prompt the user for the custom challenge answer, and pass the answer to the `confirmSignIn` API. @@ -1933,7 +1996,10 @@ RxAmplify.Auth.confirmSignUp( This call fetches the current logged in user and should be used after a user has been successfully signed in. If the user is signed in, it will return the current userId and username. -Note: An empty string will be assigned to userId and/or username, if the values are not present in the accessToken. + + +**Note:** An empty string will be assigned to userId and/or username, if the values are not present in the accessToken. + diff --git a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx index 15272c691cd..59c955c5fee 100644 --- a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx @@ -209,7 +209,7 @@ RxAmplify.Auth.signIn("username", "password") func signIn(username: String, password: String) async { do { let signInResult = try await Amplify.Auth.signIn( - username: username, + username: username, password: password ) if signInResult.isSignedIn { @@ -230,7 +230,7 @@ func signIn(username: String, password: String) async { func signIn(username: String, password: String) -> AnyCancellable { Amplify.Publisher.create { try await Amplify.Auth.signIn( - username: username, + username: username, password: password ) }.sink { @@ -280,10 +280,12 @@ The `signIn` API response will include a `nextStep` property, which can be used | `CONFIRM_SIGN_IN_WITH_TOTP_CODE` | The sign-in must be confirmed with a TOTP code from the user. Complete the process with `confirmSignIn`. | | `CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE` | The sign-in must be confirmed with a SMS code from the user. Complete the process with `confirmSignIn`. | | `CONFIRM_SIGN_IN_WITH_OTP` | The sign-in must be confirmed with a code from the user (sent via SMS or Email). Complete the process with `confirmSignIn`. | -| `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` | The user must select their mode of MFA verification before signing in. Complete the process with `confirmSignIn`. | +| `CONFIRM_SIGN_IN_WITH_PASSWORD` | The sign-in must be confirmed with the password from the user. Complete the process with `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION` | The user must select their mode of MFA verification to setup. Complete the process by passing either `MFAType.EMAIL.challengeResponse` or `MFAType.TOTP.challengeResponse` to `confirmSignIn`. | +| `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` | The user must select their mode of MFA verification before signing in. Complete the process with `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` | The TOTP setup process must be continued. Complete the process with `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP` | The EMAIL setup process must be continued. Complete the process by passing a valid email address to `confirmSignIn`. | +| `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION` | The user must select their mode of first factor authentication. Complete the process by passing the desired mode to the `challengeResponse` field of `confirmSignIn`. | | `RESET_PASSWORD` | The user must reset their password via `resetPassword`. | | `CONFIRM_SIGN_UP` | The user hasn't completed the sign-up flow fully and must be confirmed via `confirmSignUp`. | | `DONE` | The sign in process has been completed. | @@ -608,6 +610,8 @@ Following sign in, you will receive a `nextStep` in the sign-in result of one of | `CONFIRM_SIGN_IN_WITH_TOTP_CODE` | The sign-in must be confirmed with a TOTP code from the user. Complete the process with `confirmSignIn`. | | `CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE` | The sign-in must be confirmed with a SMS code from the user. Complete the process with `confirmSignIn`. | | `CONFIRM_SIGN_IN_WITH_OTP` | The sign-in must be confirmed with a code from the user (sent via SMS or Email). Complete the process with `confirmSignIn`. | +| `CONFIRM_SIGN_IN_WITH_PASSWORD` | The sign-in must be confirmed with the password from the user. Complete the process with `confirmSignIn`. | +| `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION` | The user must select their mode of first factor authentication. Complete the process by passing the desired mode to the `challengeResponse` field of `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` | The user must select their mode of MFA verification before signing in. Complete the process with `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION` | The user must select their mode of MFA verification to setup. Complete the process by passing either `MFAType.EMAIL.challengeResponse` or `MFAType.TOTP.challengeResponse` to `confirmSignIn`. | | `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` | The TOTP setup process must be continued. Complete the process with `confirmSignIn`. | @@ -735,7 +739,7 @@ Amplify.Auth.confirmSignIn("code received via SMS", ```kotlin try { val result = Amplify.Auth.confirmSignIn("code received via SMS") - Log.i("AuthQuickstart", "Confirmed signin: $result") + Log.i("AuthQuickstart", "Confirmed signin: $result") } catch (error: AuthException) { Log.e("AuthQuickstart", "Failed to confirm signin", error) } @@ -799,10 +803,10 @@ func confirmSignIn() -> AnyCancellable { ## Sign in with an external identity provider -To sign in using an external identity provider such as Google, use the `signInWithRedirect` function. - +To sign in using an external identity provider such as Google, use the `signInWithRedirect` function. + ```ts import { signInWithRedirect } from "aws-amplify/auth" @@ -840,7 +844,9 @@ await autoSignIn(); ``` - + + ### Install native module @@ -879,6 +885,8 @@ Add the `intent-filter` to your application's main activity, replacing `myapp` w +To sign in using an external identity provider such as Google, use the `signInWithWebUI` function. + ### How It Works Sign-in with web UI will display the sign-in UI inside a webview. After the sign-in process is complete, the sign-in UI will redirect back to your app. @@ -945,7 +953,10 @@ Future socialSignIn() async { ``` -## Update AndroidManifest.xml + +To sign in using an external identity provider such as Google, use the `signInWithSocialWebUI` function. + +### Update AndroidManifest.xml Add the following activity and queries tag to your app's `AndroidManifest.xml` file, replacing `myapp` with your redirect URI prefix if necessary: @@ -967,7 +978,7 @@ your redirect URI prefix if necessary: ``` -## Launch Social Web UI Sign In +### Launch Social Web UI Sign In Sweet! You're now ready to launch sign in with your social provider's web UI. @@ -1030,9 +1041,12 @@ RxAmplify.Auth.signInWithSocialWebUI(AuthProvider.facebook(), this) -## Update Info.plist -Sign-in with web UI requires the Amplify plugin to show up the sign-in UI inside a webview. After the sign-in process is complete it will redirect back to your app. +To sign in using an external identity provider such as Google, use the `signInWithWebUI` function. + +### Update Info.plist + +Sign-in with web UI requires the Amplify plugin to show up the sign-in UI inside a webview. After the sign-in process is complete it will redirect back to your app. You have to enable this in your app's `Info.plist`. Right click Info.plist and then choose Open As > Source Code. Add the following entry in the URL scheme: ```xml @@ -1060,7 +1074,7 @@ You have to enable this in your app's `Info.plist`. Right click Info.plist and t When creating a new SwiftUI app using Xcode 13 no longer require configuration files such as the Info.plist. If you are missing this file, click on the project target, under Info, Url Types, and click '+' to add a new URL Type. Add `myapp` to the URL Schemes. You should see the Info.plist file now with the entry for CFBundleURLSchemes. -## Launch Social Web UI Sign In +### Launch Social Web UI Sign In Invoke the following API with the provider you're using (shown with Facebook below): @@ -1107,12 +1121,12 @@ func socialSignInWithWebUI() -> AnyCancellable { - + ## Sign in with passwordless methods -Your application's users can also sign in using passwordless methods. To learn more, visit the [concepts page for passwordless](/[platform]/build-a-backend/auth/concepts/passwordless/) +Your application's users can also sign in using passwordless methods. To learn more, visit the [concepts page for passwordless](/[platform]/build-a-backend/auth/concepts/passwordless/). ### SMS OTP @@ -1147,7 +1161,108 @@ if (signInNextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_SMS_CODE') { -{/* */} +To request an OTP code via SMS for authentication, you pass the `challengeResponse` for `AuthFactorType.SMS_OTP` to the `confirmSignIn` API. + +Amplify will respond appropriately to Cognito and return the challenge as the sign in next step: `CONFIRM_SIGN_IN_WITH_OTP_CODE`. You will call `confirmSignIn` again, this time with the OTP that your user provides. + + + + +```java +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.SMS_OTP.getChallengeResponse(), + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); + +// Then pass that OTP into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "123456", + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.SMS_OTP.challengeResponse, + { result -> + if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) + +// Then pass that OTP into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "123456", + { result -> + // result.nextStep.signInStep should be "DONE" now + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) +``` + + + + +```kotlin +// First confirm the challenge type +var result = Amplify.Auth.confirmSignIn(AuthFactorType.SMS_OTP.challengeResponse) +if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP +} + +// Then pass that OTP into the confirmSignIn API +result = Amplify.Auth.confirmSignIn("123456") + +// result.nextStep.signInStep should be "DONE" now +``` + + + + +```java +// First confirm the challenge type +RxAmplify.Auth.confirmSignIn(AuthFactorType.SMS_OTP.getChallengeResponse()) + .subscribe( + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); + +// Then pass that OTP into the confirmSignIn API +RxAmplify.Auth.confirmSignIn("123456") + .subscribe( + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + @@ -1260,7 +1375,109 @@ if (signInNextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_EMAIL_CODE') { -{/* */} +To request an OTP code via email for authentication, you pass the `challengeResponse` for `AuthFactorType.EMAIL_OTP` to the `confirmSignIn` API. + +Amplify will respond appropriately to Cognito and return the challenge as the sign in next step: `CONFIRM_SIGN_IN_WITH_OTP_CODE`. You will call `confirmSignIn` again, this time with the OTP that your user provides. + + + + +```java +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.EMAIL_OTP.getChallengeResponse(), + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); + +// Then pass that OTP into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "123456", + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.EMAIL_OTP.challengeResponse, + { result -> + if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) + +// Then pass that OTP into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "123456", + { result -> + // result.nextStep.signInStep should be "DONE" now + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) +``` + + + + +```kotlin +// First confirm the challenge type +var result = Amplify.Auth.confirmSignIn(AuthFactorType.EMAIL_OTP.challengeResponse) +if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP +} + +// Then pass that OTP into the confirmSignIn API +result = Amplify.Auth.confirmSignIn("123456") + +// result.nextStep.signInStep should be "DONE" now +``` + + + + +```java +// First confirm the challenge type +RxAmplify.Auth.confirmSignIn(AuthFactorType.EMAIL_OTP.getChallengeResponse()) + .subscribe( + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP) { + // Show UI to collect OTP + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); + +// Then pass that OTP into the confirmSignIn API +RxAmplify.Auth.confirmSignIn("123456") + .subscribe( + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + + @@ -1340,7 +1557,7 @@ func confirmSignIn() -> AnyCancellable { - + ### WebAuthn Passkeys {/* blurb with supplemental information about handling sign-in, events, etc. */} @@ -1366,7 +1583,97 @@ if (signInNextStep.signInStep === 'DONE') { -{/* */} +To sign in with WebAuthn, you pass the `challengeResponse` for `AuthFactorType.WEB_AUTHN` to the `confirmSignIn` API. Amplify will invoke Android's Credential Manager to retrieve a PassKey, and the user will be shown a system UI to authorize the PassKey access. This flow +completes without any additional interaction from your application, so there is only one `confirmSignIn` call needed for WebAuthn. + + +Amplify requires an `Activity` reference to attach the PassKey UI to your Application's [Task](https://developer.android.com/guide/components/activities/tasks-and-back-stack) when using WebAuthn - if an `Activity` is not supplied then the UI will appear in a separate Task. For this reason, we strongly recommend passing the `callingActivity` option to both the `signIn` and `confirmSignIn` APIs if your application uses the `USER_AUTH` flow. + + + + + +```java +// Pass the calling activity +AuthSignInOptions options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build(); + +// Confirm WebAuthn as the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.WEB_AUTHN.getChallengeResponse(), + options, + result -> Log.i("AuthQuickStart", "Next sign in step: " + result.getNextStep()), + error -> Log.e("AuthQuickstart", "Failed to sign in", error) +); +``` + + + + +```kotlin +// Pass the calling activity +val options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build() + +// Confirm WebAuthn as the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.WEB_AUTHN.name, + options, + { result -> Log.i("AuthQuickStart", "Next sign in step: ${result.nextStep}") }, + { error -> Log.e("AuthQuickstart", "Failed to sign in", error) } +) +``` + + + + +```kotlin +// Pass the calling activity +val options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build() + +try { + // Confirm WebAuthn as the challenge type + var result = Amplify.Auth.confirmSignIn( + challengeResponse = AuthFactorType.WEB_AUTHN.challengeResponse, + options = options + ) + Log.i("AuthQuickStart", "Next sign in step: ${result.nextStep}") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Failed to sign in", error) +} +``` + + + + +```java +// Pass the calling activity +AuthSignInOptions options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build(); + +// Confirm WebAuthn as the challenge type +RxAmplify.Auth.confirmSignIn(AuthFactorType.WEB_AUTHN.getChallengeResponse(), options) + .subscribe( + result -> Log.i("AuthQuickStart", "Next sign in step: " + result.getNextStep()), + error -> Log.e("AuthQuickstart", "Failed to sign in", error) + ); +``` + + + + +Using WebAuthn sign in may result in a number of possible exception types. + +- `UserCancelledException` - If the user declines to authorize access to the PassKey in the system UI. You can retry the WebAuthn flow by invoking `confirmSignIn` again, or restart the `signIn` process to select a different `AuthFactorType`. +- `WebAuthnNotEnabledException` - This indicates WebAuthn is not enabled in your user pool. +- `WebAuthnNotSupportedException` - This indicates WebAuthn is not supported on the user's device. +- `WebAuthnRpMismatchException` - This indicates there is a problem with the `assetlinks.json` file deployed to your relying party. +- `WebAuthnFailedException` - This exception is used for other errors that may occur with WebAuthn. Inspect the `cause` to determine the best course of action. @@ -1380,12 +1687,15 @@ if (signInNextStep.signInStep === 'DONE') { - + ### Password - Pass either `PASSWORD` or `PASSWORD_SRP` as the `preferredChallenge` in order to initiate a traditional password based authentication flow. +Pass either `PASSWORD` or `PASSWORD_SRP` as the `preferredChallenge` in order to initiate a traditional password based authentication flow. + + + ```ts const { nextStep: signInNextStep } = await signIn({ username: 'hello@example.com', @@ -1400,14 +1710,119 @@ if (confirmSignInNextStep.signInStep === 'DONE') { console.log('Sign in successful!'); } ``` + + + + + + + +```java +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.PASSWORD.getChallengeResponse(), // or PASSWORD_SRP + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD) { + // Show UI to collect password + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); + +// Then pass that password into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "password", + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// First confirm the challenge type +Amplify.Auth.confirmSignIn( + AuthFactorType.PASSWORD.challengeResponse, // or PASSWORD_SRP + { result -> + if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD) { + // Show UI to collect password + } + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) + +// Then pass that password into the confirmSignIn API +Amplify.Auth.confirmSignIn( + "password", + { result -> + // result.nextStep.signInStep should be "DONE" now + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) +``` + + + + +```kotlin +// First confirm the challenge type +var result = Amplify.Auth.confirmSignIn(AuthFactorType.PASSWORD.challengeResponse) // or PASSWORD_SRP +if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD) { + // Show UI to collect password +} + +// Then pass that password into the confirmSignIn API +result = Amplify.Auth.confirmSignIn("password") + +// result.nextStep.signInStep should be "DONE" now +``` + + + + +```java +// First confirm the challenge type +RxAmplify.Auth.confirmSignIn(AuthFactorType.PASSWORD.getChallengeResponse()) // or PASSWORD_SRP + .subscribe( + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD) { + // Show UI to collect password + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); + +// Then pass that password into the confirmSignIn API +RxAmplify.Auth.confirmSignIn("password") + .subscribe( + result -> { + // result.getNextStep().getSignInStep() should be "DONE" now + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + + ### First Factor Selection -Omit the `preferredChallenge` parameter to discover what first factors are available for a given user. +Omit the `preferredChallenge` parameter to discover what first factors are available for a given user. The `confirmSignIn` API can then be used to select a challenge and initiate the associated authentication flow. + + ```ts const { nextStep: signInNextStep } = await signIn({ username: '+15551234567', @@ -1429,7 +1844,119 @@ if ( } ``` + + + + + + +```java +// Retrieve the authentication factors by calling .availableFactors +AWSCognitoAuthSignInOptions options = + AWSCognitoAuthSignInOptions + .builder() + .authFlowType(AuthFlowType.USER_AUTH) + .callingActivity(callingActivity) + .build(); +Amplify.Auth.signIn( + "hello@example.com", + null, + options, + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION) { + Log.i( + "AuthQuickstart", + "Available authentication factors for this user: " + result.getNextStep().getAvailableFactors() + ); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// Retrieve the authentication factors by calling .availableFactors +val options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_AUTH) + .callingActivity(callingActivity) + .build() +Amplify.Auth.signIn( + "hello@example.com", + null, + options, + { result -> + if (result.nextStep.signInStep == AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION) { + Log.i( + "AuthQuickstart", + "Available factors for this user: ${result.nextStep.availableFactors}" + ) + } + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) +``` + + + + +```kotlin +try { + // Retrieve the authentication factors by calling .availableFactors + val options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_AUTH) + .callingActivity(callingActivity) + .build() + val result = Amplify.Auth.signIn( + username = "hello@example.com", + password = null, + options = options + ) + if (result.nextStep.signInStep == AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION) { + Log.i( + "AuthQuickstart", + "Available factors for this user: ${result.nextStep.availableFactors}" + ) + } +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Sign in failed", error) +} +``` + + + + +```java +// Retrieve the authentication factors by calling .availableFactors +AWSCognitoAuthSignInOptions options = + AWSCognitoAuthSignInOptions + .builder() + .authFlowType(AuthFlowType.USER_AUTH) + .callingActivity(callingActivity) + .build(); +RxAmplify.Auth.signIn("hello@example.com", null, options) + .subscribe( + result -> { + if (result.getNextStep().getSignInStep() == AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION) { + Log.i( + "AuthQuickstart", + "Available authentication factors for this user: " + result.getNextStep().getAvailableFactors() + ); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + + diff --git a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-up/index.mdx b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-up/index.mdx index 436ce634a0e..f06dcbdb8bc 100644 --- a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-up/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-up/index.mdx @@ -528,11 +528,11 @@ export default function App() { - + ## Sign up with passwordless methods -Your application's users can also sign up using passwordless methods. To learn more, visit the [concepts page for passwordless](/[platform]/build-a-backend/auth/concepts/passwordless/) +Your application's users can also sign up using passwordless methods. To learn more, visit the [concepts page for passwordless](/[platform]/build-a-backend/auth/concepts/passwordless/). ### SMS OTP @@ -578,7 +578,168 @@ if (confirmSignUpNextStep.signUpStep === 'DONE') { -{/* */} + + + +```java +// Sign up using a phone number +ArrayList attributes = new ArrayList<>(); +attributes.add(new AuthUserAttribute(AuthUserAttributeKey.phoneNumber(), "+15551234567")); + +Amplify.Auth.signUp( + "hello@example.com", + null, + AuthSignUpOptions.builder().userAttributes(attributes).build(), + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } else if (result.getNextStep().getSignUpStep() == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + result.getNextStep().getCodeDeliveryDetails().getDeliveryMedium()); + Log.i("AuthQuickstart", "Code Deliver Destination: " + + result.getNextStep().getCodeDeliveryDetails().getDestination()); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); + +// Confirm sign up with the OTP received +Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456", + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// Sign up using a phone number +val attributes = listOf( + AuthUserAttribute(AuthUserAttributeKey.phoneNumber(), "+15555551234") +) +val options = + AuthSignUpOptions + .builder() + .userAttributes(attributes) + .build() + +Amplify.Auth.signUp( + "hello@example.com", + null, + options, + { result -> + if (result.isSignUpComplete) { + Log.i("AuthQuickstart", "Sign up is complete") + } else if (result.nextStep.signUpStep == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + "${result.nextStep.codeDeliveryDetails?.deliveryMedium}") + Log.i("AuthQuickstart", "Code Deliver Destination: " + + "${result.nextStep.codeDeliveryDetails?.destination}") + } + }, + { Log.e("AuthQuickstart", "Failed to sign up", it) } +) + +// Confirm sign up with the OTP received +Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456", + { result -> + if (result.nextStep.signUpStep == AuthSignUpStep.DONE) { + Log.i("AuthQuickstart", "Sign up is complete") + } + }, + { Log.e("AuthQuickstart", "Failed to sign up", it) } +) +``` + + + + +```kotlin +// Sign up using a phone number +val attributes = listOf( + AuthUserAttribute(AuthUserAttributeKey.phoneNumber(), "+15555551234") +) +val options = + AuthSignUpOptions + .builder() + .userAttributes(attributes) + .build() +var result = Amplify.Auth.signUp("hello@example.com", null, options) + +if (result.isSignUpComplete) { + Log.i("AuthQuickstart", "Sign up is complete") +} else if (result.nextStep.signUpStep == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + "${result.nextStep.codeDeliveryDetails?.deliveryMedium}") + Log.i("AuthQuickstart", "Code Deliver Destination: " + + "${result.nextStep.codeDeliveryDetails?.destination}") +} + +// Confirm sign up with the OTP received +result = Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456" +) + +if (result.nextStep.signUpStep == AuthSignUpStep.DONE) { + Log.i("AuthQuickstart", "Sign up is complete") +} +``` + + + + +```java +// Sign up using a phone number +ArrayList attributes = new ArrayList<>(); +attributes.add(new AuthUserAttribute(AuthUserAttributeKey.phoneNumber(), "+15551234567")); + +RxAmplify.Auth.signUp( + "hello@example.com", + null, + AuthSignUpOptions.builder().userAttributes(attributes).build() +) + .subscribe( + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } else if (result.getNextStep().getSignUpStep() == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + result.getNextStep().getCodeDeliveryDetails().getDeliveryMedium()); + Log.i("AuthQuickstart", "Code Deliver Destination: " + + result.getNextStep().getCodeDeliveryDetails().getDestination()); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); + +// Confirm sign up with the OTP received +RxAmplify.Auth.confirmSignUp( + "hello@example.com", + "123456" +) + .subscribe( + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + @@ -726,7 +887,167 @@ if (confirmSignUpNextStep.signUpStep === 'DONE') { -{/* */} + + + +```java +// Sign up using an email address +ArrayList attributes = new ArrayList<>(); +attributes.add(new AuthUserAttribute(AuthUserAttributeKey.email(), "hello@example.com")); + +Amplify.Auth.signUp( + "hello@example.com", + null, + AuthSignUpOptions.builder().userAttributes(attributes).build(), + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } else if (result.getNextStep().getSignUpStep() == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + result.getNextStep().getCodeDeliveryDetails().getDeliveryMedium()); + Log.i("AuthQuickstart", "Code Deliver Destination: " + + result.getNextStep().getCodeDeliveryDetails().getDestination()); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); + +// Confirm sign up with the OTP received +Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456", + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) +); +``` + + + + +```kotlin +// Sign up using an email address +val attributes = listOf( + AuthUserAttribute(AuthUserAttributeKey.email(), "my@email.com") +) +val options = + AuthSignUpOptions + .builder() + .userAttributes(attributes) + .build() + +Amplify.Auth.signUp( + "hello@example.com", + null, + options, + { result -> + if (result.isSignUpComplete) { + Log.i("AuthQuickstart", "Sign up is complete") + } else if (result.nextStep.signUpStep == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + "${result.nextStep.codeDeliveryDetails?.deliveryMedium}") + Log.i("AuthQuickstart", "Code Deliver Destination: " + + "${result.nextStep.codeDeliveryDetails?.destination}") + } + }, + { Log.e("AuthQuickstart", "Failed to sign up", it) } +) + +// Confirm sign up with the OTP received +Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456", + { result -> + if (result.nextStep.signUpStep == AuthSignUpStep.DONE) { + Log.i("AuthQuickstart", "Sign up is complete") + } + }, + { Log.e("AuthQuickstart", "Failed to sign up", it) } +) +``` + + + + +```kotlin +// Sign up using an email address +val attributes = listOf( + AuthUserAttribute(AuthUserAttributeKey.email(), "my@email.com") +) +val options = + AuthSignUpOptions + .builder() + .userAttributes(attributes) + .build() +var result = Amplify.Auth.signUp("hello@example.com", null, options) + +if (result.isSignUpComplete) { + Log.i("AuthQuickstart", "Sign up is complete") +} else if (result.nextStep.signUpStep == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + "${result.nextStep.codeDeliveryDetails?.deliveryMedium}") + Log.i("AuthQuickstart", "Code Deliver Destination: " + + "${result.nextStep.codeDeliveryDetails?.destination}") +} + +// Confirm sign up with the OTP received +result = Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456" +) + +if (result.nextStep.signUpStep == AuthSignUpStep.DONE) { + Log.i("AuthQuickstart", "Sign up is complete") +} +``` + + + + +```java +// Sign up using an email address +ArrayList attributes = new ArrayList<>(); +attributes.add(new AuthUserAttribute(AuthUserAttributeKey.email(), "my@email.com")); + +RxAmplify.Auth.signUp( + "hello@example.com", + null, + AuthSignUpOptions.builder().userAttributes(attributes).build() +) + .subscribe( + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } else if (result.getNextStep().getSignUpStep() == AuthSignUpStep.CONFIRM_SIGN_UP_STEP) { + Log.i("AuthQuickstart", "Code Deliver Medium: " + + result.getNextStep().getCodeDeliveryDetails().getDeliveryMedium()); + Log.i("AuthQuickstart", "Code Deliver Destination: " + + result.getNextStep().getCodeDeliveryDetails().getDestination()); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); + +// Confirm sign up with the OTP received +RxAmplify.Auth.confirmSignUp( + "hello@example.com", + "123456" +) + .subscribe( + result -> { + if (result.isSignUpComplete()) { + Log.i("AuthQuickstart", "Sign up is complete"); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + @@ -854,7 +1175,120 @@ if (confirmSignUpNextStep.signUpStep === 'COMPLETE_AUTO_SIGN_IN') { -{/* */} + + + +```java +private void confirmSignUp(String username, String confirmationCode) { + // Confirm sign up with the OTP received then auto sign in + Amplify.Auth.confirmSignUp( + username, + confirmationCode, + result -> { + if (result.getNextStep().getSignUpStep() == AuthSignUpStep.COMPLETE_AUTO_SIGN_IN) { + Log.i("AuthQuickstart", "Sign up is complete, auto sign in"); + autoSignIn(); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +} + +private void autoSignIn() { + Amplify.Auth.autoSignIn( + result -> Log.i("AuthQuickstart", "Sign in is complete"), + error -> Log.e("AuthQuickstart", error.toString()) + ); +} +``` + + + + +```kotlin +fun confirmSignUp(username: String, confirmationCode: String) { + // Confirm sign up with the OTP received + Amplify.Auth.confirmSignUp( + username, + confirmationCode, + { signUpResult -> + if (signUpResult.nextStep.signUpStep == AuthSignUpStep.COMPLETE_AUTO_SIGN_IN) { + Log.i("AuthQuickstart", "Sign up is complete, auto sign in") + autoSignIn() + } + }, + { Log.e("AuthQuickstart", "Failed to sign up", it) } + ) +} +fun autoSignIn() { + Amplify.Auth.autoSignIn( + { signInResult -> + Log.i("AuthQuickstart", "Sign in is complete") + }, + { Log.e("AuthQuickstart", "Failed to sign in", it) } + ) +} +``` + + + + +```kotlin +suspend fun confirmSignUp(username: String, confirmationCode: String) { + // Confirm sign up with the OTP received then auto sign in + val result = Amplify.Auth.confirmSignUp( + "hello@example.com", + "123456" + ) + + if (result.nextStep.signUpStep == AuthSignUpStep.COMPLETE_AUTO_SIGN_IN) { + Log.i("AuthQuickstart", "Sign up is complete, auto sign in") + autoSignIn() + } +} + +suspend fun autoSignIn() { + val result = Amplify.Auth.autoSignIn() + if (result.isSignedIn) { + Log.i("AuthQuickstart", "Sign in is complete") + } else { + Log.e("AuthQuickstart", "Sign in did not complete $result") + } +} +``` + + + + +```java +private void confirmSignUp(String username, String confirmationCode) { + // Confirm sign up with the OTP received then auto sign in + RxAmplify.Auth.confirmSignUp( + username, + confirmationCode + ) + .subscribe( + result -> { + if (result.getNextStep().getSignUpStep() == AuthSignUpStep.COMPLETE_AUTO_SIGN_IN) { + Log.i("AuthQuickstart", "Sign up is complete, auto sign in"); + autoSignIn(); + } + }, + error -> Log.e("AuthQuickstart", error.toString()) + ); +} + +private void autoSignIn() { + RxAmplify.Auth.autoSignIn() + .subscribe( + result -> Log.i("AuthQuickstart", "Sign in is complete" + result.toString()), + error -> Log.e("AuthQuickstart", error.toString()) + ); +} +``` + + + diff --git a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx index 5c82f2da750..f0bcbe79167 100644 --- a/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx @@ -10,7 +10,8 @@ export const meta = { 'react', 'react-native', 'swift', - 'vue' + 'vue', + 'android' ] }; @@ -28,7 +29,7 @@ export function getStaticProps() { -`AWSCognitoAuthPlugin` allows you to switch between different auth flows while initiating signIn. You can configure the flow in the `amplifyconfiguration.json` file or pass the `authFlowType` as a runtime parameter to the `signIn` api call. +`AWSCognitoAuthPlugin` allows you to switch between different auth flows while initiating signIn. You can configure the flow in the `amplify_outputs.json` file or pass the `authFlowType` as a runtime parameter to the `signIn` api call. For client side authentication there are four different flows that can be configured during runtime: @@ -101,30 +102,6 @@ func signIn(username: String, password: String) async throws { } ``` -### Set up auth backend - -In order to use the authentication flow `USER_PASSWORD_AUTH`, your Cognito app client has to be configured to allow it. Amplify Gen 2 enables SRP auth by default. To enable USER_PASSWORD_AUTH, you can update the `backend.ts` file with the following changes: - -```ts title="amplify/backend.ts" -import { defineBackend } from '@aws-amplify/backend' -import { auth } from './auth/resource' -import { data } from './data/resource' - -const backend = defineBackend({ - auth, - data, -}); - -// highlight-start -backend.auth.resources.cfnResources.cfnUserPoolClient.explicitAuthFlows = [ - "ALLOW_USER_PASSWORD_AUTH", - "ALLOW_USER_SRP_AUTH", - "ALLOW_USER_AUTH", - "ALLOW_REFRESH_TOKEN_AUTH" -]; -// highlight-end -``` - ### Migrate users with Amazon Cognito Amazon Cognito provides a trigger to migrate users from your existing user directory seamlessly into Cognito. You achieve this by configuring your User Pool's "Migration" trigger which invokes a Lambda function whenever a user that does not already exist in the user pool authenticates, or resets their password. @@ -274,6 +251,387 @@ To create a CAPTCHA challenge with a Lambda Trigger, please visit [AWS Amplify G + + +`AWSCognitoAuthPlugin` allows you to switch between different auth flows while initiating signIn. You can configure the flow in the `amplify_outputs.json` file or pass the `authFlowType` as a option to the `signIn` api call. + +For client side authentication there are four different flows that can be configured during runtime: + +1. `USER_SRP_AUTH`: The `USER_SRP_AUTH` flow uses the [SRP protocol (Secure Remote Password)](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) where the password never leaves the client and is unknown to the server. This is the recommended flow and is used by default. + +2. `USER_PASSWORD_AUTH`: The `USER_PASSWORD_AUTH` flow will send user credentials unencrypted to the back-end. If you want to migrate users to Cognito using the "Migration" trigger and avoid forcing users to reset their passwords, you will need to use this authentication type because the Lambda function invoked by the trigger needs to verify the supplied credentials. + +3. `CUSTOM_AUTH_WITH_SRP`: The `CUSTOM_AUTH_WITH_SRP` flow is used to start with SRP authentication and then switch to custom authentication. This is useful if you want to use SRP for the initial authentication and then use custom authentication for subsequent authentication attempts. + +4. `CUSTOM_AUTH_WITHOUT_SRP`: The `CUSTOM_AUTH_WITHOUT_SRP` flow is used to start authentication flow **WITHOUT** SRP and then use a series of challenge and response cycles that can be customized to meet different requirements. + +5. `USER_AUTH`: The `USER_AUTH` flow is a choice-based authentication flow that allows the user to choose from the list of available authentication methods. This flow is useful when you want to provide the user with the option to choose the authentication method. The choices that may be available to the user are `EMAIL_OTP`, `SMS_OTP`, `WEB_AUTHN`, `PASSWORD` or `PASSWORD_SRP`. + +`Auth` can be configured to use the different flows at runtime by calling `signIn` with `AWSCognitoAuthSignInOptions`'s `authFlowType` as `AuthFlowType.USER_PASSWORD_AUTH`, `AuthFlowType.CUSTOM_AUTH_WITHOUT_SRP`, `AuthFlowType.CUSTOM_AUTH_WITH_SRP`, or `AuthFlowType.USER_AUTH`. If you do not specify the `AuthFlowType` in `AWSCognitoAuthSignInOptions`, the default flow specified in `amplify_outputs.json` will be used. + + + +Runtime configuration will take precedence and will override any auth flow type configuration present in `amplify_outputs.json`. + + + +For more information about authentication flows, please visit [Amazon Cognito developer documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow) + +## USER_AUTH (Choice-based authentication) flow + +A use case for the `USER_AUTH` authentication flow is to provide the user with the option to choose the authentication method. The choices that may be available to the user are `EMAIL_OTP`, `SMS_OTP`, `WEB_AUTHN`, `PASSWORD` or `PASSWORD_SRP`. + + +Amplify requires an `Activity` reference to attach the PassKey UI to your Application's [Task](https://developer.android.com/guide/components/activities/tasks-and-back-stack) when using WebAuthn - if an `Activity` is not supplied then the UI will appear in a separate Task. For this reason, we strongly recommend passing the `callingActivity` option to both the `signIn` and `confirmSignIn` APIs if your application uses the `USER_AUTH` flow. + + +If the desired first factor is known before the sign in flow is initiated it can be passed to the initial sign in call. + + + + +```java +// PASSWORD_SRP / PASSWORD +// Sign in with preferred challenge as password +// NOTE: Password must be provided in the same step +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.PASSWORD_SRP) // or "PASSWORD" + .build(); +Amplify.Auth.signIn( + username, + password, + options, + result -> Log.i("AuthQuickStart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) +); + +// WEB_AUTHN / EMAIL_OTP / SMS_OTP +// Sign in with preferred passwordless challenge +// No user input is required at this step +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.WEB_AUTHN) // or "EMAIL_OTP" or "SMS_OTP" + .build(); +Amplify.Auth.signIn( + username, + null, + options, + result -> Log.i("AuthQuickStart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) +); +``` + + + + +```kotlin +// PASSWORD_SRP / PASSWORD +// Sign in with preferred challenge as password +// NOTE: Password must be provided in the same step +val options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.PASSWORD_SRP) // or "PASSWORD" + .build() +Amplify.Auth.signIn( + username, + password, + options, + { result -> Log.i("AuthQuickStart", "Next step for sign in is ${result.nextStep}") }, + { error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) } +) + +// WEB_AUTHN / EMAIL_OTP / SMS_OTP +// Sign in with preferred passwordless challenge +// No user input is required at this step +val options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.WEB_AUTHN) // or "EMAIL_OTP" or "SMS_OTP" + .build() +Amplify.Auth.signIn( + username, + null, + options, + { result -> Log.i("AuthQuickStart", "Next step for sign in is ${result.nextStep}") }, + { error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) } +) +``` + + + + +```kotlin +// PASSWORD_SRP / PASSWORD +// Sign in with preferred challenge as password +// NOTE: Password must be provided in the same step +try { + val options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.PASSWORD_SRP) // or "PASSWORD" + .build() + val result = Amplify.Auth.signIn( + username = "hello@example.com", + password = "password", + options = options + ) + Log.i("AuthQuickstart", "Next step for sign in is ${result.nextStep}") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Sign in failed", error) +} + +// WEB_AUTHN / EMAIL_OTP / SMS_OTP +// Sign in with preferred passwordless challenge +// No user input is required at this step +try { + val options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.WEB_AUTHN) // or "EMAIL_OTP" or "SMS_OTP" + .build() + val result = Amplify.Auth.signIn( + username = "hello@example.com", + password = null, + options = options + ) + Log.i("AuthQuickstart", "Next step for sign in is ${result.nextStep}") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Sign in failed", error) +} +``` + + + + +```java +// PASSWORD_SRP / PASSWORD +// Sign in with preferred challenge as password +// NOTE: Password must be provided in the same step +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.PASSWORD_SRP) // or "PASSWORD" + .build(); +RxAmplify.Auth.signIn(username, password, options) + .subscribe( + result -> Log.i("AuthQuickstart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickstart", "Failed to confirm sign in", error)) + ); + +// WEB_AUTHN / EMAIL_OTP / SMS_OTP +// Sign in with preferred passwordless challenge +// No user input is required at this step +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .callingActivity(activity) + .authFlowType(AuthFlowType.USER_AUTH) + .preferredFirstFactor(AuthFactorType.WEB_AUTHN) // or "EMAIL_OTP" or "SMS_OTP" + .build(); +RxAmplify.Auth.signIn(username, null, options) + .subscribe( + result -> Log.i("AuthQuickstart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickstart", "Failed to confirm sign in", error)) + ); +``` + + + + +If the preferred first factor is not supplied or is unavailable, and the user has multiple factors available, the flow will continue to select an available first factor by returning an `AuthNextSignInStep.signInStep` value of `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION`, and a list of `AuthNextSignInStep.availableFactors`. + +The selection of the authentication method is done by the user. The user can choose from the available factors and proceed with the selected factor. You should call the `confirmSignIn` API with the selected factor to continue the sign-in process. Following is an example if you want to proceed with the `WEB_AUTHN` factor selection: + + + + +```java +AuthConfirmSignInOptions options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build(); +Amplify.Auth.confirmSignIn( + AuthFactorType.WEB_AUTHN.getChallengeResponse(), + options, + result -> Log.i("AuthQuickStart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) +); +``` + + + + +```kotlin +val options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build() +Amplify.Auth.confirmSignIn( + AuthFactorType.WEB_AUTHN.challengeResponse, + options, + { result -> Log.i("AuthQuickStart", "Next step for sign in is ${result.nextStep}") }, + { error -> Log.e("AuthQuickStart", "Failed to confirm sign in", error) } +) +``` + + + + +```kotlin +try { + val options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build() + val result = Amplify.Auth.confirmSignIn( + challengeResponse = AuthFactorType.WEB_AUTHN.challengeResponse, + options = options + ) + Log.i("AuthQuickstart", "Next step for sign in is ${result.nextStep}") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Sign in failed", error) +} +``` + + + + +```java +AuthConfirmSignInOptions options = AWSCognitoAuthConfirmSignInOptions.builder() + .callingActivity(activity) + .build(); +RxAmplify.Auth.confirmSignIn(AuthFactorType.WEB_AUTHN.getChallengeResponse(), options) + .subscribe( + result -> Log.i("AuthQuickstart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickstart", "Failed to confirm sign in", error)) + ); +``` + + + + +## USER_PASSWORD_AUTH flow + +A use case for the `USER_PASSWORD_AUTH` authentication flow is migrating users into Amazon Cognito + +A user migration Lambda trigger helps migrate users from a legacy user management system into your user pool. If you choose the USER_PASSWORD_AUTH authentication flow, users don't have to reset their passwords during user migration. This flow sends your user's password to the service over an encrypted SSL connection during authentication. + +When you have migrated all your users, switch flows to the more secure SRP flow. The SRP flow doesn't send any passwords over the network. + + + + +```java +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_PASSWORD_AUTH) + .build(); +Amplify.Auth.signIn( + "hello@example.com", + "password", + options, + result -> Log.i("AuthQuickStart", "Sign in succeeded with result " + result), + error -> Log.e("AuthQuickStart", "Failed to sign in", error) +); +``` + + + + +```kotlin +val options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_PASSWORD_AUTH) + .build() +Amplify.Auth.signIn( + "hello@example.com", + "password", + options, + { result -> + Log.i("AuthQuickstart", "Next step for sign in is ${result.nextStep}") + }, + { error -> + Log.e("AuthQuickstart", "Failed to sign in", error) + } +) +``` + + + + +```kotlin +try { + val options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_PASSWORD_AUTH) + .build() + val result = Amplify.Auth.signIn( + username = "hello@example.com", + password = "password", + options = options + ) + Log.i("AuthQuickstart", "Next step for sign in is ${result.nextStep}") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Sign in failed", error) +} +``` + + + + +```java +AuthSignInOptions options = AWSCognitoAuthSignInOptions.builder() + .authFlowType(AuthFlowType.USER_PASSWORD_AUTH) + .build(); +RxAmplify.Auth.signIn("hello@example.com", "password", options) + .subscribe( + result -> Log.i("AuthQuickstart", "Next step for sign in is " + result.getNextStep()), + error -> Log.e("AuthQuickstart", error.toString()) + ); +``` + + + + +### Set up auth backend + +In order to use the authentication flow `USER_PASSWORD_AUTH`, your Cognito app client has to be configured to allow it. Amplify Gen 2 enables SRP auth by default. To enable USER_PASSWORD_AUTH, you can update the `backend.ts` file with the following changes: + +```ts title="amplify/backend.ts" +import { defineBackend } from '@aws-amplify/backend' +import { auth } from './auth/resource' +import { data } from './data/resource' + +const backend = defineBackend({ + auth, + data, +}); + +// highlight-start +backend.auth.resources.cfnResources.cfnUserPoolClient.explicitAuthFlows = [ + "ALLOW_USER_PASSWORD_AUTH", + "ALLOW_USER_SRP_AUTH", + "ALLOW_USER_AUTH", + "ALLOW_REFRESH_TOKEN_AUTH" +]; +// highlight-end +``` + +### Migrate users with Amazon Cognito + +Amazon Cognito provides a trigger to migrate users from your existing user directory seamlessly into Cognito. You achieve this by configuring your User Pool's "Migration" trigger which invokes a Lambda function whenever a user that does not already exist in the user pool authenticates, or resets their password. + +In short, the Lambda function will validate the user credentials against your existing user directory and return a response object containing the user attributes and status on success. An error message will be returned if an error occurs. There's documentation around [how to set up this migration flow](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-import-using-lambda.html) and more detailed instructions on [how the lambda should handle request and response objects](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-migrate-user.html#cognito-user-pools-lambda-trigger-syntax-user-migration). + +## CUSTOM_AUTH flow + +Amazon Cognito User Pools supports customizing the authentication flow to enable custom challenge types, in addition to a password in order to verify the identity of users. The custom authentication flow is a series of challenge and response cycles that can be customized to meet different requirements. These challenge types may include CAPTCHAs or dynamic challenge questions. + +To define your challenges for custom authentication flow, you need to implement three Lambda triggers for Amazon Cognito. + +The flow is initiated by calling `signIn` with `AWSCognitoAuthSignInOptions` configured with `AuthFlowType.CUSTOM_AUTH_WITH_SRP` OR `AuthFlowType.CUSTOM_AUTH_WITHOUT_SRP`. + +Follow the instructions in [Custom Auth Sign In](/gen1/[platform]/build-a-backend/auth/sign-in-custom-flow/) to learn about how to integrate custom authentication flow in your application with the Auth APIs. + + + + For more information about working with Lambda Triggers for custom authentication challenges, please visit [Amazon Cognito Developer Documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html). diff --git a/src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx index 1f31f20593b..af358d68c50 100644 --- a/src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx @@ -55,7 +55,55 @@ await associateWebAuthnCredential(); -{/* */} + + + +```java +Amplify.Auth.associateWebAuthnCredential( + activity, + () -> Log.i("AuthQuickstart", "Associated credential"), + error -> Log.e("AuthQuickstart", "Failed to register credential", error) +); +``` + + + + +```kotlin +Amplify.Auth.associateWebAuthnCredential( + activity, + { Log.i("AuthQuickstart", "Associated credential") }, + { Log.e("AuthQuickstart", "Failed to register credential", error) } +) +``` + + + + +```kotlin +try { + val result = Amplify.Auth.associateWebAuthnCredential(activity) + Log.i("AuthQuickstart", "Associated credential") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Failed to associate credential", error) +} +``` + + + + +```java +RxAmplify.Auth.associateWebAuthnCredential(activity) + .subscribe( + result -> Log.i("AuthQuickstart", "Associated credential"), + error -> Log.e("AuthQuickstart", "Failed to associate credential", error) + ); +``` + + + + +You must supply an `Activity` instance so that Amplify can display the PassKey UI in your Application's [Task](https://developer.android.com/guide/components/activities/tasks-and-back-stack). @@ -94,8 +142,8 @@ func associateWebAuthNCredentials() -> AnyCancellable { - -You will be prompted to register a passkey using your local authenticator. Amplify will then associate that passkey with Cognito. + +The user will be prompted to register a passkey using their local authenticator. Amplify will then associate that passkey with Cognito. ## List WebAuthN credentials @@ -116,11 +164,6 @@ for (const credential of result.credentials) { } ``` - - - -{/* */} - @@ -186,6 +229,76 @@ func listWebAuthNCredentials() -> AnyCancellable { + + + + + + +```java +Amplify.Auth.listWebAuthnCredentials( + result -> result.getCredentials().forEach(credential -> { + Log.i("AuthQuickstart", "Credential ID: " + credential.getCredentialId()); + Log.i("AuthQuickstart", "Friendly Name: " + credential.getFriendlyName()); + Log.i("AuthQuickstart", "Relying Party ID: " + credential.getRelyingPartyId()); + Log.i("AuthQuickstart", "Created At: " + credential.getCreatedAt()); + }), + error -> Log.e("AuthQuickstart", "Failed to list credentials", error) +); +``` + + + + +```kotlin +Amplify.Auth.listWebAuthnCredentials( + { result -> + result.credentials.forEach { credential -> + Log.i("AuthQuickstart", "Credential ID: ${credential.credentialId}") + Log.i("AuthQuickstart", "Friendly Name: ${credential.friendlyName}") + Log.i("AuthQuickstart", "Relying Party ID: ${credential.relyingPartyId}") + Log.i("AuthQuickstart", "Created At: ${credential.createdAt}") + } + }, + { error -> Log.e("AuthQuickstart", "Failed to list credentials", error) } +) +``` + + + + +```kotlin +try { + val result = Amplify.Auth.listWebAuthnCredentials() + result.credentials.forEach { credential -> + Log.i("AuthQuickstart", "Credential ID: ${credential.credentialId}") + Log.i("AuthQuickstart", "Friendly Name: ${credential.friendlyName}") + Log.i("AuthQuickstart", "Relying Party ID: ${credential.relyingPartyId}") + Log.i("AuthQuickstart", "Created At: ${credential.createdAt}") + } +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Failed to list credentials", error) +} +``` + + + + +```java +RxAmplify.Auth.listWebAuthnCredentials() + .subscribe( + result -> result.getCredentials().forEach(credential -> { + Log.i("AuthQuickstart", "Credential ID: " + credential.getCredentialId()); + Log.i("AuthQuickstart", "Friendly Name: " + credential.getFriendlyName()); + Log.i("AuthQuickstart", "Relying Party ID: " + credential.getRelyingPartyId()); + Log.i("AuthQuickstart", "Created At: " + credential.getCreatedAt()); + }), + error -> Log.e("AuthQuickstart", "Failed to list credentials", error) + ); +``` + + + ## Delete WebAuthN credentials @@ -203,11 +316,6 @@ await deleteWebAuthnCredential({ credentialId: id }); ``` - - - -{/* */} - @@ -244,6 +352,59 @@ func deleteWebAuthNCredentials(credentialId: String) -> AnyCancellable { + + + + + +```java +Amplify.Auth.deleteWebAuthnCredential( + credentialId, + (result) -> Log.i("AuthQuickstart", "Deleted credential"), + error -> Log.e("AuthQuickstart", "Failed to delete credential", error) +); +``` + + + + +```kotlin +Amplify.Auth.deleteWebAuthnCredential( + credentialId, + { Log.i("AuthQuickstart", "Deleted credential") }, + { Log.e("AuthQuickstart", "Failed to delete credential", error) } +) +``` + + + + +```kotlin +try { + val result = Amplify.Auth.deleteWebAuthnCredential(credentialId) + Log.i("AuthQuickstart", "Deleted credential") +} catch (error: AuthException) { + Log.e("AuthQuickstart", "Failed to delete credential", error) +} +``` + + + + +```java +RxAmplify.Auth.deleteWebAuthnCredential(credentialId) + .subscribe( + result -> Log.i("AuthQuickstart", "Deleted credential"), + error -> Log.e("AuthQuickstart", "Failed to delete credential", error) + ); +``` + + + + +The delete passkey API has only the required `credentialId` as input, and it does not return a value. + +