[AWS]Amazon Cognito ユーザープールに MFA を設定する方法


* AWS Cognito における多要素認証（MFA）の設定方法について、主要概念から具体的な設定手順、注意事項、さらにはカスタムUIでの開発要素などをまとめる。



## 1. Cognito における主要概念

- **多要素認証 (MFA) の目的**
   ユーザー認証のセキュリティ強化のため、パスワード（知識要素）に加え、SMS、Eメール、またはタイムベースワンタイムパスワード (TOTP) など、ユーザーが所有する要素を追加して認証を行う。
- **対象ユーザー**
  - **ローカルユーザー**：ユーザープールに直接登録されたユーザー。MFA を利用して追加の認証要素を設定できる。
  - **フェデレーションユーザー**：外部の IdP に認証を委任しているため、Cognito 側では MFA の設定が行われない。
- **MFA の強制設定とオプション設定**
  - **必須（required）**：すべてのユーザーに対して MFA の設定・利用を強制する。
  - **オプション（optional）**：ユーザーが MFA の登録を希望した場合にのみ MFA を利用する。
     ※Hosted UI の表示やユーザーへのプロンプトの挙動も、この設定に応じて変化する。
- **アダプティブ認証**
   リスク評価に応じて、特定のサインイン試行時にのみ追加認証を要求する仕組みを導入できる。

## 2. 設定方法

### コンソールを利用した MFA の設定手順

1. **AWS Cognito コンソールにサインイン**
    AWS Cognito コンソールにログインし、対象のユーザープールを選択するか、新規作成する。
2. **サインインエクスペリエンスの設定**
    ユーザープールの詳細画面で、**[Sign-in experience]（サインインエクスペリエンス）** タブを選択する。
3. **MFA の強制／オプション設定の選択**
    [Multi-factor authentication]（多要素認証）の項目で、以下のいずれかを選択する。
   - **MFA が必要（必須）**：全ユーザーに対して、SMS または TOTP などの追加認証要素でサインインを要求
   - **MFA のオプション**：ユーザーが MFA の登録を希望する場合にのみ MFA コードの入力を求める
   - **MFA なし**：追加認証要素を使用しない
4. **MFA メソッドの選択**
    利用可能な MFA の方法（SMS、Eメール、TOTP）から、使用する方式をチェックして選択する。
   - SMS を利用する場合は、SMS 用の Amazon Simple Notification Service (SNS) の設定が必要。
   - TOTP を利用する場合は、ユーザーが認証アプリ（例：Google Authenticator、Authy など）を利用し、QR コードをスキャンしてセットアップする。
5. **SNS（SMS 用）設定の確認**
    SMS テキストメッセージを MFA の要素として使用する場合、ユーザープールの **[Messaging]（メッセージング）** タブで、SMS の送信に使用する IAM ロールや送信元番号、リージョンなどのパラメータの設定を確認・実施する。
6. **設定の保存**
    すべての設定内容を確認後、[Save changes]（変更の保存）ボタンをクリックして確定する。
7. **動作確認**
    テストユーザーを用いて、実際のサインインフローで MFA が正しく動作するか検証する。



## 3. 設定時の注意事項

- **認証フローへの影響**
  - 新規ユーザーは初回サインイン時に OAuth 2.0 トークンが発行され、その後 MFA 用の追加認証が要求される場合がある。
  - MFA を必須に設定すると、ユーザーはサインインのたびに設定された MFA 要素（SMS、TOTP など）を利用する必要がある。
- **パスワード復旧との関係**
  * ユーザーが希望する MFA の方式によっては、パスワードリセット時に利用できる手段が制限される可能性がある。
     例：SMS を選択した場合、パスワードリセットコードも SMS で送信されるため、事前にユーザーの電話番号やEメールの属性設定および検証が必要。
- **失敗時のロックアウト**
   MFA コードの入力に5回失敗すると、指数関数的なタイムアウトロックアウトプロセスが開始され、一時的にユーザーのアカウントが使用できなくなる可能性がある。
- **SNS サンドボックス**
   SMS を利用する場合、ユーザーの電話番号がSNSサンドボックス内にある場合は、送信前にその電話番号の確認が必要。
