# 画面設計書 2-SSOログイン画面

## 概要

本ドキュメントは、Chatwootアプリケーションのシングルサインオン（SSO）ログイン画面に関する設計書です。SAML認証によるエンタープライズ向け認証機能を提供する画面について記述しています。

### 本画面の処理概要

SSOログイン画面は、SAML認証プロトコルを使用したシングルサインオン機能を提供します。企業の既存ID基盤（Active Directory、Okta、Azure AD等）と連携し、統一された認証体験を実現します。

**業務上の目的・背景**：エンタープライズ環境では、従業員が複数のシステムにアクセスする際、個別のパスワード管理は非効率かつセキュリティリスクとなります。本画面は、企業の既存認証基盤と連携することで、ユーザーは社内システムと同じ認証情報でChatwootにアクセスでき、IT管理者は一元的なアクセス制御と監査が可能になります。これはEnterprise版限定の機能であり、大規模組織向けのセキュリティ要件に対応しています。

**画面へのアクセス方法**：ブラウザで `/app/login/sso` にアクセスするか、通常のログイン画面から「SAMLでログイン」リンクをクリックして遷移します。Enterprise版が有効でない環境ではアクセスできません。

**主要な操作・処理内容**：
1. 企業メールアドレスを入力してSAML認証を開始する
2. 認証リクエストがSAMLプロバイダー（IdP）にリダイレクトされる
3. IdPでの認証完了後、Chatwootにリダイレクトされる
4. 通常ログイン画面に戻るリンクを使用する

**画面遷移**：
- 遷移元：通常ログイン画面（SAMLログインリンク）
- 遷移先：SAML IdP認証ページ（外部）、通常ログイン画面（戻るリンク）、ダッシュボードホーム画面（認証成功後）

**権限による表示制御**：
- Enterprise版が有効な環境でのみアクセス可能
- SAML設定が完了している場合のみ認証処理が実行される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | SSO認証 | 主機能 | SAML認証によるシングルサインオンログイン |

## 画面種別

ログイン（認証）

## URL/ルーティング

| パス | ルート名 | 説明 |
|------|----------|------|
| `/app/login/sso` | `sso_login` | SSOログイン画面 |

### クエリパラメータ

| パラメータ | 型 | 説明 |
|-----------|-----|------|
| `error` | String | エラーコード（SAML認証失敗時） |
| `target` | String | 認証後のリダイレクト先（`web`等） |

### ルートメタ情報

| メタキー | 値 | 説明 |
|---------|-----|------|
| `requireEnterprise` | `true` | Enterprise版が必要 |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | バリデーション | 説明 |
|--------|--------|-----|------|----------------|------|
| 企業メールアドレス | `email` | text | Yes | required, email形式 | SAML認証用の企業メールアドレス |

### 隠しフィールド

| 項目名 | 項目ID | 説明 |
|--------|--------|------|
| CSRFトークン | `authenticity_token` | CSRF保護用トークン |
| ターゲット | `target` | 認証後のリダイレクト先 |

### 出力項目

認証成功時はダッシュボードにリダイレクトされるため、本画面での出力項目はありません。

## 表示項目

| 項目名 | 説明 | 表示条件 |
|--------|------|----------|
| ロゴ | アプリケーションロゴ（ライト/ダークモード対応） | 常時 |
| タイトル | 「SAMLでサインイン」 | 常時 |
| 企業メールアドレス入力欄 | SAML認証用メールアドレス入力 | 常時 |
| サインインボタン | SAML認証開始ボタン | 常時 |
| 通常ログインリンク | 通常ログイン画面へ戻るリンク | 常時 |

## イベント仕様

### 1-サインインボタン押下

**トリガー**: サインインボタンのクリックまたはフォーム送信

**処理フロー**:
1. フロントエンドでメールアドレスのバリデーション実行
   - 必須チェック
   - メールアドレス形式チェック
2. フォームを `POST /api/v1/auth/saml_login` にネイティブ送信
3. バックエンドがメールドメインからSAML IdPを特定
4. SAML認証リクエストを生成
5. ユーザーをIdPの認証ページにリダイレクト
6. IdPで認証完了後、Chatwootのコールバックエンドポイントにリダイレクト
7. 認証成功時: 認証情報を設定し、ダッシュボードにリダイレクト
8. 認証失敗時: エラーパラメータ付きでログイン画面にリダイレクト

**データフロー**:
```
[ユーザー入力]
    │
    ▼
[バリデーション]
    │
    │ 成功
    ▼
[POST /api/v1/auth/saml_login]
    │
    ▼
[SAML IdP特定]
    │
    ▼
[IdP認証ページへリダイレクト]
    │
    ▼
[IdPで認証]
    │
    ├─ 成功 ─▶ [コールバック] → [ダッシュボードへ]
    │
    └─ 失敗 ─▶ [エラーリダイレクト] → [ログイン画面]
```

### 2-通常ログインリンク押下

**トリガー**: 「通常のログイン画面に戻る」リンクのクリック

**処理フロー**:
1. `/app/login` にルーター遷移
2. 通常ログイン画面を表示

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| SAML認証開始 | - | - | クライアント側ではDB更新なし |
| SAML認証成功（コールバック） | users | UPDATE/INSERT | ユーザー情報の更新または新規作成 |

