[AWS]Amazon Cognitoを用いたマルチテナント構成メモ


## マルチテナント構成の考え方

- マルチテナントSaaSでは、複数のテナント（顧客）が同じアプリケーションを利用する  
このとき、**テナント間のデータ隔離**と**アクセス制御**が重要となる  
    
## Cognitoの主要用語・概念

| 用語                                  | 説明                                                                                                          |
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **User Pool**                       | アプリのユーザを認証（サインアップ／サインイン）するためのディレクトリサービス。ユーザアカウントやパスワード、MFA設定などを管理できる。                                       |
| **Identity Pool**                   | User Poolで認証したユーザに対して、AWSリソースアクセスのための一時的な認証情報（AWSクレデンシャル）を割り当てる仕組み。IAMロールをユーザの属性に合わせてマッピングすることで、柔軟な権限付与が可能。 |
| **グループ (Cognito User Pool Groups)** | User Pool内でユーザをグループに分けて管理する機能。例えば「Admin」「Editor」「Viewer」などの役割で分けたり、マルチテナントではテナントIDごとにグループを割り当てたりできる。        |
| **カスタム属性 (Custom Attributes)**      | ユーザの情報（Eメールや電話番号など標準属性以外）を保持するための拡張属性。マルチテナントの場合は `tenant_id` などの属性を付与してユーザを区別できる。                          |
| **Cognito トリガー (Lambda Triggers)**  | Cognitoでユーザがサインアップ／サインイン／トークン発行されるタイミングなどに合わせて、Lambda関数を実行する仕組み。ユーザの登録プロセスや属性検証、グループへの自動割り当てなどをカスタマイズできる。   |

## 構成パターン1: 単一User Pool + カスタム属性/グループ管理

### 概要

- すべてのテナントのユーザを**一つのUser Pool**で管理し、ユーザに**テナントIDのカスタム属性**や**グループ**を付与する方式  
- アプリケーション側では、ユーザがどのテナントに属しているかをトークン（IDトークンやアクセストークン）内の属性を参照して判別する

```mermaid
flowchart TB
    A[単一のUser Pool] --> B[テナントAユーザ<br>カスタム属性: tenant=A<br>or グループA]
    A[単一のUser Pool] --> C[テナントBユーザ<br>カスタム属性: tenant=B<br>or グループB]
    B --> D[アプリ側がトークンを確認<br>テナントIDを判定]
    C --> D
```
### メリット
- Cognitoの設定や運用がシンプル
- ユーザプール数が1つだけなので、リソースの数が少なく管理が容易
- コストを最小化しやすい（主にUser Poolの月額課金やMAU数の集計が単一になるため）
### デメリット
- テナントごとに厳格な物理的分離を行えない（同じUser Poolを共有する）
- テナントごとに異なるパスワードポリシーやサインアップフローを設定するのが難しい
- User Poolレベルでの制限事項・スロットリングなどを複数テナントで共有するため、大規模になるとスケーラビリティ面での考慮が必要
    
### 適用ケース
- テナント数が多いが、各テナントあたりのユーザ数が比較的少ない場合
- テナント固有の設定要件（パスワードポリシーなど）が少なく、共通化できる場合
- SaaSアプリ開発初期で運用負荷を抑えたい場合

## 構成パターン2: テナントごとに別々のUser Poolを作成

### 概要

テナントごとに**専用のUser Pool**を用意する方式  
テナントAのユーザはUser Pool A、テナントBのユーザはUser Pool B、というように分離する

```mermaid
flowchart LR
    subgraph Tenant A
        A1[User Pool A]
    end
    subgraph Tenant B
        B1[User Pool B]
    end
    A1 -- 認証 --> C[アプリ]
    B1 -- 認証 --> C[アプリ]
```

### メリット
- テナント間での物理的な分離ができる（ユーザデータや設定はプールごとに完全に分離）
- テナントごとにパスワードポリシーやMFA設定などを細かくカスタマイズ可能
- テナント単位での運用・拡張が明確になり、セキュリティ的にも管理しやすい
### デメリット
- テナントが増えるほどUser Poolが増え、管理や運用コストが高くなる    
- 同じアプリから複数のUser Poolに対して認証フローを実装する必要があり、実装が複雑化する
- MAUの合計数をまたいで最適化することが難しくなるケースもある（プールごとの利用状況の差が大きい場合など）
### 適用ケース
- テナントごとのセキュリティ設定・フローを厳密に分ける必要がある場合
- テナントがそこまで多くなく、個別管理がそこまで大変でない場合
- エンタープライズ向けSaaSで、各社向けにカスタマイズ認証フローを提供する場合
    
## 構成パターン3: ハイブリッド構成
### 概要
- 基本的には単一User Poolを使いつつ、要件が特に厳しいテナントについては**専用のUser Pool**を用意する  
- テナント全体を一つのUser Poolでまかなう部分と、いくつかのテナントだけ分割管理する、という柔軟なアプローチ

```mermaid
flowchart LR
    A[単一User Pool<br>多数のテナントを管理] -- 認証 --> C[アプリ]
    B[専用User Pool<br>セキュリティ要件が厳しいテナント] -- 認証 --> C[アプリ]
```

