ユニバーサルログインに対するMFA選択をカスタイズする

Auth0は多要素認証(MFA)でユーザーアクセスを確保するための様々な要素をサポートしています。ポストログインを使用することで、MFAフローをカスタマイズし、指定要素または要素のシーケンスでユーザーにチャレンジできます。ユーザーやその所属する組織に関するコンテキスト情報を使用して、より個別化された体験を作成することも可能です。例えば、特定の組織への所属やユーザーに割り当てられた役割に基づいて、特定の要素でユーザーにチャレンジするようにフローをカスタマイズすることができます。

仕組み

アクションを使用して、MFAフローをカスタマイズできます。具体的には、ログインフローポストログイントリガーを、以下の認証APIメソッドを使用して変更できます:

  • challengeWith:ワンタイムパスワード(OTP)といった要素または、ユーザー認証に使用する必要のある要素を指定します。このメソッドはデフォルトのチャレンジをユーザーに提示し、オプションでファクターピッカーを提供して、異なる認証方法を選択できるようにします。

  • challengeWithAny:メールやOTPといった、ユーザーが認証時に選択できるファクターのグループを設定します。デフォルトで、この方法は、次の条件に従って、ユーザーに特定のチャレンジではなく、ファクターピッカーを提示します:

    • 複数のファクターが指定された場合、ファクターピッカーはユーザーに表示されます。

    • ユーザーが指定ファクターの一つ(または提供されたファクターが一つ)にのみに登録した場合、ファクターピッカーはスキップされます。

    • ユーザーがどの指定ファクターにも登録していない場合、コマンドは失敗します。

これらの方法を組み合わせて、必要に応じてMFAフローをカスタマイズできます。役割や以前使用したファクターなどのユーザーメタデータをこれらの方法に組み込むことで、よりカスタマイズされたフローを作成できます。

コマンドでMFAチャレンジを選択する際には、以下のファクターやenrolledFactorsの値を使用できます。enrolledFactorsは、ユーザーのアカウントに関連付けられたアクティブなファクターのリストを表します。

  • otp

  • email

  • push-notification

    • otpFallback

  • phone

    • preferredMethod: voice

    • preferredMethod: sms

    • preferredMethod: both

  • webauthn-platform

  • webauthn-roaming

event.authentication.methodsの配列には、方法の名前がmfaタイプに設定されている場合に typeフィールドが含まれています。タイプは上記のenrolledFactorstypeフィールドで使用されるファクター値と一致する文字列です。MFAチャレンジが実行されると、methods にはname:mfaのオブジェクトが含まれ、 typeがそのチャレンジに使用されるファクターに設定されます。methodsはアクションが開始されたときにのみ更新されます。チャレンジの結果を見るには、methodsがフローの次のアクションにアクセスされていなければなりません。

詳しくは、以下のリソースをご確認ください:

シーケンス化されたフローとコンテキストに基づくフロー

challengeWithchallengeWithAnyコマンドを使用することで、コンテキスト情報を活用してユーザーに提示する最適なチャレンジやチャレンジのシリーズを決定できます。具体的には以下のものを活用できます:

  • シーケンス化されたフロー:ユーザーに対して、特定の順序に並べた、一連の異なる要素でチャレンジを行います。

  • コンテキストに基づくフロー:フロー内での以前のチャレンジに基づいて、次にどの要素でユーザーにチャレンジするかを決定します。

これらのフローを説明するために、次の例を考えてみましょう:

// ACTION 1 

exports.onExecutePostLogin = async (event, api) => {

   api.authentication.challengeWithAny([{ type: 'phone'}, { type: 'push-notification' }]);

} 

// ============================================ 

// ACTION 2 

// Decide based on what the user did in the previous action 

exports.onExecutePostLogin = async (event, api) => { 

    if(event.authentication.methods.find(m => m.type === 'phone') && event.authorization?.roles.includes('admin')) { 

        api.authentication.challengeWith({ type: 'push-notification' }); 

    }

}

Was this helpful?

/

このシナリオでは、アクション1でユーザーはまず、challengeWithAny コマンドを通じてSMSでチャレンジされます。次に、アクション2ではユーザーはプッシュ通知でチャレンジされます。これは、ユーザーがAdminロールを持っており、SMSチャレンジも完了しているからです。

このフローでは、次の理由から、ユーザーをどの要素でチャレンジするかを決定することができます:

  1. フローがアクション1実行後に停止するため。

  2. ユーザーがアクション1で促されたMFAフローを完了するため。

  3. アクション2のevent.authentication.methods.typeは、以前のMFAチャレンジからの情報を入力します。

  4. このフローは、アクション1からのコンテキストに基づく情報を使用して、 アクション2の実行に進みます。