- **Hosted UI の挙動**
  - MFA が必須の場合、ホストされた UI は自動的にユーザーに MFA の設定を促すプロンプトを表示する。
  - オプションの場合は、ユーザー自身が MFA の希望設定（SetUserMfaPreference や AdminSetUserPreference API の利用）を行う必要がある。



## 4. カスタムUI実装の場合

Hosted UI では Cognito が認証画面や MFA の処理を自動で行ってくれるが、独自に実装する場合は以下の点に留意する必要がある。

- **自前のUIの実装**

  * ログイン、MFA登録、MFAチャレンジ用の画面を自作し、ユーザーからの入力を受け付ける必要がある。
    たとえば、ユーザーがログイン画面でユーザー名／パスワードを入力した後、MFA が必要な場合は追加でSMSコードまたはTOTPコードの入力画面を表示し、対応するAPIを呼び出す。

- **連携の流れ**

  ```mermaid
  sequenceDiagram
      autonumber
      participant U as ユーザー
      participant UI as カスタムUI
      participant C as Cognito API
      participant AA as 認証アプリ（TOTP用）
  
      %% ログイン・認証開始（ユーザー名/パスワード入力）
      U->>UI: ユーザー名・パスワードを入力（ログイン画面）
      UI->>C: InitiateAuth API呼び出し<br/>(ユーザー認証開始)
      C-->>UI: MFAチャレンジ（セッション情報付）<br/>(MFAが必要な場合)
  
      %% MFAがTOTPの場合：登録フローが未完了なら登録処理
      alt MFAタイプがTOTPかつ未登録の場合
          UI->>C: AssociateSoftwareToken API呼び出し<br/>(TOTP登録用シークレット取得)
          C-->>UI: シークレットキー返却
          UI->>U: QRコード生成して表示<br/>(AssociateSoftwareToken対応)
          U->>AA: 認証アプリでQRコードをスキャンしOTP生成
          U->>UI: OTPを入力（TOTP登録画面）
          UI->>C: VerifySoftwareToken API呼び出し<br/>(OTP検証)
          C-->>UI: TOTP登録成功
          UI->>C: SetUserMfaPreference API呼び出し<br/>(TOTPをMFA優先に設定)
      else MFAタイプがSMSまたはTOTP既登録の場合
          %% ユーザーがMFAコードを入力してチャレンジに応答
          U->>UI: MFAコード（SMSまたはTOTP）を入力（MFAチャレンジ画面）
          UI->>C: RespondToAuthChallenge API呼び出し<br/>(MFAコードとセッション情報を送信)
          C-->>UI: 認証成功／トークン発行
      end
  
      UI->>U: 認証完了（アクセストークン等を表示または内部保持）
  ```

- **必要な開発要素**

  - **UIコンポーネントの実装**
     ログイン画面、MFA登録画面（TOTPの場合）、MFAチャレンジ画面を自作。
  - **API連携と認証フローの実装**
     InitiateAuth、RespondToAuthChallenge、（TOTPの場合は）AssociateSoftwareToken/VerifySoftwareToken、SetUserMfaPreference などのAPI呼び出しを実装する。
  - **セッション管理とエラーハンドリング**
     Cognitoが返すセッション文字列の管理や、MFAコード入力失敗時のリトライ、エラーメッセージの表示を適切に実装する。
  - **SMS MFA の利用時の設定**
     AWS SNS および必要なIAMロールの設定を行い、SMS送信に伴う制約（料金、利用制限、送信先国など）に対応する。

- **開発時の考慮事項と制約**

  - セッションタイムアウト（通常数分）やネットワーク遅延に対応した設計。
  - API呼び出しは HTTPS 経由で行い、認証情報やトークンの安全管理を徹底する。
  - TOTP 登録時にはQRコード生成ライブラリ（例：qrcode.jsなど）を用いてシークレットキーからQRコードを生成する。



## 5. 参考文献

- **Amazon Cognito ユーザープールに MFA を追加します**
   https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-mfa.html
- **TOTP ソフトウェアトークン MFA**
   https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-mfa-totp.html