多要素認証
Amplify Auth は、ユーザーサインインフローにおける多要素認証(MFA)をサポートしています。MFA は、アカウントへのアクセスを試みるユーザーが本人であることを確認するための追加のセキュリティレイヤーです。ユーザーは自分のアイデンティティを確認するために追加情報を提供する必要があります。Amplify Auth は、時間ベースのワンタイムパスワード(TOTP)、テキストメッセージ(SMS)、およびメールによる MFA をサポートしています。
このガイドでは、これらの各方法で MFA を設定する方法を説明し、アプリケーションに適したセットアップを選択するためのトレードオフについて説明します。また、デバイスを記憶する MFA の設定方法と、ユーザーのサインインの手間を軽減する方法についても説明します。
多要素認証の設定
defineAuth を使用してアプリの MFA を有効にします。以下の例は、TOTP で MFA を設定していますが、電話番号が必須属性ではないため、SMS は設定していません。
- SMS を MFA に使用する場合は、
userAttributesでphoneNumber属性を必須としてマークする必要があります。loginWith.phoneがtrueの場合、この属性は自動的に必須としてマークされます。 - メールを MFA に使用する場合は、
email属性もtrueにし、userAttributesで必須としてマークする必要があります。loginWith.emailがtrueの場合、この属性は自動的に必須としてマークされます。
import { defineAuth } from '@aws-amplify/backend';
export const auth = defineAuth({ loginWith: { email: true }, multifactor: { mode: 'OPTIONAL', totp: true, email: true, }, senders: { email: { fromEmail: 'noreply@example.com', fromName: 'My App', }, }, userAttributes: { phoneNumber: { required: true } }});バックエンド auth リソースで MFA が SMS で REQUIRED に設定されている場合、サインアップ API 呼び出し時に電話番号を渡す必要があります。email または username を主要なサインインメカニズムとして使用している場合は、phone_number 属性をユーザー属性として渡す必要があります。
同様に、MFA がメールを配信メカニズムとして REQUIRED に設定されている場合、サインアップ API 呼び出し時にメールアドレスを渡す必要があります。phoneNumber または username を主要なサインインメカニズムとして使用している場合は、email 属性をユーザー属性として渡す必要があります。
この設定は、ユーザープールで有効になっている MFA メソッドの組み合わせによって変わる場合があります。
MFA オプションを理解する
MFA を有効にする際には、2つの重要な決定事項があります:
- MFA の強制: このセットアップの一環として、MFA の強制方法を決定します。MFA モードを
REQUIREDに設定して MFA を必須にすると、すべてのユーザーがサインインするために MFA を完了する必要があります。OPTIONALのままにすると、ユーザーはアカウントの MFA を有効にするかどうかを選択できます。 - MFA メソッド: 使用する MFA メソッドも指定します:TOTP(時間ベースのワンタイムパスワード)、SMS(テキストメッセージ)、メール、またはそれらの組み合わせ。TOTP ベースの MFA の方がより安全であり、SMS やメールはアカウントの回復用に予約できるため、TOTP ベースの MFA の使用をお勧めします。
詳しく見るTOTP、SMS、メール MFA メソッドの比較
| 時間ベースのワンタイムパスワード(TOTP) | ショートメッセージサービス(SMS) | メール | |
|---|---|---|---|
| 説明 | 認証アプリを使用して、共有秘密鍵と現在の時刻を含むユーザー認証用の短命な数値コードを生成します。 | テキストメッセージで共有されるワンタイムコードを生成し、ユーザー認証のために他の資格情報と一緒に入力します。 | ユーザーの登録済みメールアドレスにワンタイムコードを送信します。ユーザーはメールにアクセスしてコードを入力し、認証プロセスを完了する必要があります。 |
| メリット | コードはローカルで生成され、ネットワーク経由で送信されないため、SMS よりも安全です。TOTP アプリがインストールされている限り、携帯電話のサービスなしでも TOTP は機能します。 | ユーザー提供の電話番号で簡単に設定でき、一般的な認証方法として使い慣れています。 | メールはユーザー側で追加のハードウェアやソフトウェア要件を必要としない、広く使用されている馴染みのある通信チャンネルです。 |
| 制約 | コードを生成するアプリが必要で、アカウントの初期設定に追加の手順が加わります。コードはすぐに期限切れになるため、生成後すぐに使用する必要があります。 | SMS は携帯電話サービスを必要とし、ユーザーに追加コストが発生する可能性があります。まれですが、SMS メッセージは傍受される可能性もあります。 | メールサービスの可用性と信頼性に依存します。まれですが、メールは傍受されたり、アカウントが侵害されたりする可能性があります。 |
ユーザーに対して複数の MFA メソッドが有効になっており、そのいずれも優先として設定されていない場合、signIn API は認証フローの次のステップとして CONTINUE_SIGN_IN_WITH_MFA_SELECTION を返します。このシナリオでは、ユーザーにサインインに使用したい MFA メソッドを選択するよう促し、その設定を confirmSignIn に渡す必要があります。
import { confirmSignIn, type SignInOutput } from 'aws-amplify/auth';
function handleSignInNextSteps(output: SignInOutput) { const { nextStep } = output; switch (nextStep.signInStep) { // ... case 'CONTINUE_SIGN_IN_WITH_MFA_SELECTION': const allowedMFATypes = nextStep.allowedMFATypes; const mfaType = promptUserForMFAType(allowedMFATypes); case 'CONFIRM_SIGN_IN_WITH_SMS_CODE': // prompt user to enter otp code delivered via SMS break; case 'CONFIRM_SIGN_IN_WITH_TOTP_CODE': // prompt user to enter otp code from their authenticator app break; case 'CONFIRM_SIGN_IN_WITH_EMAIL_CODE': // prompt user to enter otp code delivered via EMAIL break; // ... }}
type MfaType = 'SMS' | 'TOTP' | 'EMAIL';
function promptUserForMFAType(allowedMFATypes?: MfaType[]): MfaType { // Prompt user to select MFA type}
async function handleMFASelection(mfaType: MfaType) { try { const output = await confirmSignIn({ challengeResponse: mfaType, }); handleSignInNextSteps(output); } catch (error) { console.log(error); }}SMS による多要素認証
上記のように SMS を MFA の第2認証レイヤーとして設定すると、ユーザーはユーザー名とパスワードでサインインした後、サインインを完了するためにテキストメッセージで認証コードを受け取ります。
サインアップ時に SMS MFA を有効にする
サインアップ時にユーザーの SMS MFA を有効にするには、phone_number をユーザー属性として渡す必要があります。ただし、Cognito リソースの主要なサインインメカニズムが phone_number(username を有効にせずに)の場合は、属性として渡す必要はありません。
import { signUp } from 'aws-amplify/auth';
await signUp({ username: "hello@mycompany.com", password: "hunter2", options: { userAttributes: { phone_number: "+15555555555", email: "hello@mycompany.com", }, },});デフォルトでは、confirmSignUp API を使用してサインアップ後にユーザーアカウントを確認する必要があります。これにより、Amazon Cognito の設定に応じて、ユーザーの電話番号またはメールにワンタイムパスワードが送信されます。
import { confirmSignUp } from 'aws-amplify/auth';
await confirmSignUp({ username: "hello@mycompany.com", confirmationCode: "123456",})サインイン時の SMS MFA の管理
ユーザーがサインインした後、アカウントに MFA が有効になっている場合は、ユーザーが電話番号に送信された確認コードを提供する confirmSignIn API を呼び出す必要があるチャレンジが返されます。
MFA が ON またはユーザーに対して有効になっている場合は、電話番号に送信された OTP で confirmSignIn を呼び出す必要があります。
import { confirmSignIn } from 'aws-amplify/auth';
await confirmSignIn({ challengeResponse: "123456"});ユーザーがサインインした後、updateMFAPreference を呼び出して MFA タイプをユーザーに対して有効として記録し、オプションで優先として設定することで、その後のログインがこの MFA タイプをデフォルトで使用するようにします。
import { updateMFAPreference } from 'aws-amplify/auth';
await updateMFAPreference({ sms: 'PREFERRED' });TOTP による多要素認証
Web またはモバイルアプリケーションの多要素認証(MFA)に時間ベースのワンタイムパスワード(TOTP)を使用できます。Amplify Auth カテゴリには、認証アプリを使用した TOTP のセットアップと確認のサポートが含まれており、統合されたソリューションとユーザーのセキュリティ強化を提供します。Google Authenticator、Microsoft Authenticator などのこれらのアプリには TOTP アルゴリズムが組み込まれており、共有秘密鍵と現在の時刻を使用して短命な6桁のパスワードを生成します。
ユーザーの TOTP を設定する
signIn API でユーザーサインインを開始した後、ユーザーが MFA メソッドとして TOTP を設定する必要がある場合、API 呼び出しはアプリで処理すべきチャレンジおよび次のステップとして CONTINUE_SIGN_IN_WITH_TOTP_SETUP を返します。このチャレンジは次の条件が満たされる場合に発生します:
- MFA がユーザープールで 必須 としてマークされている。
- TOTP がユーザープールで有効になっている。
- ユーザーがまだ TOTP MFA を設定していない。
CONTINUE_SIGN_IN_WITH_TOTP_SETUP ステップは、ユーザーがサインインする前に TOTP を設定する必要があることを意味します。このステップは、Microsoft Authenticator や Google Authenticator などの認証アプリを設定するために使用する必要がある TOTPSetupDetails タイプの関連値を返します。TOTPSetupDetails は getSetupURI というヘルパーメソッドを提供し、例えばユーザーのインストール済み認証アプリを開くボタンで使用できる URI を生成します。より高度なユースケースでは、TOTPSetupDetails には QR コードを生成したり、認証アプリに手動で入力したりするために使用できる sharedSecret も含まれています。
認証アプリが設定されると、ユーザーは TOTP コードを生成してライブラリに提供し、サインインプロセスを完了できます。
import { signIn, SignInOutput } from 'aws-amplify/auth';
const output = await signIn({ username: "hello@mycompany.com", password: "hunter2"});
const { nextStep } = output;switch (nextStep.signInStep) { // ... case 'CONTINUE_SIGN_IN_WITH_TOTP_SETUP': const totpSetupDetails = nextStep.totpSetupDetails; const appName = 'my_app_name'; const setupUri = totpSetupDetails.getSetupUri(appName); // Open setupUri with an authenticator APP to retrieve an OTP code break; // ...}TOTP コードは、テキストフィールドやその他の手段でユーザーから取得できます。ユーザーが TOTP コードを提供したら、TOTP コードを challengeResponse パラメータとして confirmSignIn を呼び出します。
import { confirmSignIn } from 'aws-amplify/auth';
await confirmSignIn({ challengeResponse: "123456"});ユーザーがサインインした後、updateMFAPreference を呼び出して MFA タイプをユーザーに対して有効として記録し、オプションで優先として設定することで、その後のログインがこの MFA タイプをデフォルトで使用するようにします。
import { updateMFAPreference } from 'aws-amplify/auth';
await updateMFAPreference({ totp: 'PREFERRED' });ユーザーのサインイン後に TOTP を有効にする
TOTP MFA は、ユーザーがサインインした後に設定できます。これは以下の条件が満たされた場合に可能です:
- MFA がユーザープールで オプション または 必須 としてマークされている。
- TOTP がユーザープールで有効な MFA メソッドとしてマークされている。
TOTP は、Auth カテゴリの setUpTOTP および verifyTOTPSetup API を呼び出すことで設定できます。
setUpTOTP API を呼び出して TOTPSetupDetails オブジェクトを生成します。これは Microsoft Authenticator や Google Authenticator などの認証アプリを設定するために使用する必要があります。TOTPSetupDetails は getSetupURI というヘルパーメソッドを提供し、例えばユーザーのインストール済み認証アプリを開くボタンで使用できる URI を生成します。より高度なユースケースでは、TOTPSetupDetails には QR コードを生成したり、認証アプリに手動で入力したりするために使用できる sharedSecret も含まれています。
sharedSecret を含み、QR コードを生成するか、認証アプリに手動で入力するために使用できます。
import { setUpTOTP } from 'aws-amplify/auth';
const totpSetupDetails = await setUpTOTP();const appName = 'my_app_name';const setupUri = totpSetupDetails.getSetupUri(appName);// Open setupUri with an authenticator APP to retrieve an OTP code認証アプリが設定されると、ユーザーは TOTP コードを生成してライブラリに提供する必要があります。コードを verifyTOTPSetup に渡して TOTP セットアッププロセスを完了します。
import { verifyTOTPSetup } from 'aws-amplify/auth';
await verifyTOTPSetup({ code: "123456" });TOTP セットアップが完了したら、updateMFAPreference を呼び出して MFA タイプをユーザーに対して有効として記録し、オプションで優先として設定することで、その後のログインがこの MFA タイプをデフォルトで使用するようにします。
import { updateMFAPreference } from 'aws-amplify/auth';
await updateMFAPreference({ sms: 'ENABLED', totp: 'PREFERRED' });TOTP デバイスの紛失からの回復
Cognito ユーザープールで MFA が「必須」としてマークされており、別の MFA メソッドが設定されていないシナリオでは、管理者はまず AdminUpdateUserAttributes の呼び出しを開始してユーザーの電話番号属性を更新する必要があります。これが完了したら、管理者は上記のように MFA の設定を SMS に変更できます。
メールによる多要素認証
メール MFA を有効にするには、マルチファクター設定で email: true を設定し、メール送信者を設定します。
import { defineAuth } from '@aws-amplify/backend';
export const auth = defineAuth({ loginWith: { email: true }, multifactor: { mode: 'OPTIONAL', email: true, }, // BE SURE TO PICK A RECOVERY OPTION APPROPRIATE FOR YOUR APPLICATION. accountRecovery: "EMAIL_AND_PHONE_WITHOUT_MFA", senders: { email: { fromEmail: 'noreply@example.com', fromName: 'My App', }, },});上記のようにメールを MFA の第2認証レイヤーとして設定すると、ユーザーはユーザー名とパスワードでサインインした後、サインインを完了するためにメールで認証コードを受け取ります。
サインアップ時に EMAIL MFA を有効にする
サインアップ時にユーザーのメール MFA を有効にするには、email をユーザー属性として渡す必要があります。ただし、Cognito リソースの主要なサインインメカニズムがすでに email(username を有効にせずに)の場合は、属性として渡す必要はありません。
import { signUp } from 'aws-amplify/auth';
await signUp({ username: "+15555555555", password: "hunter2", options: { userAttributes: { email: "hello@mycompany.com", }, },});デフォルトでは、confirmSignUp API を使用してサインアップ後にユーザーアカウントを確認する必要があります。最初の signUp リクエストに続いて、Amazon Cognito の設定に応じて、ユーザーの電話番号またはメールにワンタイムパスコードが送信されます。
import { confirmSignUp } from 'aws-amplify/auth';
await confirmSignUp({ username: "+15555555555", confirmationCode: "123456",})サインイン時の EMAIL MFA の管理
ユーザーがサインインした後、アカウントに MFA が有効になっている場合は、メールアドレスに送信されたユーザー提供の確認コードで confirmSignIn API を呼び出す必要があるチャレンジが発行されます。
MFA が ON またはユーザーに対して有効になっている場合は、メールアドレスに送信された OTP で confirmSignIn を呼び出す必要があります。
import { confirmSignIn } from 'aws-amplify/auth';
await confirmSignIn({ challengeResponse: "123456"});ユーザーがサインインした後、updateMFAPreference を呼び出して MFA タイプをユーザーに対して有効として記録し、オプションで優先として設定することで、その後のログインがこの MFA タイプをデフォルトで使用するようにします。
import { updateMFAPreference } from 'aws-amplify/auth';
await updateMFAPreference({ email: 'PREFERRED' });ユーザーの優先 MFA メソッドを設定する
ユーザープールの設定によっては、特定のユーザーに複数の MFA オプションが利用可能な場合があります。ユーザーがアプリケーションにサインインするたびに MFA メソッドを選択する手間を省くために、Amplify は個々のユーザーの MFA 設定を管理するための 2 つのユーティリティ API を提供しています。
現在のユーザーの MFA 設定を取得する
現在のユーザーの現在の MFA 設定と有効な MFA タイプ(存在する場合)を取得するには、次の API を呼び出します。
import { fetchMFAPreference } from 'aws-amplify/auth';
const { enabled, preferred } = await fetchMFAPreference();現在のユーザーの MFA 設定を更新する
現在のユーザーの MFA 設定を更新するには、次の API を呼び出します。
import { updateMFAPreference } from 'aws-amplify/auth';
await updateMFAPreference({ sms: 'ENABLED', totp: 'PREFERRED' });デバイスを記憶する
デバイスを記憶する機能は、MFA と組み合わせて使用すると便利です。ユーザーがそのデバイスでサインインする際に第2要素の要件が自動的に満たされ、サインイン体験の摩擦が軽減されます。デフォルトでは、この機能はオフになっています。
デバイストラッキングの設定
deviceTracking コンストラクトを使用してデバイストラッキングを設定できます。
import { defineBackend } from '@aws-amplify/backend';import { auth } from './auth/resource';import { data } from './data/resource';
const backend = defineBackend({ auth, data});
const { cfnUserPool } = backend.auth.resources.cfnResources;
cfnUserPool.addPropertyOverride('DeviceConfiguration', { ChallengeRequiredOnNewDevice: true, DeviceOnlyRememberedOnUserPrompt: false});詳しく見るデバイスのトラッキングに使用される主要な用語を理解する
記憶済み、忘れられた、およびトラッキング済みデバイスの扱いにはいくつかの違いがあります。
- トラッキング済み: ユーザーが新しいデバイスでサインインするたびに、成功した認証イベントの終わりにクライアントにデバイスキーが付与されます。このデバイスキーを使用して、
ConfirmDeviceAPI の呼び出しに使用するソルトとパスワードベリファイアを生成します。この時点で、デバイスは「トラッキング済み」とみなされます。デバイスがトラッキング済み状態になると、Amazon Cognito コンソールを使用してトラッキングが開始された時間、最後の認証時間、およびそのデバイスに関するその他の情報を確認できます。 - 記憶済み: 記憶済みデバイスもトラッキングされます。ユーザー認証中に、記憶済みデバイスに割り当てられたデバイスキーとシークレットのペアを使用してデバイスを認証し、ユーザーが以前にサインインに使用したデバイスと同じであることを確認します。
- 記憶されていない: 記憶されていないデバイスは、Cognito がユーザーにデバイスを「オプトイン」で記憶させるよう設定されているが、ユーザーがデバイスを記憶しないことを選択したトラッキング済みデバイスです。このユースケースは、自分のものではないデバイスからアプリケーションにサインインするユーザー向けです。
- 忘れられた: デバイスを記憶またはトラッキングしたくなくなった場合は、
forgetDevice()API を使用してデバイスを記憶済みおよびトラッキング済みの両方から削除できます。