Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.
Gen1 DocsLegacy

Page updated Mar 26, 2026

マルチステップサインイン

ユーザーがサインアップを完了した後、サインインに進むことができます。Amplify Auth のサインインフローはマルチステップのプロセスになる場合があります。必要なステップは、MFA 設定の管理ページで説明されているように認証リソースを定義する際に提供した設定によって決まります。

設定によっては、ユーザーのサインインを完了するためにさまざまな API を呼び出す必要がある場合があります。サインインフローの次のステップを特定するには、サインイン結果の nextStep パラメータを確認してください。

新しい列挙値

Amplify が新しい列挙値(例:Kotlin の新しい enum クラスエントリやシールドクラスのサブタイプ、Swift/Dart/Kotlin の新しい enum 値)を追加する場合、Amplify ライブラリの新しいマイナーバージョンが公開されます。列挙値を切り替えるプラグインには、新しい列挙値による影響を受けないようにするためのデフォルトハンドラー(Kotlin の else ブランチや Swift/Dart/Kotlin の default 文)を含める必要があります。

成功した場合、サインイン API は AuthSignInResult を返します。結果の nextStep プロパティを確認して、追加のサインインステップが必要かどうかを確認してください。

func signIn(username: String, password: String) async {
do {
let signInResult = try await Amplify.Auth.signIn(username: username, password: password)
switch signInResult.nextStep {
case .confirmSignInWithSMSMFACode(let deliveryDetails, let info):
print("SMS code sent to \(deliveryDetails.destination)")
print("Additional info \(String(describing: info))")
// Prompt the user to enter the SMSMFA code they received
// Then invoke `confirmSignIn` api with the code
case .confirmSignInWithTOTPCode:
print("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
case .confirmSignInWithOTP(let deliveryDetails):
print("Email code sent to \(deliveryDetails.destination)")
// Prompt the user to enter the Email MFA code they received
// Then invoke `confirmSignIn` api with the code
case .continueSignInWithFirstFactorSelection(let allowedFactors):
print("Received next step as continue sign in by selecting first factor")
print("Allowed factors \(allowedFactors)")
// Prompt the user to select the first factor they want to use
// Then invoke `confirmSignIn` api with the factor
case .confirmSignInWithPassword:
print("Received next step as confirm sign in with password")
// Prompt the user to enter the password
// Then invoke `confirmSignIn` api with the password
case .continueSignInWithTOTPSetup(let setUpDetails):
print("Received next step as continue sign in by setting up TOTP")
print("Shared secret that will be used to set up TOTP in the authenticator app \(setUpDetails.sharedSecret)")
// Prompt the user to enter the TOTP code generated in their authenticator app
// Then invoke `confirmSignIn` api with the code
case .continueSignInWithEmailMFASetup:
print("Received next step as continue sign in by setting up email MFA")
// Prompt the user to enter the email address they wish to use for MFA
// Then invoke `confirmSignIn` api with the email address
case .continueSignInWithMFASetupSelection(let allowedMFATypes):
print("Received next step as continue sign in by selecting MFA type to setup")
print("Allowed MFA types \(allowedMFATypes)")
// Prompt the user to select the MFA type they want to setup
// Then invoke `confirmSignIn` api with the MFA type
case .continueSignInWithMFASelection(let allowedMFATypes):
print("Received next step as continue sign in by selecting MFA type")
print("Allowed MFA types \(allowedMFATypes)")
// Prompt the user to select the MFA type they want to use
// Then invoke `confirmSignIn` api with the MFA type
case .confirmSignInWithCustomChallenge(let info):
print("Custom challenge, additional info \(String(describing: info))")
// Prompt the user to enter custom challenge answer
// Then invoke `confirmSignIn` api with the answer
case .confirmSignInWithNewPassword(let info):
print("New password additional info \(String(describing: info))")
// Prompt the user to enter a new password
// Then invoke `confirmSignIn` api with new password
case .resetPassword(let info):
print("Reset password additional info \(String(describing: info))")
// 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.
case .confirmSignUp(let info):
print("Confirm signup additional info \(String(describing: info))")
// 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.
case .done:
// Use has successfully signed in to the app
print("Signin complete")
}
} catch let error as AuthError{
print ("Sign in failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}

nextStep プロパティは AuthSignInStep という enum 型です。その値に応じて、コードは以下のいずれかのアクションを実行する必要があります:

SMS MFA でサインインを確認する

次のステップが confirmSignInWithSMSMFACode の場合、Amplify Auth はユーザーに SMS でランダムなコードを送信し、ユーザーがそれを正常に受け取ったかどうかを確認するのを待っています。このステップを処理するには、アプリの UI でユーザーにコードの入力を促す必要があります。ユーザーがコードを入力したら、実装は Amplify Auth の confirmSignIn API にその値を渡す必要があります。

注記:サインイン結果には AuthCodeDeliveryDetails メンバーも含まれます。SMS 受信者の部分的な電話番号など、コードの配信に関する追加情報が含まれています。

func confirmSignIn(confirmationCodeFromUser: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: confirmationCodeFromUser)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch let error as AuthError {
print("Confirm sign in failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func confirmSignIn(confirmationCodeFromUser: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(challengeResponse: confirmationCodeFromUser)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

TOTP MFA でサインインを確認する

次のステップが confirmSignInWithTOTPCode の場合、セットアップ時に関連付けられた認証アプリから TOTP コードを入力するようユーザーに促してください。コードは 30 秒ごとに変わる 6 桁の数字です。ユーザーは 30 秒のウィンドウが切れる前にコードを入力する必要があります。

ユーザーがコードを入力したら、実装は Amplify Auth の confirmSignIn API にその値を渡す必要があります。

func confirmSignIn(totpCode: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: totpCode)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch {
print("Confirm sign in failed \(error)")
}
}
func confirmSignIn(totpCode: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(challengeResponse: totpCode)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

メール MFA でサインインを確認する

次のステップが confirmSignInWithOTP の場合、Amplify Auth はユーザーのメールアドレスにランダムなコードを送信し、ユーザーがそれを正常に受け取ったかどうかを確認するのを待っています。このステップを処理するには、アプリの UI でユーザーにコードの入力を促す必要があります。ユーザーがコードを入力したら、実装は Amplify Auth の confirmSignIn API にその値を渡す必要があります。

注記: サインイン結果には AuthCodeDeliveryDetails メンバーも含まれます。受信者の部分的なメールアドレスなど、コードの配信に関する追加情報が含まれています。

func confirmSignIn(confirmationCodeFromUser: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: confirmationCodeFromUser)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch let error as AuthError {
print("Confirm sign in failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func confirmSignIn(confirmationCodeFromUser: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(challengeResponse: confirmationCodeFromUser)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

MFA の選択でサインインを続行する

次のステップが continueSignInWithMFASelection の場合、ユーザーは使用する MFA メソッドを選択する必要があります。Amplify Auth は現在、SMS、TOTP、メールを MFA メソッドとしてサポートしています。ユーザーが MFA メソッドを選択したら、実装は confirmSignIn API を使用して選択した MFA メソッドを Amplify Auth に渡す必要があります。

func confirmSignInWithTOTPAsMFASelection() async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(
challengeResponse: MFAType.totp.challengeResponse)
if case .confirmSignInWithTOTPCode = signInResult.nextStep {
print("Received next step as confirm sign in with TOTP")
}
} catch {
print("Confirm sign in failed \(error)")
}
}
func confirmSignInWithTOTPAsMFASelection() -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(
challengeResponse: MFAType.totp.challengeResponse)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if case .confirmSignInWithTOTPCode = signInResult.nextStep {
print("Received next step as confirm sign in with TOTP")
}
}
}

メールセットアップでサインインを続行する

次のステップが continueSignInWithEmailMFASetup の場合、ユーザーはサインインプロセスを完了するためにメールアドレスを提供する必要があります。この値をユーザーから収集したら、confirmSignIn API を呼び出して続行してください。

// Confirm sign in with Email Setup
case .continueSignInWithEmailMFASetup:
print("Received next step as continue sign in by setting up email MFA")
// Prompt the user to enter the email address they wish to use for MFA
// Then invoke `confirmSignIn` api with the email address

TOTP セットアップでサインインを続行する

次のステップが continueSignInWithTOTPSetup の場合、ユーザーはサインインプロセスを完了するために TOTP コードを提供する必要があります。このステップは TOTPSetupDetails 型の関連値を返し、TOTP の生成に使用されます。TOTPSetupDetailsgetSetupURI というヘルパーメソッドを提供しており、ネイティブパスワードマネージャーによる TOTP 関連付けに使用できる URI を生成できます。例えば、Apple プラットフォームで URI を使用すると、プラットフォームのネイティブパスワードマネージャーがアカウントと TOTP を関連付けるよう促します。より高度なユースケースでは、TOTPSetupDetails に含まれる sharedSecret を使って QR コードを生成したり、認証アプリに手動で入力したりすることもできます。

認証アプリがセットアップされると、ユーザーは TOTP コードを生成してライブラリに提供し、サインインプロセスを完了できます。

// Confirm sign in with TOTP setup
case .continueSignInWithTOTPSetup(let setUpDetails):
/// appName parameter will help distinguish the account in the Authenticator app
let setupURI = try setUpDetails.getSetupUri(appName: "<Your_App_Name>>")
print("TOTP Setup URI: \(setupURI)")
func confirmSignInWithTOTPSetup(totpCodeFromAuthenticatorApp: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(
challengeResponse: totpCodeFromAuthenticatorApp)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch {
print("Confirm sign in failed \(error)")
}
}
func confirmSignInWithTOTPSetup(totpCodeFromAuthenticatorApp: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(
challengeResponse: totpCodeFromAuthenticatorApp)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

MFA セットアップ選択でサインインを続行する

次のステップが continueSignInWithMFASetupSelection の場合、ユーザーはセットアップしたい利用可能な MFA メソッドを選択する必要があります。ユーザーがセットアップする MFA メソッドを選択したら、実装は confirmSignIn API に選択した MFA メソッドを渡す必要があります。

func continueSignInWithEmailMFASetupSelection() async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(
challengeResponse: MFAType.email.challengeResponse)
if case .confirmSignInWithTOTPCode = signInResult.nextStep {
print("Received next step as confirm sign in with TOTP")
}
} catch {
print("Confirm sign in failed \(error)")
}
}
func continueSignInWithEmailMFASetupSelection() -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(
challengeResponse: MFAType.email.challengeResponse)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if case .confirmSignInWithTOTPCode = signInResult.nextStep {
print("Received next step as confirm sign in with TOTP")
}
}
}

カスタムチャレンジでサインインを確認する

次のステップが confirmSignInWithCustomChallenge の場合、Amplify Auth はカスタム認証チャレンジの完了を待っています。チャレンジは、カスタムサインインフローのセットアップ時に設定した Lambda トリガーに基づいています。このステップを完了するには、ユーザーにカスタムチャレンジの答えを入力するよう促し、その答えを confirmSignIn API に渡す必要があります。

func confirmSignIn(challengeAnswerFromUser: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: challengeAnswerFromUser)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch let error as AuthError {
print("Confirm sign in failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func confirmSignIn(challengeAnswerFromUser: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(challengeResponse: challengeAnswerFromUser)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

confirmSignIn の特別な処理

confirmSignIn の呼び出し中に Lambda 関数から failAuthentication=true が返された場合、Cognito によってリクエストのセッションが無効化され、NotAuthorizedException が返されます。その場合、Amplify.Auth.signIn を介して新しいサインイン呼び出しが期待されます。

Exception: notAuthorized{message=Failed since user is not authorized., cause=NotAuthorizedException(message=Invalid session for the user.), recoverySuggestion=Check whether the given values are correct and the user is authorized to perform the operation.}

新しいパスワードでサインインを確認する

次のステップが confirmSignInWithNewPassword の場合、Amplify Auth は続行前にユーザーが新しいパスワードを入力する必要があります。ユーザーに新しいパスワードを求め、confirmSignIn API に渡してください。

func confirmSignIn(newPasswordFromUser: String) async {
do {
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: newPasswordFromUser)
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
} catch let error as AuthError {
print("Confirm sign in failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func confirmSignIn(newPasswordFromUser: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignIn(challengeResponse: newPasswordFromUser)
}.sink {
if case let .failure(authError) = $0 {
print("Confirm sign in failed \(authError)")
}
}
receiveValue: { signInResult in
if signInResult.isSignedIn {
print("Confirm sign in succeeded. The user is signed in.")
} else {
print("Confirm sign in succeeded.")
print("Next step: \(signInResult.nextStep)")
// Switch on the next step to take appropriate actions.
// If `signInResult.isSignedIn` is true, the next step
// is 'done', and the user is now signed in.
}
}
}

パスワードのリセット

resetPassword を受け取った場合、パスワードをリセットしないと認証フローを続行できません。次のステップは resetPassword API を呼び出してパスワードリセットフローを開始することです。完了したら signIn を呼び出してサインインフローを再開してください。

func resetPassword(username: String) async {
do {
let resetPasswordResult = try await Amplify.Auth.resetPassword(for: username)
print("Reset password succeeded.")
print("Next step: \(resetPasswordResult.nextStep)")
} catch let error as AuthError {
print("Reset password failed \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func resetPassword(username: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.resetPassword(for: username)
}.sink {
if case let .failure(authError) = $0 {
print("Reset password failed \(authError)")
}
}
receiveValue: { resetPasswordResult in
print("Reset password succeeded.")
print("Next step: \(resetPasswordResult.nextStep)")
}
}

サインアップの確認

次のステップとして confirmSignUp を受け取った場合、メールや電話番号などのユーザー情報を確認しないとサインアップを続行できません。次のステップは confirmSignUp API を呼び出してサインアップ確認フローを進めることです。

func confirmSignUp(for username: String, with confirmationCode: String) async {
do {
let confirmSignUpResult = try await Amplify.Auth.confirmSignUp(
for: username,
confirmationCode: confirmationCode
)
print("Confirm sign up result completed: \(confirmSignUpResult.isSignUpComplete)")
} catch let error as AuthError {
print("An error occurred while confirming sign up \(error)")
} catch {
print("Unexpected error: \(error)")
}
}
func confirmSignUp(for username: String, with confirmationCode: String) -> AnyCancellable {
Amplify.Publisher.create {
try await Amplify.Auth.confirmSignUp(for: username, confirmationCode: confirmationCode)
}.sink {
if case let .failure(authError) = $0 {
print("An error occurred while confirming sign up \(authError)")
}
}
receiveValue: { _ in
print("Confirm signUp succeeded")
}
}

完了

done が返された場合、サインインフローは完了し、ユーザーは正常に認証されています。便宜上、SignInResult には isSignedIn プロパティも提供されており、次のステップが done の場合は true になります。