# 機能設計書 2-OmniAuth統合

## 概要

本ドキュメントは、ChatwootシステムにおけるOmniAuth統合機能の設計を記載する。Google OAuth2およびSAML認証を使用した外部認証プロバイダーとの連携を実現する。

### 本機能の処理概要

本機能は、外部認証プロバイダー（Google、SAML IdP）を使用したソーシャルログイン機能を提供し、ユーザーの認証プロセスを簡素化する。

**業務上の目的・背景**：エンタープライズ環境では、組織の既存ID管理システム（Google Workspace、企業IdP）との連携が必須となる。本機能により、ユーザーは既存の認証情報を使用してChatwootにログインでき、パスワード管理の負担を軽減するとともに、組織のセキュリティポリシーとの整合性を確保する。

**機能の利用シーン**：
- Google Workspaceを使用している企業のエージェントがGoogleアカウントでログイン
- SAML対応のIdP（Okta、Azure AD等）を使用した企業向けSSO
- 新規ユーザーがソーシャルアカウントで初回アカウント作成

**主要な処理内容**：
1. OAuth2/SAML認証フローの開始とコールバック処理
2. 認証プロバイダーからのユーザー情報取得
3. 既存ユーザーの照合またはアカウント新規作成
4. SSOトークン生成とログイン画面へのリダイレクト
5. アバター画像の自動取得・設定

**関連システム・外部連携**：
- Google OAuth2 API
- SAML 2.0 IdP（Okta、Azure AD、OneLogin等）
- Redis（SSOトークン一時保存）

**権限による制御**：認証成功時は自動的にadministratorロールでアカウントに紐付けられる（新規アカウント作成時）。既存ユーザーの場合は既存のロールが維持される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ログイン画面 | 主画面 | Google OAuth2によるソーシャルログイン |
| 2 | SSOログイン画面 | 参照画面 | SAML認証への遷移 |
| 3 | サインアップ画面 | 参照画面 | OAuth経由での新規アカウント作成 |

## 機能種別

認証連携 / OAuth2 / SAML

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| provider | String | Yes | 認証プロバイダー名（google_oauth2, saml） | 登録済みプロバイダーのみ |
| auth_hash | Hash | Yes | OmniAuthからの認証情報ハッシュ | - |
| auth_hash.info.email | String | Yes | ユーザーメールアドレス | 有効なメール形式 |
| auth_hash.info.name | String | No | ユーザー表示名 | - |
| auth_hash.info.image | String | No | プロフィール画像URL | - |
| auth_hash.info.email_verified | Boolean | No | メール確認済みフラグ | - |

### 入力データソース

- OmniAuthミドルウェア（認証プロバイダーからのコールバック）
- 環境変数（OAuth2クライアントID/シークレット）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| redirect_url | String | リダイレクト先URL（ログイン画面 + SSOトークン） |
| error | String | エラー発生時のエラーコード |
| sso_auth_token | String | SSOログイン用一時トークン |

### 出力先

- HTTPリダイレクトレスポンス
- Redis（SSOトークン保存）
- データベース（新規ユーザー/アカウント作成時）

## 処理フロー

### 処理シーケンス

