マルチステップサインイン
ユーザーがサインアップを完了した後、サインインに進むことができます。Amplify Auth のサインインフローはマルチステップのプロセスになる場合があります。必要なステップは、MFA 設定の管理ページで説明されているように認証リソースを定義する際に提供した設定によって決まります。
設定によっては、ユーザーのサインインを完了するためにさまざまな API を呼び出す必要がある場合があります。サインインフローの次のステップを特定するには、サインイン結果の nextStep パラメータを確認してください。
Amplify.Auth.signIn API は SignInResult オブジェクトを返し、サインインフローが完了しているか、ユーザーがサインインするために追加のステップが必要かどうかを示します。
追加のサインインステップが必要かどうかを確認するには、サインイン結果の nextStep.signInStep プロパティを確認してください。
- サインインステップが
doneの場合、フローは完了し、ユーザーはサインインしています。 - サインインステップが
doneでない場合、1 つ以上の追加ステップが必要です。これらについては以下で詳しく説明します。
Future<SignInResult> signInWithCognito( String username, String password,) async { final SignInResult result = await Amplify.Auth.signIn( username: username, password: password, ); return _handleSignInResult(result);}
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { case AuthSignInStep.continueSignInWithMfaSelection: // Handle select from MFA methods case case AuthSignInStep.continueSignInWithMfaSetupSelection: // Handle select from MFA methods available to setup case AuthSignInStep.continueSignInWithEmailMfaSetup: // Handle email setup case case AuthSignInStep.confirmSignInWithOtpCode: // Handle email MFA case case AuthSignInStep.continueSignInWithTotpSetup: // Handle TOTP setup case case AuthSignInStep.confirmSignInWithTotpMfaCode: // Handle TOTP MFA case case AuthSignInStep.confirmSignInWithSmsMfaCode: // Handle SMS MFA case case AuthSignInStep.confirmSignInWithNewPassword: // Handle new password case case AuthSignInStep.confirmSignInWithCustomChallenge: // Handle custom challenge case case AuthSignInStep.resetPassword: // Handle reset password case case AuthSignInStep.confirmSignUp: // Handle confirm sign up case case AuthSignInStep.done: safePrint('Sign in is complete'); }}SMS MFA でサインインを確認する
次のステップが confirmSignInWithSmsMfaCode の場合、Amplify Auth はユーザーに SMS でランダムなコードを送信し、そのコードを確認するのを待っています。このステップを処理するには、アプリの UI でユーザーにコードの入力を促す必要があります。ユーザーがコードを入力したら、その値を confirmSignIn API に渡してください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { case AuthSignInStep.confirmSignInWithSmsMfaCode: final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!; _handleCodeDelivery(codeDeliveryDetails); // ... }}
void _handleCodeDelivery(AuthCodeDeliveryDetails codeDeliveryDetails) { safePrint( 'A confirmation code has been sent to ${codeDeliveryDetails.destination}. ' 'Please check your ${codeDeliveryDetails.deliveryMedium.name} for the code.', );}Future<void> confirmMfaUser(String mfaCode) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: mfaCode, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming MFA code: ${e.message}'); }}TOTP MFA でサインインを確認する
次のステップが confirmSignInWithTOTPCode の場合、セットアップ時に関連付けられた認証アプリから TOTP コードを入力するようユーザーに促してください。コードは 30 秒ごとに変わる 6 桁の数字です。ユーザーは 30 秒のウィンドウが切れる前にコードを入力する必要があります。
ユーザーがコードを入力したら、実装は Amplify Auth の confirmSignIn API にその値を渡す必要があります。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ··· case AuthSignInStep.confirmSignInWithTotpMfaCode: safePrint('Enter a one-time code from your registered authenticator app'); // ··· }}
// Then, pass the TOTP code to `confirmSignIn`
Future<void> confirmTotpUser(String totpCode) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: totpCode, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming TOTP code: ${e.message}'); }}メール MFA でサインインを確認する
次のステップが confirmSignInWithOtpCode の場合、Amplify Auth はユーザーのメールアドレスにランダムなコードを送信し、そのコードを確認するのを待っています。このステップを処理するには、アプリの UI でユーザーにコードの入力を促す必要があります。ユーザーがコードを入力したら、その値を confirmSignIn API に渡してください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { case AuthSignInStep.confirmSignInWithOtpCode: final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!; _handleCodeDelivery(codeDeliveryDetails); // ... }}
void _handleCodeDelivery(AuthCodeDeliveryDetails codeDeliveryDetails) { safePrint( 'A confirmation code has been sent to ${codeDeliveryDetails.destination}. ' 'Please check your ${codeDeliveryDetails.deliveryMedium.name} for the code.', );}Future<void> confirmMfaUser(String mfaCode) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: mfaCode, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming MFA code: ${e.message}'); }}MFA の選択でサインインを続行する
次のステップが continueSignInWithMFASelection の場合、ユーザーは使用する MFA メソッドを選択する必要があります。Amplify Auth は現在、SMS、TOTP、メールを MFA メソッドとしてサポートしています。ユーザーが MFA メソッドを選択したら、実装は confirmSignIn API を使用して選択した MFA メソッドを Amplify Auth に渡す必要があります。
Amplify Auth で現在サポートされている MFA タイプは以下の通りです:
MfaType.smsMfaType.totpMfaType.email
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ··· case AuthSignInStep.continueSignInWithMfaSelection: final allowedMfaTypes = result.nextStep.allowedMfaTypes!; final selection = await _promptUserPreference(allowedMfaTypes); return _handleMfaSelection(selection); // ··· }}
Future<MfaType> _promptUserPreference(Set<MfaType> allowedTypes) async { // ···}
Future<void> _handleMfaSelection(MfaType selection) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: selection.confirmationValue, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error resending code: ${e.message}'); }}メールセットアップでサインインを続行する
次のステップが continueSignInWithEmailMfaSetup の場合、ユーザーはサインインプロセスを完了するためにメールアドレスを提供する必要があります。この値をユーザーから収集したら、confirmSignIn API を呼び出して続行してください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ··· case AuthSignInStep.continueSignInWithEmailMfaSetup: // Prompt user to enter an email address they would like to use for MFA // ··· }}
// Then, pass the email address to `confirmSignIn`
Future<void> confirmEmailUser(String emailAddress) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: emailAddress, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming email address: ${e.message}'); }}TOTP セットアップでサインインを続行する
次のステップが continueSignInWithTOTPSetup の場合、ユーザーはサインインプロセスを完了するために TOTP コードを提供する必要があります。このステップは TOTPSetupDetails 型の関連値を返し、TOTP の生成に使用されます。TOTPSetupDetails は getSetupURI というヘルパーメソッドを提供しており、ネイティブパスワードマネージャーによる TOTP 関連付けに使用できる URI を生成できます。例えば、Apple プラットフォームで URI を使用すると、プラットフォームのネイティブパスワードマネージャーがアカウントと TOTP を関連付けるよう促します。より高度なユースケースでは、TOTPSetupDetails に含まれる sharedSecret を使って QR コードを生成したり、認証アプリに手動で入力したりすることもできます。
認証アプリがセットアップされると、ユーザーは TOTP コードを生成してライブラリに提供し、サインインプロセスを完了できます。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ··· case AuthSignInStep.continueSignInWithTotpSetup: final totpSetupDetails = result.nextStep.totpSetupDetails!; final setupUri = totpSetupDetails.getSetupUri(appName: 'MyApp'); safePrint('Open URI to complete setup: $setupUri'); // ··· }}
// Then, pass the TOTP code to `confirmSignIn`
Future<void> confirmTotpUser(String totpCode) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: totpCode, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming TOTP code: ${e.message}'); }}MFA セットアップ選択でサインインを続行する
次のステップが continueSignInWithMfaSetupSelection の場合、ユーザーはセットアップしたい利用可能な MFA メソッドを選択する必要があります。ユーザーがセットアップする MFA メソッドを選択したら、実装は confirmSignIn API に選択した MFA メソッドを渡す必要があります。
Amplify Auth で現在サポートされている MFA タイプは以下の通りです:
MfaType.smsMfaType.totpMfaType.email
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ··· case AuthSignInStep.continueSignInWithMfaSetupSelection: final allowedMfaTypes = result.nextStep.allowedMfaTypes!; final selection = await _promptUserPreference(allowedMfaTypes); return _handleMfaSelection(selection); // ··· }}
Future<MfaType> _promptUserPreference(Set<MfaType> allowedTypes) async { // ···}
Future<void> _handleMfaSelection(MfaType selection) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: selection.confirmationValue, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error selecting MFA method: ${e.message}'); }}カスタムチャレンジでサインインを確認する
次のステップが confirmSignInWithCustomChallenge の場合、Amplify Auth はカスタム認証チャレンジの完了を待っています。チャレンジは、カスタムサインインフローの一部として設定した AWS Lambda トリガーに基づいています。
例えば、カスタムチャレンジ Lambda がフロントエンドにプロンプトを渡し、ユーザーにシークレットコードの入力を要求する場合があります。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ... case AuthSignInStep.confirmSignInWithCustomChallenge: final parameters = result.nextStep.additionalInfo; final hint = parameters['hint']!; safePrint(hint); // "Enter the secret code" // ... }}このステップを完了するには、ユーザーにカスタムチャレンジの答えを入力するよう促し、その答えを confirmSignIn API に渡す必要があります。
Future<void> confirmCustomChallenge(String answer) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: answer, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming custom challenge: ${e.message}'); }}新しいパスワードでサインインを確認する
次のステップが confirmSignInWithNewPassword の場合、Amplify Auth はサインインを進める前にユーザーが新しいパスワードを選択する必要があります。
ユーザーに新しいパスワードを求め、confirmSignIn API に渡してください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ... case AuthSignInStep.confirmSignInWithNewPassword: safePrint('Please enter a new password'); // ... }}Future<void> confirmNewPassword(String newPassword) async { try { final result = await Amplify.Auth.confirmSignIn( confirmationValue: newPassword, ); return _handleSignInResult(result); } on AuthException catch (e) { safePrint('Error confirming new password: ${e.message}'); }}パスワードのリセット
次のステップが resetPassword の場合、Amplify Auth は続行する前にユーザーがパスワードをリセットする必要があります。
resetPassword API を使用してユーザーをパスワードリセットのフローに案内し、完了したら Amplify.Auth.signIn を呼び出してサインインフローを再開してください。
詳細については、パスワードのリセットのドキュメントをご覧ください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ... case AuthSignInStep.resetPassword: final resetResult = await Amplify.Auth.resetPassword( username: username, ); await _handleResetPasswordResult(resetResult); // ... }}
Future<void> _handleResetPasswordResult(ResetPasswordResult result) async { switch (result.nextStep.updateStep) { case AuthResetPasswordStep.confirmResetPasswordWithCode: final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!; _handleCodeDelivery(codeDeliveryDetails); case AuthResetPasswordStep.done: safePrint('Successfully reset password'); }}
void _handleCodeDelivery(AuthCodeDeliveryDetails codeDeliveryDetails) { safePrint( 'A confirmation code has been sent to ${codeDeliveryDetails.destination}. ' 'Please check your ${codeDeliveryDetails.deliveryMedium.name} for the code.', );}サインアップの確認
次のステップが resetPassword の場合、Amplify Auth は続行する前にユーザーがメールまたは電話番号を確認する必要があります。
resendSignUpCode API を使用して登録済みのメールまたは電話番号に新しいサインアップコードを送信し、その後 confirmSignUp を呼び出してサインアップを完了してください。
詳細については、サインアップの確認のドキュメントをご覧ください。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ... case AuthSignInStep.confirmSignUp: // Resend the sign up code to the registered device. final resendResult = await Amplify.Auth.resendSignUpCode( username: username, ); _handleCodeDelivery(resendResult.codeDeliveryDetails); // ... }}
void _handleCodeDelivery(AuthCodeDeliveryDetails codeDeliveryDetails) { safePrint( 'A confirmation code has been sent to ${codeDeliveryDetails.destination}. ' 'Please check your ${codeDeliveryDetails.deliveryMedium.name} for the code.', );}Future<void> confirmSignUp({ required String username, required String confirmationCode,}) async { try { await Amplify.Auth.confirmSignUp( username: username, confirmationCode: confirmationCode, ); } on AuthException catch (e) { safePrint('Error confirming sign up: ${e.message}'); }}サインアップが確認されたら、Amplify.Auth.signIn を再度呼び出してサインインフローを再開してください。
完了
次のステップが done の場合、サインインフローは完了し、ユーザーは正常に認証されています。
便宜上、SignInResult には isSignedIn プロパティも提供されており、次のステップが done の場合は true になります。
Future<void> _handleSignInResult(SignInResult result) async { switch (result.nextStep.signInStep) { // ... case AuthSignInStep.done: // Could also check that `result.isSignedIn` is `true` safePrint('Sign in is complete'); }}