この例は、アクション内でリダイレクトを使用するのと似た体験を提供しますが、 challengeWithおよびchallengeWithAnyコマンドを使用することで、以下のような独自の利点があります:

  • フローは各コマンド後に停止するため、以降のアクションで使用できるユーザー情報を蓄積できます。比較すると、リダイレクトはフローの最終コマンドとして一度だけ発生します。

  • MFAは、challengeWithchallengeWithAnyコマンドを含む各アクションが実行された後にトリガーされます。リダイレクトの場合、MFAはパイプラインの最終アクションとして実行されます。

注意:アクションを実行するこの方法は、 challengeWithまたはchallengeWithAnyを含むものにしか適用されません。その他の目的を果たすアクションに影響はありません。

開始する前に

MFAフローをカスタマイズする前に、まず、テナントでMFAを有効にし、ユーザーに適切な要素に登録するように促します。

テナントの準備をする

はじめに、テナントでMFAを設定し、アクション設定を使用して、MFA要素のカスタマイズを有効にします。[Auth0 Dashboard]の [セキュリティ]>[多要素認証] から、1つ以上の要素を設定し、MFAポリシーを定義することができます。

フローのカスタマイズには、[追加設定]セクションのアクショントグルを使用して、[MFA要素のカスタマイズ]を有効にする必要があります。この設定が無効になっている場合、カスタマイズされたフローは、正常に作動しません。

[Auth0 Dashboard]>[Security(セキュリティ)]>[MFA(多要素認証)]>[Additional Settings(追加設定)]

要素にユーザーを登録する

MFAが構成されると、有効にした1つ以上の要素にユーザーを登録するようにしてください。ユーザーは、ポストログインアクションコマンドにチャレンジされる前にAuthenticatorに登録する必要があります。

ユーザーがサインアップまたはテナントで作成された後、Management APIauthentication-methodsエンドポイントを使用して登録を作成する必要があります。または、Auth0 Dashboardのプロファイルページから直接ユーザーの登録を管理することができます。

MFAフローをカスタマイズする

テナントの準備が整ったら、ポストログインアクションを作成して、MFAフローをカスタマイズできます。以下が、そのステップとユースケース例になります。

ポストログインアクションを作成する

  1. [Auth0 Dashboard]で、[アクション]>[フロー]に移動し、 [ログイン]を選択します。

  2. 追加アクションの下の、[カスタム]を選択し、[アクションの作成]を選択します。

  3. アクションの作成のポップアップでの表示:

    • アクションの名前を入力します。

    • トリガーとして、 ログイン/ポストログインを選択します。

    • ランタイムには、Node 18(推奨)を使用します。

  4. 正確性のために、ポップアップをご確認ください。その後、 [作成]を選択します。

  5. 作成後、コードエディターがonPostExecuteコマンドを表示します。カスタムコードまたはコードサンプルをコマンドに追加します。

  6. コマンドの準備が整ったら、[導入]を選択します。

  7. 成功した導入通知で[フローの追加]を選択します。

    • 注意:通知が閉じられている場合、コードエディターの上の[フローに戻る]を選択します。

  8. 新しいコマンドを「アクションの追加」パネルから、ログインフローにドラッグアンドドロップします。その後、[適用]を選択します。

アクションに追加の更新を行う場合、[アクション]>[ライブラり]>[カスタム]に移動し、コマンドを選択します。その後、必要な時にコードの更新と再導入ができます。

ポストログインアクションをテストする

コマンドが適切に機能するように、Auth0 Dashboardを通じてアクションをテストできます:

  • [認証]>[認証プロファイル]に移動します。

  • [試す]を選択し、新しいタブでログインプロンプトのサンプルを開きます。

  • 資格情報を入力し、新しいMFAフローをテストします。

フローが成功したら、確認画面が表示されます。問題が生じたら,、Auth0 Dashboardの[アクション]>[ライブラリ]>[カスタム]に移動し、コードを更新することができます。

ユースケース例

以下の例では、MFAフローをカスタマイズする際の一般的なユースケースを示しています。

現在の登録を使用して、チャレンジ方法を決定する

次のサンプルは、ユーザーが以下のファクターに登録されている場合にMFAでチャレンジを行います。

  • ワンタイムパスワード(OTP)

  • Phone(電話番号)

exports.onExecutePostLogin = async (event, api) => {

 api.authentication.challengeWithAny([{type: 'otp'}, {type: 'phone'}]);

}

Was this helpful?

/

ロールを使用して、チャレンジ方法を決定する

次のサンプルは、すべてのユーザーに対してOTPでチャレンジを行います。ユーザーがAdminロールを持ち、アプリケーションへのより高いレベルのアクセスが必要な場合、ステップアップ認証の一環として追加の要素でチャレンジされます。