```
1. OAuth認証フロー開始
   └─ ユーザーがログイン画面で「Googleでログイン」をクリック
   └─ OmniAuthが認証プロバイダーへリダイレクト

2. 認証プロバイダーでの認証
   └─ ユーザーが認証プロバイダーで認証
   └─ 認可コード/SAMLアサーションの発行

3. コールバック受信
   └─ /auth/:provider/callbackエンドポイントで受信
   └─ OmniAuthCallbacksControllerのomniauth_successアクション

4. ユーザー照合
   └─ auth_hash.info.emailでUser検索
   └─ 既存ユーザーの場合: sign_in_user処理
   └─ 新規ユーザーの場合: sign_up_user処理

5. 既存ユーザー処理（sign_in_user）
   └─ メール確認をスキップ
   └─ SSOトークン生成
   └─ ログイン画面へリダイレクト（email + sso_auth_token）

6. 新規ユーザー処理（sign_up_user）
   └─ アカウント作成許可チェック
   └─ ビジネスドメインメールチェック
   └─ AccountBuilderでユーザー・アカウント作成
   └─ アバター画像取得ジョブ投入
   └─ パスワードリセット画面へリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[OAuth認証開始] --> B[認証プロバイダー]
    B --> C[コールバック受信]
    C --> D[get_resource_from_auth_hash]
    D --> E{既存ユーザー?}
    E -->|Yes| F[sign_in_user]
    E -->|No| G{signup許可?}
    G -->|No| H[エラー: no-account-found]
    G -->|Yes| I{ビジネスドメイン?}
    I -->|No| J[エラー: business-account-only]
    I -->|Yes| K[create_account_for_user]
    K --> L[AccountBuilder.perform]
    L --> M[Avatar取得ジョブ]
    M --> N[パスワードリセット画面へリダイレクト]
    F --> O[SSOトークン生成]
    O --> P[ログイン画面へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | アカウント作成許可 | ENABLE_ACCOUNT_SIGNUPがfalseの場合、新規ユーザー作成不可 | 新規ユーザーの場合 |
| BR-002 | ビジネスドメイン制限 | フリーメールドメインでのサインアップを制限可能 | 新規ユーザーの場合 |
| BR-003 | 自動メール確認 | OAuth認証成功時は自動的にメール確認済みとする | 既存ユーザーの場合 |
| BR-004 | 管理者ロール付与 | 新規アカウント作成時、最初のユーザーはadministratorロール | 新規アカウント作成時 |
| BR-005 | アバター自動取得 | 認証プロバイダーのプロフィール画像を自動取得 | image URLが存在する場合 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー検索 | users | SELECT | email条件でユーザー取得 |
| ユーザー作成 | users | INSERT | 新規ユーザーレコード作成 |
| アカウント作成 | accounts | INSERT | 新規アカウントレコード作成 |
| アカウントユーザー作成 | account_users | INSERT | ユーザーとアカウントの紐付け |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | WHERE email = :email | 小文字変換後の値で検索 |
| INSERT | name | auth_hash.info.name | 新規ユーザー作成時 |
| INSERT | email | auth_hash.info.email | 新規ユーザー作成時 |
| INSERT | confirmed_at | Time.now | email_verified=true時 |
| UPDATE | confirmed_at | Time.now | 既存ユーザーの確認スキップ時 |

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | ドメイン名（TLD除く） | AccountBuilder経由 |
| INSERT | locale | I18n.locale | 現在のロケール |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| no-account-found | リダイレクトエラー | 既存ユーザー不在かつsignup無効 | 管理者にアカウント作成依頼 |
| business-account-only | リダイレクトエラー | フリーメールでのsignup試行 | ビジネスメールで再試行 |
| OAuth認証失敗 | OmniAuthエラー | 認証プロバイダーでの認証失敗 | 再認証を促す |

### リトライ仕様

- OAuth認証失敗時は再度認証フローを開始可能
- コールバック処理のリトライは不要（ステートレス）

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

- AccountBuilderによるユーザー・アカウント作成はActiveRecord::Transactionで囲まれる
- いずれかの作成に失敗した場合は全てロールバック

## パフォーマンス要件

- OAuth認証フロー: 外部プロバイダー依存
- コールバック処理: 1秒以内
- SSOトークン生成: 100ms以内

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

- OAuth2クライアントシークレットは環境変数で管理
- SSOトークンは64文字の暗号学的乱数
- SSOトークンの有効期限は5分間
- CSRF対策はOmniAuthの標準機能で実装
- SAML署名検証はruby-saml gemで実装

## 備考

- OmniAuthプロバイダーの設定は`config/initializers/devise.rb`で行う
- 新規プロバイダー追加時はomniauthable設定の更新が必要

---

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

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

### 推奨読解順序

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

OmniAuthからの認証情報（auth_hash）の構造を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | omniauthable設定、プロバイダー定義 |

**読解のコツ**: 68行目の`omniauth_providers: [:google_oauth2, :saml]`で対応プロバイダーを確認。auth_hashの構造はOmniAuth gemの仕様に依存。

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

OmniAuthコールバックコントローラーの処理フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | omniauth_callbacks_controller.rb | `app/controllers/devise_overrides/omniauth_callbacks_controller.rb` | omniauth_successアクション |

**主要処理フロー**:
1. **4-8行目**: omniauth_successで既存/新規ユーザーを分岐
2. **12-19行目**: sign_in_userでSSO認証トークン生成
3. **35-43行目**: sign_up_userで新規アカウント作成
4. **62-65行目**: get_resource_from_auth_hashでユーザー検索
5. **74-83行目**: create_account_for_userでAccountBuilder呼び出し

#### Step 3: アカウント作成サービスを理解する

新規アカウント作成時のAccountBuilderの処理を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | account_builder.rb | `app/builders/account_builder.rb` | performメソッドの処理フロー |

**主要処理フロー**:
- **7-16行目**: performメソッドでトランザクション実行
- **34-36行目**: validate_emailでメールバリデーション
- **46-49行目**: create_accountでアカウント作成
- **60-66行目**: link_user_to_accountでadministratorロール付与

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sso_authenticatable.rb | `app/models/concerns/sso_authenticatable.rb` | トークン生成・検証メソッド |

**主要処理フロー**:
- **4-8行目**: generate_sso_auth_tokenでRedis保存
- **18-21行目**: generate_sso_linkでリダイレクトURL生成

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

```
DeviseOverrides::OmniauthCallbacksController#omniauth_success
    │
    ├─ get_resource_from_auth_hash
    │      └─ User.from_email
    │
    ├─ [既存ユーザー] sign_in_user
    │      ├─ resource.skip_confirmation!
    │      └─ resource.generate_sso_auth_token
    │             └─ Redis::Alfred.setex
    │
    └─ [新規ユーザー] sign_up_user
           ├─ account_signup_allowed?
           │      └─ GlobalConfigService.load
           │
           ├─ validate_signup_email_is_business_domain?
           │      └─ Account::SignUpEmailValidationService
           │
           └─ create_account_for_user
                  ├─ AccountBuilder.perform
                  │      ├─ Account.create!
                  │      ├─ User.create!
                  │      └─ AccountUser.create!
                  │
                  └─ Avatar::AvatarFromUrlJob.perform_later
