# 画面設計書 7-2要素認証画面

## 概要

本ドキュメントは、GitLabの2要素認証画面の設計仕様を記載したものです。2要素認証（2FA）が有効なユーザーがログイン時に認証コードを入力する画面です。

### 本画面の処理概要

**業務上の目的・背景**：2要素認証画面は、パスワード認証に加えて追加のセキュリティ層を提供します。ユーザーがパスワードで認証した後、TOTP（Time-based One-Time Password）アプリやハードウェアセキュリティキー（WebAuthn）、または緊急時にはリカバリーコードを使用して本人確認を行います。これにより、パスワードが漏洩した場合でも不正アクセスを防止し、アカウントセキュリティを大幅に向上させます。

**画面へのアクセス方法**：
- ログイン画面でパスワード認証成功後、2FAが有効なユーザーに自動的に表示
- セッションタイムアウト後の再認証時

**主要な操作・処理内容**：
1. TOTP認証アプリからの6桁コード入力
2. リカバリーコードの入力（TOTPデバイス紛失時）
3. WebAuthn（セキュリティキー）による認証
4. メールOTPフォールバック（設定時）
5. 認証コードの検証
6. セッション作成

**画面遷移**：
- 遷移元：ログイン画面（パスワード認証成功後）
- 遷移先：ダッシュボード（2FA認証成功時）、ログイン画面（認証失敗・キャンセル時）

**権限による表示制御**：
- 2FA認証待ち状態のユーザーのみがアクセス可能
- WebAuthnが登録されている場合はWebAuthn UIが優先表示される
- メールOTPフォールバックは設定で有効化される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | 2要素認証 | 主機能 | 2FAコードの入力・検証処理 |

## 画面種別

認証フォーム

## URL/ルーティング

| HTTPメソッド | URL | アクション |
|-------------|-----|----------|
| GET | `/users/sign_in` | 2FA認証画面表示（ログインフロー内） |
| POST | `/users/sign_in` | 2FA認証処理 |

## 入出力項目

### 入力項目

| 項目名 | 物理名 | 型 | 必須 | 最大長 | 説明 |
|--------|--------|-----|------|--------|------|
| 認証コード | user[otp_attempt] | string | Yes | 32 | TOTPコードまたはリカバリーコード |
| Remember me | user[remember_me] | boolean | No | - | セッション永続化（前画面から引き継ぎ） |
| WebAuthnレスポンス | user[device_response] | string | 条件付き | - | WebAuthn認証レスポンス |

## 表示項目

| 項目名 | 説明 | 条件 |
|--------|------|------|
| 認証コード入力フォーム | TOTP/リカバリーコード入力欄 | 常時表示 |
| 説明テキスト | コード入力またはリカバリーコード使用の説明 | 常時表示 |
| Verify codeボタン | 認証コード検証ボタン | 常時表示 |
| WebAuthn認証UI | セキュリティキー認証用JavaScript UI | WebAuthn登録時 |
| メールOTPオプション | メールでのOTP受信オプション | メールOTPフォールバック有効時 |
| エラーメッセージ | 認証エラー表示領域 | エラー発生時 |

## イベント仕様

### 1-Verify codeボタン押下

**トリガー**: 「Verify code」ボタンクリック

**処理フロー**:
1. 認証コードの形式検証
2. OTP検証サービス呼び出し
3. TOTPコードまたはリカバリーコードの検証
4. 認証成功時のセッション作成
5. 監査ログ記録
6. ダッシュボードにリダイレクト

**成功時**: ダッシュボードまたは元のページにリダイレクト
**失敗時**: エラーメッセージを表示して2FA画面に戻る

### 2-WebAuthn認証

**トリガー**: WebAuthn UIでの認証開始

**処理フロー**:
1. WebAuthnチャレンジの取得
2. ブラウザWebAuthn API呼び出し
3. セキュリティキーでの認証
4. 認証レスポンスの検証
5. セッション作成

### 3-メールOTPフォールバック

**トリガー**: メールOTPオプション選択

**処理フロー**:
1. ワンタイムパスワードのメール送信
2. OTP入力フォーム表示
3. OTP検証

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 2FA認証成功 | users | UPDATE | ログイン情報更新 |
| 2FA認証成功 | authentication_events | INSERT | 認証イベント記録 |
| 2FA認証成功 | audit_events | INSERT | 監査ログ記録 |
| リカバリーコード使用 | users | UPDATE | 使用済みリカバリーコード無効化 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sign_in_count | +1 | 認証成功時 |
| UPDATE | current_sign_in_at | 現在時刻 | 認証成功時 |
| UPDATE | last_sign_in_at | 旧current_sign_in_at | 認証成功時 |
| UPDATE | otp_backup_codes | リカバリーコード除去 | リカバリーコード使用時 |

