# 機能設計書 1-ユーザー認証

## 概要

本ドキュメントは、Chatwootシステムにおけるユーザー認証機能の設計を記載する。Devise TokenAuthを使用したメール・パスワード認証を中心に、MFA（多要素認証）対応やSSO認証との連携を含む。

### 本機能の処理概要

本機能は、Chatwootシステムへのユーザーログインを管理し、セキュアなセッション確立を実現する。

**業務上の目的・背景**：カスタマーサポートシステムにおいて、オペレーターやアドミニストレーターの認証は、顧客データの保護とシステムセキュリティの観点から最も重要な機能である。本機能により、正当なユーザーのみがシステムにアクセスし、適切な権限に基づいた操作を行えるようにする。

**機能の利用シーン**：
- エージェントが業務開始時にChatwootダッシュボードへログインする場面
- セッションタイムアウト後の再認証
- MFA有効化済みユーザーの2段階認証
- SSOトークンを使用した自動ログイン

**主要な処理内容**：
1. メールアドレスとパスワードによる認証情報の検証
2. Devise TokenAuthによるトークン生成とHTTPヘッダーへの付与
3. MFA有効ユーザーに対するTOTPコード検証
4. SSOトークンによる自動ログイン処理
5. ログイン履歴（回数、IP、日時）の記録

**関連システム・外部連携**：
- Google OAuth2（OmniAuth統合）
- SAML IdP（SSO認証）
- Redis（SSOトークン管理）

**権限による制御**：認証処理自体は権限制御の前段階であり、認証成功後にAccountUserのrole（agent/administrator）に基づいた認可処理が行われる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ログイン画面 | 主画面 | メール・パスワードによるログイン認証処理 |
| 3 | サインアップ画面 | 参照画面 | 登録後の自動ログイン処理 |
| 90 | MFA設定画面 | 参照画面 | MFA検証が必要な場合のTOTP認証処理 |

## 機能種別

認証処理 / セッション管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| email | String | Yes | ユーザーメールアドレス | 有効なメール形式、存在チェック |
| password | String | Yes | ユーザーパスワード | 認証情報との一致確認 |
| mfa_token | String | No | MFA検証用一時トークン | JWT形式、5分間有効 |
| otp_code | String | No | TOTPワンタイムパスワード | 6桁数字 |
| backup_code | String | No | MFAバックアップコード | 8文字16進数 |
| sso_auth_token | String | No | SSOログイン用トークン | 64文字16進数、5分間有効 |

### 入力データソース

- 画面入力（ログインフォーム）
- データベース（usersテーブル）
- Redis（SSOトークン検証）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| access-token | String | APIアクセス用トークン（HTTPヘッダー） |
| client | String | クライアント識別子（HTTPヘッダー） |
| uid | String | ユーザー識別子（HTTPヘッダー） |
| data | Object | ユーザー情報（id, name, email, accounts等） |
| mfa_required | Boolean | MFA検証が必要な場合true |
| mfa_token | String | MFA検証用一時トークン |

### 出力先

- HTTPレスポンスヘッダー（認証トークン）
- HTTPレスポンスボディ（JSON形式ユーザー情報）
- データベース（usersテーブル - ログイン履歴更新）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ DeviseOverrides::SessionsControllerのcreateアクション

2. SSO認証チェック
   └─ sso_auth_tokenパラメータの存在確認
   └─ 存在する場合、Redisからトークン検証

3. MFA検証リクエストチェック
   └─ mfa_tokenパラメータの存在確認
   └─ 存在する場合、MFA検証フローへ分岐

4. 通常認証処理
   └─ メールアドレスの正規化（小文字変換）
   └─ User.from_emailでユーザー検索
   └─ valid_password?でパスワード検証
   └─ active_for_authentication?で有効性確認

5. MFA有効確認
   └─ user.mfa_enabled?でMFA状態確認
   └─ MFA有効の場合、mfa_tokenを生成して206応答

6. 認証成功処理
   └─ create_tokenでDevise TokenAuth認証トークン生成
   └─ sign_inでセッション確立
   └─ ログイン履歴更新（trackableモジュール）

7. レスポンス返却
   └─ HTTPヘッダーにトークン情報設定
   └─ JSONでユーザー情報返却