exports.onExecutePostLogin = async (event, api) => {
    api.authentication.challengeWith({type: 'otp'});

    const isAdmin = event.authorization?.roles.includes('admin');
    if(isAdmin) {
        api.authentication.challengeWith({type: 'phone'});
    }
}

Was this helpful?

/

メタデータを使用して、チャレンジ方法を決定する

この例では、MFA要素は組織レベルで有効になっています。このサンプルはメタデータの異なるカテゴリーを使用して、個々のユーザーに対する正しいチャレンジを決定します:

  • Organizationメタデータ:指定要素などのOrganizationレベルデータは、Organizationに対して有効になっています。

  • ユーザーメタデータ:ユーザープロファイルに関連づいた電話番号を持っているかどうかなどの、ユーザーレベルのデータ。

exports.onExecutePostLogin = async (event, api) => {
  const orgFactors = event.organization?.metadata.factors.split(',') ?? [];

  // Get the intersection of factors available for the user and factors enabled for the org
  const availableFactors = orgFactors.filter(f => event.user?.enrolledFactors?.some(ef => ef.type === f));

  // Prefer push if available
  if(availableFactors.includes('push-notification')) {
    api.authentication.challengeWith({ type: 'push-notification' });
    return;
  }

  // If the user has a verified phone number and the organization
  // allows for SMS and email, prefer SMS and allow email as a fallback
  // if available
  if(event.user.phone_number && 
     event.user.phone_verified && 
     availableFactors.includes('phone')) {
    if(availableFactors.includes('email')) {
      api.authentication.challengeWith({ type: 'phone' }, {
        additionalFactors: [{
          type: 'email'
        }]
      });
    } else {
      api.authentication.challengeWith({ type: 'phone' });
    }

    return;
  }

  // If push-notifications and/or phone couldn't be prioritized, fallback to email if
  // enabled for the org, otherwise fail.
  if(availableFactors.includes('email')) {
    api.authentication.challengeWith({ type: "email" });
    return;
  }

  api.access.deny("No MFA factors available for this org + user");
};

Was this helpful?

/

ユーザーが別の認証方法を選択できるようにします。

より柔軟な体験を提供するために、MFAチャレンジの一部としてユーザーに他の方法を試すリンクを提示することができます。このリンクにより、ユーザーはデフォルトチャレンジの代わりに別の認証方法を選択することができます。

そのためには、アクションコードにadditionalFactorsパラメーターを含めてください。このパラメーターをすべてのユーザーに対して指定の要素に設定するか、enrolledFactorsを使用してユーザーに好みの要素を選択させることができます。

指定要素

次のサンプルでは、デフォルトで、OTPでユーザーにチャレンジを行います。必要であれば、ユーザーは「他の方法を試す」リンクにアクセスし、代わりにメールで認証することができます。

exports.onExecutePostLogin = async (event, api) => {
  api.authentication.challengeWith({ type: 'otp' }, 
    { additionalFactors: [{type: 'email'}] })
};

Was this helpful?

/

登録済み要素

次のサンプルでは、デフォルトで、OTPでユーザーにチャレンジを行います。必要であれば、ユーザーは「他の方法を試す」リンクにアクセスし、その他の登録済み要素の1つで認証することができます。

exports.onExecutePostLogin = async (event, api) => {
  const enrolledFactors = event.user.enrolledFactors.map((f) => ({type: f.type}));

  api.authentication.challengeWith({ type: 'otp' }, 
    { additionalFactors: enrolledFactors })
};

Was this helpful?

/

Adaptive MFAを使用して、ユーザーにチャレンジを行うタイミングを決定する

次のサンプルでは、Adaptive MFAを使用して、ユーザーにチャレンジを行うべきかどうかを決定します。

Adaptive MFAは、ログイン取引中のリスクを評価し、適切な場合に追加の検証をユーザーに求めることで、不正者からテナントを保護する柔軟なMFAポリシーです。

この場合、ユーザーが認識されていないデバイスからログインし、全体的な信頼スコアが低いまたは中程度の場合にMFAが求められます。

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  if (event.authentication?.riskAssessment?.assessments.NewDevice) {

  // Example condition: prompt MFA only based on the NewDevice 
    // confidence level, this will prompt for MFA when a user is logging in 
    // from an unknown device.
    let shouldPromptMfa;

    switch (event.authentication.riskAssessment.assessments.NewDevice.confidence) {
      case 'low':
      case 'medium':
        shouldPromptMfa = true;
        break;
      case 'high':
        shouldPromptMfa = false;
        break;
      case 'neutral':
        // When this assessor has no useful information about the confidence, 
        // do not prompt MFA.
        shouldPromptMfa = false;
        break;
    }

      // It only makes sense to prompt for MFA when the user has at least one 
      // enrolled MFA factor.
    const canPromptMfa = event.user.enrolledFactors?.length > 0;

    if (shouldPromptMfa && canPromptMfa) {
      const enrolledFactors = event.user.enrolledFactors.map((f) => ({type: f.type}));
      api.authentication.challengeWithAny(enrolledFactors);
    }

  }

};

