# 画面設計書 334-OAuth認可エラー

## 概要

本ドキュメントは、GitLabにおけるOAuth認可エラー画面の設計仕様を定義する。

### 本画面の処理概要

OAuth認可エラー画面は、OAuth2.0認可フローにおいてエラーが発生した場合に表示されるエラー画面である。認可リクエストの検証失敗、無効なパラメータ、ユーザーのメール未確認など、様々なエラー状況に対応する。

**業務上の目的・背景**：OAuth2.0認可フローは外部アプリケーションとの連携において重要な役割を果たすが、様々な理由でエラーが発生する可能性がある。不正なクライアントID、無効なリダイレクトURI、サポートされていないスコープ、メール未確認のユーザーなど、エラーの原因は多岐にわたる。本画面は、これらのエラー状況をユーザーに明確に伝え、適切な対処を促すために必要である。開発者にとっても、アプリケーション設定の問題を特定するための重要な情報源となる。

**画面へのアクセス方法**：
1. 外部アプリケーションがGitLab OAuth認可エンドポイントにリダイレクト
2. 認可リクエストの検証でエラーが発生
3. 本エラー画面が表示される

**主要な操作・処理内容**：
1. エラー内容の表示
2. エラー詳細メッセージの確認
3. （可能な場合）問題の修正と再試行

**画面遷移**：
- 遷移元：OAuth認可エンドポイントへのアクセス
- 遷移先：なし（ユーザーはブラウザを閉じるか、修正後に再試行）

**権限による表示制御**：
- ログインユーザー・未ログインユーザー両方に表示される可能性がある
- エラー内容に応じて表示される情報が異なる

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 88 | OAuth2プロバイダ | 主機能 | OAuth認可エラー画面表示 |
| 76 | ユーザー登録 | 補助機能 | メール未確認エラーの処理 |

## 画面種別

エラー表示

## URL/ルーティング

| メソッド | パス | アクション |
|---------|------|-----------|
| GET | `/oauth/authorize` | `oauth/authorizations#new`（エラー発生時にレンダリング） |

## 入出力項目

本画面はエラー表示専用画面であり、ユーザー入力項目はない。

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| Error Description | 出力 | String | - | エラーの詳細説明 |

## 表示項目

| 項目名 | データソース | 表示形式 | 備考 |
|--------|-------------|---------|------|
| ページタイトル | 固定 | 見出し | "An error has occurred" |
| Error Description | @pre_auth.error_response.body[:error_description] | preタグ（整形済みテキスト） | エラーの詳細 |

## イベント仕様

本画面にはユーザー操作可能なイベントはない。エラー情報の表示のみ。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | - | - | データベース更新なし |

本画面はエラー表示のみであり、データベースへの書き込みは行わない。

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|-------------|---------------|---------|
| エラー見出し | - | An error has occurred | 常時表示 |
| エラー詳細 | error_description | 様々（下記参照） | エラー種別による |

### 主なエラーメッセージ

| エラーコード | エラー説明 | 発生条件 |
|-------------|-----------|---------|
| invalid_client | The client identifier provided is invalid. | 無効なclient_id |
| invalid_redirect_uri | The redirect URI included is not valid. | 無効なredirect_uri |
| invalid_scope | The requested scope is invalid, unknown, or malformed. | 無効なスコープ |
| unauthorized_client | The client is not authorized to request an authorization code. | 認可されていないクライアント |
| access_denied | The resource owner or authorization server denied the request. | アクセス拒否 |
| unconfirmed_email | Please verify your email address. | メール未確認 |
| pkce_required_for_dynamic_applications | PKCE is required for dynamic applications. | 動的アプリでPKCE未使用 |
| invalid_code_challenge_method | The code challenge method must be S256. | 無効なcode_challenge_method |

## 例外処理

| 例外状況 | 処理内容 | 表示/遷移先 |
|---------|---------|------------|
| pre_authが存在しない | 一般的なエラー表示 | 本画面 |
| error_responseが空 | 空のエラー詳細 | 本画面 |

## 備考

- エラー画面は最小限のレイアウト（`minimal`レイアウト）で表示される
- エラー詳細はpreタグ内に表示されるため、整形されたテキストとして表示される
- OAuth2.0仕様に準拠したエラーコードとエラー説明が使用される
- メール未確認エラーは、GitLab独自の拡張エラーコード
- 動的アプリケーション（MCP等）ではPKCE必須のエラーが発生する可能性がある

---

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

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

### 推奨読解順序

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

エラーレスポンスの構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Doorkeeper::OAuth::PreAuthorization | Doorkeeper gem内 | pre_authオブジェクトの構造 |
| 1-2 | Doorkeeper::OAuth::ErrorResponse | Doorkeeper gem内 | error_responseの構造 |

**読解のコツ**: Doorkeeper gemの内部クラスを理解することで、エラー情報の取得方法が明確になる。`error_response.body`はHashで、`:error`と`:error_description`キーを持つ。

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

エラー発生時の処理フローを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | authorizations_controller.rb | `app/controllers/oauth/authorizations_controller.rb` | エラーレンダリングの条件 |

**主要処理フロー**:
1. **行25**: `pre_auth.authorizable?` - 認可可能性判定
2. **行37-39**: 認可不可の場合、errorテンプレートをレンダリング
3. **行143-148**: `verify_confirmed_email!` - メール未確認チェック
4. **行167-180**: `validate_pkce_for_dynamic_applications` - PKCEバリデーション

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

シンプルなエラー表示画面。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | error.html.haml | `app/views/doorkeeper/authorizations/error.html.haml` | エラー画面テンプレート |

**主要処理フロー**:
- **行1**: ページヘッダー「An error has occurred」
- **行2-3**: mainロール、preタグでエラー詳細表示

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

```
GET /oauth/authorize
    │
    └─ AuthorizationsController#new
           │
           ├─ verify_confirmed_email!
           │      └─ 未確認の場合: pre_auth.error = :unconfirmed_email
           │                       render "error"
           │
           ├─ verify_admin_allowed!
           │      └─ 禁止の場合: render "forbidden"
           │
           ├─ validate_pkce_for_dynamic_applications
           │      └─ 失敗の場合: pre_auth.error = :pkce_required...
           │                     render "error"
           │
           └─ pre_auth.authorizable?
                  │
                  ├─ Yes: 認可画面表示
                  │
                  └─ No: render "doorkeeper/authorizations/error"
                              └─ @pre_auth.error_response.body[:error_description]
```

### データフロー図

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

認可リクエスト ───▶ AuthorizationsController#new
    │                      │
    │                      ├─ pre_auth = Doorkeeper::OAuth::PreAuthorization.new
    │                      │
    │                      ├─ バリデーション
    │                      │      ├─ client_id チェック
    │                      │      ├─ redirect_uri チェック
    │                      │      ├─ scope チェック
    │                      │      └─ email確認チェック
    │                      │
    │                      └─ エラー発生時
    │                             └─ pre_auth.error_response ───▶ error.html.haml
    │                                    └─ body[:error_description]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| authorizations_controller.rb | `app/controllers/oauth/authorizations_controller.rb` | コントローラ | 認可フロー制御、エラー判定 |
| error.html.haml | `app/views/doorkeeper/authorizations/error.html.haml` | テンプレート | エラー画面表示 |
| doorkeeper.rb | `config/initializers/doorkeeper.rb` | 設定 | Doorkeeper設定 |
| PageHeadingComponent | `app/components/layouts/page_heading_component.rb` | コンポーネント | ページヘッダー |