```

### フローチャート

```mermaid
flowchart TD
    A[ログインリクエスト受信] --> B{sso_auth_token?}
    B -->|Yes| C[SSO認証処理]
    B -->|No| D{mfa_token?}
    D -->|Yes| E[MFA検証処理]
    D -->|No| F[メール/パスワード検証]
    F --> G{認証成功?}
    G -->|No| H[401エラー返却]
    G -->|Yes| I{MFA有効?}
    I -->|Yes| J[mfa_token生成]
    J --> K[206 Partial Content]
    I -->|No| L[トークン生成]
    C --> L
    E --> M{MFA検証成功?}
    M -->|Yes| L
    M -->|No| N[400/401エラー返却]
    L --> O[ログイン履歴更新]
    O --> P[200 OK + 認証情報]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | メール正規化 | メールアドレスは小文字に変換して処理 | すべてのログインリクエスト |
| BR-002 | MFA優先 | MFA有効ユーザーは必ずTOTP検証を要求 | otp_required_for_login=true |
| BR-003 | SSOトークン有効期限 | SSOトークンは5分間のみ有効 | sso_auth_token使用時 |
| BR-004 | MFAトークン有効期限 | MFAトークンは5分間のみ有効 | mfa_token使用時 |
| BR-005 | バックアップコード使い捨て | 使用されたバックアップコードは無効化 | backup_code使用時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー検索 | users | SELECT | email条件でユーザー取得 |
| トークン保存 | users | UPDATE | tokens, updated_atカラム更新 |
| ログイン履歴更新 | users | UPDATE | sign_in_count, current_sign_in_at, last_sign_in_at, current_sign_in_ip, last_sign_in_ip更新 |
| バックアップコード更新 | users | UPDATE | otp_backup_codes更新（使用済みコードのマスク） |

### テーブル別操作詳細

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | WHERE email = :email | 小文字変換後の値で検索 |
| UPDATE | tokens | JSON形式の認証トークン情報 | Devise TokenAuthが管理 |
| UPDATE | sign_in_count | increment | trackableモジュール |
| UPDATE | current_sign_in_at | Time.now | trackableモジュール |
| UPDATE | last_sign_in_at | 前回のcurrent_sign_in_at | trackableモジュール |
| UPDATE | current_sign_in_ip | request.remote_ip | trackableモジュール |
| UPDATE | last_sign_in_ip | 前回のcurrent_sign_in_ip | trackableモジュール |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | メール/パスワード不一致 | 再入力を促す |
| 401 | Unauthorized | MFAトークン無効/期限切れ | 再ログインを促す |
| 400 | Bad Request | OTPコード不正 | 正しいコード入力を促す |
| 403 | Forbidden | アカウント停止中 | 管理者への連絡を促す |
| 422 | Unprocessable Entity | 必須パラメータ不足 | 入力値確認を促す |

### リトライ仕様

- パスワード認証失敗時のリトライ制限なし（アプリケーションレベル）
- MFA検証失敗時のリトライ制限なし（トークン有効期限内）
- Deviseのlockableモジュールは未使用

## トランザクション仕様

- トークン生成・保存は単一トランザクション
- バックアップコード更新は単一トランザクション
- ログイン履歴更新は認証成功後に自動実行

## パフォーマンス要件

- ログイン処理: 2秒以内
- Redis SSOトークン検証: 100ms以内
- データベースクエリ: emailカラムにインデックスあり

## セキュリティ考慮事項

- パスワードはbcryptでハッシュ化（encrypted_password）
- 認証トークンはHTTPヘッダーで返却（access-token, client, uid）
- OTPシークレットはAES暗号化（Active Record Encryption）
- バックアップコードも暗号化保存
- SSOトークンはRedisで管理（5分間TTL）
- タイミング攻撃対策（secure_compare使用）

## 備考

- Devise TokenAuthの標準機能を継承しつつ、MFA対応のためオーバーライド
- MFA機能は環境変数ENABLE_MFAで有効/無効化可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ユーザーモデルの構造と認証関連のカラムを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | usersテーブルのスキーマ定義、deviseモジュール設定 |
| 1-2 | access_token.rb | `app/models/access_token.rb` | APIアクセストークンの構造 |