Was this helpful?

/

アクションを使用して、ユーザーにチャレンジを行う

ログインフローの ポストログインを修正することで、アクションを使用して、MFAをカスタマイズできます。この例では、認証と preferredMethod:'both'phone方法を使用します。は、ユーザーのアカウントに関連付けられたアクティブなMFA要素を示します。詳しくは、アクションのトリガー: ポストログイン - イベントオブジェクトを参照してください。

api.authentication.challengeWith({ 
  type: 'phone', 
  options: { preferredMethod: 'both'} 
});

Was this helpful?

/

トラブルシューティング

カスタマイズされたMFAフローでエラーや予期しない結果が発生した場合は、以下の情報を使用して問題を特定し解決するのに役立ててください。

テナントログ

テナントログを通じて、カスタマイズされたMFAフローを監視できます。

テナントログは、Auth0 Dashboardの[モニタリング]>[ログ]から利用可能です。その他に、Management APIを使用して、ログを取得します。

予期しない動作が発生した場合は、次のイベントコードのテナントログを確認して、詳細情報を得てください。

シナリオ イベントコード エラーの説明
ユーザーに多要素認証が求められますが、要求されたいずれの要素もチャレンジに使用できません。この場合、ユーザーはMFAを完了できません。 mfar このシナリオでは、次のエラーメッセージが表示されます:

An MFA challenge is used in a PostLogin action but the requested factors are not properly set up.To perform MFA, enable the requested factors and ensure the user is enrolled with them.(PostLoginアクションはMFAチャレンジを使用していますが、要求された要素が適切にセットアップされていません。MFAを実行するには、要求された要素を有効にして、ユーザーがそれらで登録していることを確認してください。)
ユーザーに多要素認証が求められますが、要求された要素の1つがチャレンジに使用できません。この場合、ユーザーは要求されている別の要素を使ってMFAを完了することができます。 w このシナリオでは、次のエラーメッセージが表示されます:

An MFA challenge is used in a PostLogin action, but the requested factor {factor name} is not properly set up.Enable the requested factor and ensure the user is enrolled with it.(PostLoginアクションはMFAチャレンジを使用していますが、要求された要素の{factor name}が適切にセットアップされていません。要求された要素を有効にして、ユーザーがそれを使って登録していることを確認してください。)

トラブルシューティングのチェックリスト

以下のチェックリストは、カスタマイズされたMFAフローに関する一般的な問題を特定し解決するための追加の提案を提供します。

  1. 「アクションでMFA要素をカスタマイズする」トグルを有効にする必要があります。

  2. アクションで参照されるファクターは、テナントで有効にする必要があります。

  3. ユーザーはアクションで参照された要素に登録されている必要があります。

    • エラーが発生した場合は、対象ユーザーの詳細を確認し、適切なファクターに登録されていることを確認してください。[Auth0 Dashboard]>[ユーザー管理]>[ユーザー]に移動し、リストからユーザーの名前を選択します。

      • [詳細]タブの[多要素認証]セクションを確認し、ユーザーの登録を確認します。ユーザーが登録されていない場合、このセクションで利用可能な「登録の招待状を送る」リンクを使用できます。

      • または、[Raw JSON(生JSON)]タブでユーザーの登録状況を確認してください。この情報は、Management APIを使用することでも取得できます。ただし、APIには、メール認証リンクを介して設定されたメール要素のような自動登録された認証手段は表示されないことに注意が必要です。

    • ユーザーが適切な要素に登録されていない場合、Management APIのauthentication-methodsエンドポイントを使用して、登録を作成できます。Auth0 Dashboardのユーザーのプロファイルページを通じて、ユーザーの登録を直接管理することもできます。

  4. アクションが導入され、パイプラインに保存されていることを確認してください。

    • [Auth0 Dashboard]>[アクション]>[ライブラリ]>[カスタム]に移動します。リストからアクションを見つけ、ステータスが「導入済み」になっていることを確認してください。異なるステータスが表示 されている場合、アクションにアクセスし、コードを確認したのち,右上の[導入]をクリックします。

    • [Auth0 Dashboard]>[アクション]>[ライブラリ]>[フロー]に移動し、 [ログイン]を選択します。アクションがフローに表示されていることを確認してください。表示されていない場合、[アクションの追加]パネルの[カスタム]タブにアクセスし、ログインフローにアクションをドラッグアンドドロップします。その後、[適用]を選択します。

  5. ポストログインアクションが最新バージョンにアップグレードされていることを確認してください。