### テーブル別更新項目詳細

SAML認証のコールバック処理はバックエンドで実行されるため、詳細はバックエンド設計書を参照してください。

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|---------------|---------------|----------|
| LOGIN.SAML.API.ERROR_MESSAGE | エラー | SAML認証に失敗しました | SAML認証エラー時 |

## 例外処理

| 例外条件 | 状態・動作 |
|---------|----------|
| Enterprise版が無効 | ルートガードによりアクセス拒否 |
| SAML設定が未完了 | 認証エラーとして処理 |
| IdP接続エラー | エラーパラメータ付きでログイン画面にリダイレクト |
| SAML応答の署名検証失敗 | 認証エラーとして処理 |
| ユーザーが存在しない（JIT無効） | `no-account-found`エラーでリダイレクト |
| メールドメインが未登録 | 認証エラーとして処理 |

## 備考

- フォーム送信はネイティブのPOST送信を使用し、API呼び出しではない
- CSRFトークンはmetaタグから取得され、隠しフィールドとして送信される
- SAML認証フローはサーバーサイドリダイレクトで制御される
- Enterprise版限定機能のため、`requireEnterprise`メタ情報がルートに設定されている
- ダークモードに対応しており、システム設定に応じてロゴ画像が切り替わる
- `target`パラメータにより、認証後のリダイレクト先を指定可能（モバイルアプリ連携等）

---

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

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

### 推奨読解順序

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

SAML認証で扱われるフォームデータとリクエスト形式を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Saml.vue | `app/javascript/v3/views/login/Saml.vue` | フォームデータ構造（email, authenticity_token, target） |

**読解のコツ**: Vue 3のComposition APIで記述されています。`<script setup>`構文を使用しており、`ref`と`computed`でリアクティブなデータを管理しています。

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

処理の起点となるVueコンポーネントを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Saml.vue | `app/javascript/v3/views/login/Saml.vue` | SSOログイン画面のメインコンポーネント |
| 2-2 | routes.js | `app/javascript/v3/views/routes.js` | ルーティング定義、`requireEnterprise`メタ情報 |

**主要処理フロー**:
1. **行27-29**: `credentials`リアクティブ変数でメールアドレスを管理
2. **行46-53**: バリデーションルール定義（required, email形式）
3. **行60-67**: `onMounted`でCSRFトークン取得とエラーハンドリング
4. **行96**: フォームがネイティブPOST送信（`action="/api/v1/auth/saml_login"`）

#### Step 3: バックエンドSAML処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | saml_controller.rb | `app/controllers/api/v1/auth/saml_controller.rb` | SAML認証のエントリーポイント |
| 3-2 | routes.rb | `config/routes.rb` | SAML関連ルーティング |

**主要処理フロー**:
- メールドメインからSAML設定を特定
- SAML認証リクエストを生成
- IdPへのリダイレクトを実行
- コールバックでSAML応答を検証
- ユーザー認証情報を設定

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

```
Saml.vue (SSOログイン画面)
    │
    ├─ [ネイティブフォーム送信]
    │      │
    │      └─ POST /api/v1/auth/saml_login
    │             │
    │             └─ [Backend] saml_controller#create
    │                    │
    │                    ├─ SAML IdP特定
    │                    │
    │                    └─ IdPへリダイレクト
    │                           │
    │                           ▼
    │                    [IdP認証ページ]
    │                           │
    │                           ▼
    │                    [コールバック]
    │                    /api/v1/auth/saml_callback
    │                           │
    │                    ┌──────┴──────┐
    │                    ▼             ▼
    │               [成功]         [失敗]
    │                 │              │
    │                 ▼              ▼
    │            ダッシュボード   エラーリダイレクト
    │
    └─ router-link
           └─ /app/login（戻るリンク）
```

### データフロー図

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

credentials.email    ──▶   Saml.vue                     ──▶   IdPへリダイレクト
authenticity_token         (ネイティブPOST送信)
target                          │
                               ▼
                          POST /api/v1/auth/saml_login
                               │
                               ▼
                          [Backend]
                          saml_controller
                               │
                               ▼
                          SAML Request生成
                               │
                               ▼
                          IdPリダイレクト
                               │
                               ▼
                          [IdP認証]
                               │
                               ▼
                          コールバック
                               │
                     ┌─────────┴─────────┐
                     ▼                   ▼
                [認証成功]            [認証失敗]
                     │                   │
                     ▼                   ▼
               ダッシュボード       ログイン画面
               リダイレクト         (error付き)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Saml.vue | `app/javascript/v3/views/login/Saml.vue` | ソース | SSOログイン画面メインコンポーネント |
| routes.js | `app/javascript/v3/views/routes.js` | ソース | ルーティング定義 |
| FormInput.vue | `app/javascript/v3/components/Form/Input.vue` | ソース | 入力フォームコンポーネント |
| Button.vue | `app/javascript/dashboard/components-next/button/Button.vue` | ソース | ボタンコンポーネント |
| saml_controller.rb | `app/controllers/api/v1/auth/saml_controller.rb` | ソース | SAML認証コントローラー |
| en.json | `app/javascript/dashboard/i18n/locale/en/login.json` | 設定 | i18n翻訳ファイル |