**読解のコツ**: user.rbの先頭にあるSchema Informationコメントでテーブル構造を把握し、deviseの各モジュール（:database_authenticatable, :trackable, :two_factor_authenticatable等）の役割を理解する。

#### Step 2: エントリーポイントを理解する

認証リクエストを受け付けるコントローラーの処理フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sessions_controller.rb | `app/controllers/devise_overrides/sessions_controller.rb` | createアクションの分岐処理 |

**主要処理フロー**:
1. **5行目**: before_actionでSSOトークン処理
2. **11-20行目**: createアクションでMFA/SSO/通常認証の分岐
3. **28-37行目**: find_user_for_authenticationでユーザー検証
4. **75-79行目**: handle_mfa_requiredでMFA要求レスポンス生成
5. **82-95行目**: handle_mfa_verificationでMFA検証処理

#### Step 3: MFA認証サービスを理解する

MFA有効ユーザーの認証フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | token_service.rb | `app/services/mfa/token_service.rb` | MFAトークンの生成・検証 |
| 3-2 | authentication_service.rb | `app/services/mfa/authentication_service.rb` | TOTP/バックアップコード認証 |

**主要処理フロー**:
- **token_service.rb 4行目**: MFA_TOKEN_EXPIRY = 5.minutes（トークン有効期限）
- **authentication_service.rb 4-11行目**: authenticateメソッドでOTP/バックアップコード判定

#### Step 4: SSO認証を理解する

SSO認証トークンの生成・検証フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sso_authenticatable.rb | `app/models/concerns/sso_authenticatable.rb` | SSOトークン管理concern |

**主要処理フロー**:
- **4-8行目**: generate_sso_auth_tokenでRedisにトークン保存
- **10-12行目**: invalidate_sso_auth_tokenでトークン無効化
- **14-16行目**: valid_sso_auth_token?でトークン検証

### プログラム呼び出し階層図

```
DeviseOverrides::SessionsController#create
    │
    ├─ process_sso_auth_token (before_action)
    │      └─ User.from_email
    │      └─ user.valid_sso_auth_token?
    │             └─ Redis::Alfred.get
    │
    ├─ [MFA検証] handle_mfa_verification
    │      ├─ Mfa::TokenService#verify_token
    │      └─ Mfa::AuthenticationService#authenticate
    │             ├─ user.validate_and_consume_otp!
    │             └─ Mfa::ManagementService#validate_backup_code!
    │
    ├─ [SSO認証] handle_sso_authentication
    │      └─ authenticate_resource_with_sso_token
    │             └─ user.invalidate_sso_auth_token
    │
    └─ [通常認証] find_user_for_authentication
           ├─ User.from_email
           ├─ user.valid_password?
           └─ user.active_for_authentication?
```

### データフロー図

```
[入力]                    [処理]                         [出力]

email/password ───────▶ SessionsController ───────▶ HTTPヘッダー
                              │                    (access-token, client, uid)
                              ▼
                       User.from_email ────────────▶ JSON Response
                              │                    (user data)
                              ▼
                       valid_password? ────────────▶ users テーブル
                              │                    (login history)
                              ▼
                       [MFA有効?] ─────Yes─────────▶ mfa_token
                              │                    (206 Partial Content)
                              No
                              ▼
                       create_token ───────────────▶ 200 OK
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| user.rb | `app/models/user.rb` | モデル | ユーザーエンティティ、Devise設定 |
| sessions_controller.rb | `app/controllers/devise_overrides/sessions_controller.rb` | コントローラー | ログイン処理のエントリーポイント |
| token_service.rb | `app/services/mfa/token_service.rb` | サービス | MFAトークン管理 |
| authentication_service.rb | `app/services/mfa/authentication_service.rb` | サービス | MFA認証処理 |
| management_service.rb | `app/services/mfa/management_service.rb` | サービス | MFA設定管理 |
| sso_authenticatable.rb | `app/models/concerns/sso_authenticatable.rb` | concern | SSO認証ヘルパー |
| access_tokenable.rb | `app/models/concerns/access_tokenable.rb` | concern | APIトークン生成 |
| routes.rb | `config/routes.rb` | 設定 | 認証エンドポイント定義（3-9行目） |
| auth.json.jbuilder | `app/views/devise/_auth.json.jbuilder` | ビュー | 認証レスポンステンプレート |