```

### データフロー図

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

認証プロバイダー            OmniauthCallbacksController
(Google/SAML) ─────────▶   omniauth_success
                                  │
auth_hash ────────────────▶ get_resource_from_auth_hash ──▶ [既存ユーザー?]
  │                               │                              │
  │                               ▼                              │
  │                         sign_in_user ◀───────────────Yes─────┘
  │                               │                              │
  │                               ▼                              │
  │                         generate_sso_auth_token ─────▶ Redis
  │                               │
  │                               ▼
  │                         redirect_to ─────────────────▶ /app/login?sso_auth_token=xxx
  │
  │
  └──────────────────────▶ sign_up_user ◀────────────────No──────┘
                                  │
                                  ▼
                          AccountBuilder.perform ────────▶ accounts, users, account_users
                                  │
                                  ▼
                          redirect_to ───────────────────▶ /app/auth/password/edit
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| omniauth_callbacks_controller.rb | `app/controllers/devise_overrides/omniauth_callbacks_controller.rb` | コントローラー | OAuthコールバック処理 |
| account_builder.rb | `app/builders/account_builder.rb` | ビルダー | アカウント・ユーザー作成 |
| sso_authenticatable.rb | `app/models/concerns/sso_authenticatable.rb` | concern | SSOトークン管理 |
| user.rb | `app/models/user.rb` | モデル | OmniAuth設定 |
| sign_up_email_validation_service.rb | `app/services/account/sign_up_email_validation_service.rb` | サービス | メールドメイン検証 |
| avatar_from_url_job.rb | `app/jobs/avatar/avatar_from_url_job.rb` | ジョブ | アバター画像取得 |
| routes.rb | `config/routes.rb` | 設定 | OAuthコールバックルート（8行目） |