#### authentication_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | 認証ユーザーID | - |
| INSERT | result | success | 認証結果 |
| INSERT | provider | two_factor/two_factor_webauthn | 認証方式 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|------------|------|---------------|----------|
| MSG001 | エラー | Invalid two-factor code | OTPコード無効時 |
| MSG002 | ヒント | Enter the code from your two-factor authenticator app. If you've lost your device, you can enter one of your recovery codes. | フォーム説明文 |
| MSG003 | エラー | Invalid recovery code | リカバリーコード無効時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 認証コード無効 | エラーメッセージを表示して2FA画面に戻る |
| リカバリーコード使用済み | エラーメッセージを表示 |
| WebAuthn認証失敗 | TOTPフォームにフォールバック |
| セッションタイムアウト | ログイン画面にリダイレクト |
| 連続認証失敗 | アカウントロックの可能性（設定による） |

## 備考

- 認証コードは数字6桁（TOTP）または英数字（リカバリーコード）
- TOTPコードの有効期間は通常30秒
- WebAuthnが登録されている場合はWebAuthn UIが優先表示される
- リカバリーコードは一度使用すると無効化される
- inputmode="numeric" によりモバイルでは数字キーボードが表示される
- Remember meは前のログインフォームから隠しフィールドで引き継がれる

---

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

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

### 推奨読解順序

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

2要素認証に関連するユーザーモデルの属性を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | otp_secret、otp_backup_codes、webauthn_registrations関連 |

**読解のコツ**: `devise :two_factor_authenticatable` によりTOTP機能、`devise :two_factor_backupable` によりリカバリーコード機能が有効化される（112-117行目）。

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

コントローラーの認証処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sessions_controller.rb | `app/controllers/sessions_controller.rb` | authenticate_with_two_factor処理 |
| 2-2 | authenticates_with_two_factor.rb | `app/controllers/concerns/authenticates_with_two_factor.rb` | 2FA認証ロジック |

**主要処理フロー**:
- **sessions_controller.rb 26-27行目**: `authenticate_with_two_factor` prepend_before_action
- **sessions_controller.rb 309-315行目**: `valid_otp_attempt?` メソッド

#### Step 3: ビューテンプレートを理解する

画面の構成要素を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | two_factor.html.haml | `app/views/devise/sessions/two_factor.html.haml` | 2FA画面エントリーポイント |
| 3-2 | _totp_recovery_code_or_webauthn.html.haml | `app/views/devise/shared/_totp_recovery_code_or_webauthn.html.haml` | 実際のフォーム |

**主要処理フロー**:
- **_totp_recovery_code_or_webauthn.html.haml 5-17行目**: TOTPフォーム
- **_totp_recovery_code_or_webauthn.html.haml 23-24行目**: WebAuthn認証UI

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

```
SessionsController#create
    │
    ├─ authenticate_with_two_factor (prepend_before_action)
    │      │
    │      ├─ find_user (session[:otp_user_id])
    │      │
    │      ├─ valid_otp_attempt?
    │      │      └─ Users::ValidateManualOtpService.execute
    │      │             ├─ User.validate_and_consume_otp!
    │      │             └─ verify_totp_code
    │      │
    │      ├─ (OR) user.invalidate_otp_backup_code!
    │      │
    │      └─ (OR) WebAuthn認証
    │             └─ webauthn_authentication_data
    │
    └─ sign_in(user)
           └─ セッション作成
```

### データフロー図

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

user[otp_attempt]     ───▶ SessionsController#create ───▶ セッションCookie
(or device_response)         │
                             ├─ Users::ValidateManualOtpService
                             │      └─ TOTP検証 または リカバリーコード検証
                             │
                             ├─ sign_in(user) ───▶ users テーブル UPDATE
                             │
                             └─ Auditor.audit ───▶ audit_events テーブル INSERT
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sessions_controller.rb | `app/controllers/sessions_controller.rb` | コントローラー | ログイン・2FA処理の制御 |
| authenticates_with_two_factor.rb | `app/controllers/concerns/authenticates_with_two_factor.rb` | Concern | 2FA認証ロジック |
| user.rb | `app/models/user.rb` | モデル | ユーザーデータと2FA設定 |
| two_factor.html.haml | `app/views/devise/sessions/two_factor.html.haml` | ビュー | 2FA画面エントリーポイント |
| _totp_recovery_code_or_webauthn.html.haml | `app/views/devise/shared/_totp_recovery_code_or_webauthn.html.haml` | ビュー | 2FAフォームパーシャル |
| validate_manual_otp_service.rb | `app/services/users/validate_manual_otp_service.rb` | サービス | OTP検証サービス |