### メリット
- 大半のテナントは単一User Poolで集約管理できるためコストを抑えられる
- 特定のテナントに対してのみ専用Poolを提供し、要望に応じた独立運用や厳格な制御が可能
- テナントのビジネス規模・セキュリティ要件に応じて柔軟に構成できる
### デメリット
- 単一Pool部分と専用Pool部分で構成が異なるため、実装・運用はより複雑になる
- どのテナントを専用Poolとし、どのテナントを共通Poolにするかの判断が必要
### 適用ケース
- 基本は共通フローで問題ないが、一部テナント（大企業や規制業界など）だけ特別なポリシーが必要な場合    
- 認証フローの一元管理と柔軟性を両立させたい場合


## マルチテナント構成方式の比較まとめ

| 方式                             | 概要                                                                       | メリット                                                                               | デメリット                                                                                  | 適用ケース                                                                                                                       |
| ------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **単一User Pool**(カスタム属性やグループ管理) | すべてのテナントのユーザを1つのUser Poolで集約管理し、ユーザごとにテナントIDなどを属性やグループで付与する方式            | - 管理がシンプルで運用しやすい- User Poolが1つだけなので、コストが把握しやすい- 大量のテナントを一括で扱える                     | - テナントごとに物理的な分離ができない- パスワードポリシー等をテナントごとに細かく変更するのが難しい- スロットリングや制限が1つのUser Pool内で共有される   | - テナント数が多いが、認証設定をほぼ共通化できる場合- 開発初期で運用負荷を抑えたい場合- テナント固有の認証要件がそれほど厳しくない場合                                                      |
| **テナントごとUser Pool**            | テナントごとに専用のUser Poolを用意し、ユーザデータや認証設定を完全に分離する方式                            | - 物理的にデータを分離でき、セキュリティ面で安心- パスワードポリシーやMFA設定などをテナント単位で自由に設定できる                       | - テナント数が増えるほどUser Poolの数も増え、管理が煩雑に- アプリ側で複数の認証エンドポイントを扱う実装が必要- 個別のUser Poolごとにコスト管理が必要 | - テナント数が比較的少なく、個別管理が許容できる場合- 各テナントの要件が大きく異なり、分離したい場合- エンタープライズ向けで厳格なセキュリティ要求に対応する場合                                         |
| **ハイブリッド構成**                   | 基本的に単一User Poolを利用しつつ、セキュリティやカスタマイズ要件が厳しい特定のテナントだけ別のUser Poolを用意して分割する方式 | - 大半のテナントは単一User Poolにまとめるため運用・コストを抑えられる- 要件が厳しいテナントには専用User Poolを提供し、柔軟かつ安全に運用できる | - 単一Pool部分と専用Pool部分で構成が異なり、実装が複雑化- テナントの分類（共通Poolに含めるか、専用Poolにするか）の基準を明確にしないと運用が混乱する   | - 一部のテナントだけセキュリティやワークフローが特殊な要件を持つ場合- SaaSアプリとして多くのテナントを集約しながら、一部大企業や規制業界への対応も視野に入れたい場合- 認証を集約したいが、一部で厳格な分離も必要という柔軟性を確保したい場合 |
## 選定基準
1. **テナント数**    
    - テナント数が非常に多い → 単一User Pool (カスタム属性/グループ) もしくはハイブリッド    
    - テナント数が限定的 → テナントごとUser Pool も選択肢に入る
2. **各テナントのカスタマイズ要件**
    - パスワードポリシーや認証フローなどを細かく変えたい → テナントごとUser Pool
    - ほとんど共通化できる → 単一User Pool
3. **セキュリティ・コンプライアンス要件**
    - 規制業界や厳格な物理的分離が必要 → テナントごとUser Pool
    - 過度な分離までは求められない → 単一User Pool でも十分
4. **スケーラビリティ・運用管理**
    - プール数が多くなると管理負荷が上がる → 単一User Pool またはハイブリッド
    - テナントごとに独立運用したい → テナントごとUser Pool
5. **コスト**
    - MAU 課金をまとめて管理したい場合は単一User Pool
    - テナント別コストを明確化したい場合は分割 (ただし個別プールが増えるほど全体コストは増える可能性あり)

## その他プラクティス
- **トークン内のカスタム属性/グループを活用する**  
    単一プール方式をとる場合には、ユーザが属するテナントをトークンで明確に管理し、アプリケーション側で適切に認可を行う
- **Cognito トリガーでの拡張**  
    サインアップやカスタム検証、グループ割り当てなどをLambdaで制御することで、マルチテナントの要件を満たす柔軟な認証フローが可能になる
- **Identity Poolとの連携**  
    AWSリソースにアクセスさせたい場合、ユーザのカスタム属性に応じて権限を振り分ける。テナントごとにポリシーを変える場合は IAM ロールを分けるなどの仕組みを構築する
- **ログ監視と監査**  
    マルチテナントでは誤った権限割り当てがないか監査が重要。CognitoログやCloudTrailなどを使って常にモニタリングを行う
- **拡張性の検討**  
    SaaSのスケールアップに対応できるよう、将来のテナント数や認証要求を見据えてパターンを選ぶ