# 画面設計書 8-Passkey認証画面

## 概要

本ドキュメントは、GitLabのPasskey認証画面の設計仕様を記載したものです。Passkeyによるパスワードレス認証を行う画面です。

### 本画面の処理概要

**業務上の目的・背景**：Passkey認証画面は、FIDO2/WebAuthnベースのパスワードレス認証を提供します。Passkeyは従来のパスワードに代わる新しい認証方式で、生体認証（指紋、顔認証）やハードウェアセキュリティキーを使用して、フィッシング耐性のある安全な認証を実現します。ユーザーはパスワードを入力する必要がなく、デバイスに保存されたPasskeyを使用して直接ログインできます。

**画面へのアクセス方法**：
- ログイン画面の「Passkey」ボタンをクリック
- `/users/passkeys/sign_in` への POST リクエスト

**主要な操作・処理内容**：
1. WebAuthn認証チャレンジの生成
2. ブラウザのPasskey UI表示
3. ユーザーによる生体認証またはセキュリティキー認証
4. 認証レスポンスの検証
5. セッション作成とダッシュボードへのリダイレクト

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

**権限による表示制御**：
- Passkey機能が有効（フィーチャーフラグ `passkeys`）な場合のみアクセス可能
- パスワード認証が有効な場合のみ利用可能（標準認証の代替として）
- Passkeyが登録されているユーザーのみが実際の認証を完了可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | 2要素認証 | 主機能 | Passkeyによる認証処理 |

## 画面種別

認証画面（JavaScript駆動）

## URL/ルーティング

| HTTPメソッド | URL | アクション |
|-------------|-----|----------|
| POST | `/users/passkeys/sign_in` | Passkey認証画面表示・処理開始 |

## 入出力項目

### 入力項目

| 項目名 | 物理名 | 型 | 必須 | 最大長 | 説明 |
|--------|--------|-----|------|--------|------|
| Remember me | remember_me | boolean | No | - | セッション永続化（ログイン画面から引き継ぎ） |
| WebAuthnレスポンス | device_response | JSON | Yes | - | Passkey認証レスポンス |

## 表示項目

| 項目名 | 説明 | 条件 |
|--------|------|------|
| ページタイトル | 「Sign in with passkeys」（スクリーンリーダー用） | 常時表示 |
| Passkey認証UI | JavaScriptによるWebAuthn認証UI | 常時表示 |
| ローディング表示 | 認証処理中の待機表示 | 認証処理中 |
| エラーメッセージ | 認証エラー表示 | エラー発生時 |

## イベント仕様

### 1-Passkey認証開始

**トリガー**: ページ読み込み完了時に自動的に認証フロー開始

**処理フロー**:
1. WebAuthn認証オプションの取得（チャレンジ、許可されたクレデンシャルID等）
2. ブラウザ `navigator.credentials.get()` API呼び出し
3. ユーザーによるPasskey選択・認証（生体認証/PIN等）
4. 認証レスポンスの取得
5. サーバーへの認証レスポンス送信
6. サーバー側での検証
7. セッション作成

**成功時**: ダッシュボードにリダイレクト
**失敗時**: エラーメッセージを表示してログイン画面へ戻るオプションを提示

### 2-認証キャンセル

**トリガー**: ユーザーがPasskey認証UIをキャンセル

**処理**: ログイン画面（`/users/sign_in`）にリダイレクト

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Passkey認証成功 | users | UPDATE | ログイン情報更新 |
| Passkey認証成功 | authentication_events | INSERT | 認証イベント記録 |
| Passkey認証成功 | audit_events | INSERT | 監査ログ記録 |
| Passkey認証成功 | webauthn_credentials | UPDATE | 使用回数更新（任意） |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sign_in_count | +1 | 認証成功時 |
| UPDATE | current_sign_in_at | 現在時刻 | 認証成功時 |
| UPDATE | last_sign_in_at | 旧current_sign_in_at | 認証成功時 |
| UPDATE | current_sign_in_ip | リクエストIP | 認証成功時 |
| UPDATE | last_sign_in_ip | 旧current_sign_in_ip | 認証成功時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|------------|------|---------------|----------|
| MSG001 | タイトル | Sign in with passkeys | ページタイトル（SR用） |
| MSG002 | エラー | Authentication failed | 認証失敗時 |
| MSG003 | エラー | No passkeys found | Passkey未登録時 |
| MSG004 | エラー | Browser does not support passkeys | WebAuthn非対応ブラウザ |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| WebAuthn非対応ブラウザ | エラーメッセージを表示、通常ログインへ誘導 |
| Passkey未登録 | エラーメッセージを表示、通常ログインへ誘導 |
| 認証キャンセル | ログイン画面にリダイレクト |
| 認証タイムアウト | エラーメッセージを表示、再試行オプションを提示 |
| サーバー検証失敗 | エラーメッセージを表示 |
| 機能無効 | 403 Forbiddenを返却 |

## 備考

- フィーチャーフラグ `passkeys` で制御される
- パスワード認証が無効化されている場合は利用不可
- クロスプラットフォームPasskey（iCloud Keychain、Google Password Manager等）に対応
- Discoverable Credentials（Resident Keys）をサポート
- 認証画面はJavaScriptで完全に駆動される
- `#js-passkey-authentication` 要素にマウントされるVue/Reactコンポーネント

---

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

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

### 推奨読解順序

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

Passkey認証に関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | passkeys.html.haml | `app/views/devise/sessions/passkeys.html.haml` | 画面構成とJSコンポーネントへのデータ渡し |

**読解のコツ**: `passkey_authentication_data(params)` ヘルパーがフロントエンドに必要なデータを提供する。

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

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

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

**主要処理フロー**:
- **73-80行目**: `new_passkey` アクション
- **74-75行目**: フィーチャーフラグとパスワード認証の確認
- **76行目**: `handle_passwordless_flow` の呼び出し

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | passkeys.html.haml | `app/views/devise/sessions/passkeys.html.haml` | 画面テンプレート |

**主要処理フロー**:
- **1-2行目**: スクリーンリーダー用のタイトル
- **4行目**: `#js-passkey-authentication` - JavaScriptコンポーネントのマウントポイント

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

```
SessionsController#new_passkey
    │
    ├─ Feature.enabled?(:passkeys)
    │
    ├─ Gitlab::CurrentSettings.password_authentication_enabled_for_web?
    │
    └─ handle_passwordless_flow
           │
           ├─ passkey_authentication_data(params)
           │      └─ WebAuthn認証オプション生成
           │
           └─ render 'passkeys'
                  │
                  └─ JavaScript Component
                         ├─ navigator.credentials.get()
                         ├─ POST /users/sign_in (device_response)
                         └─ リダイレクト
```

### データフロー図

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

ページ読み込み ───▶ passkey_authentication_data ───▶ WebAuthn Options (JSON)
                                                         │
                                                         ▼
                              navigator.credentials.get() ◀── ブラウザPasskey UI
                                                         │
                                                         ▼
device_response ───▶ SessionsController#create ───▶ セッションCookie
                        │
                        ├─ WebAuthn検証
                        │
                        ├─ sign_in(user) ───▶ users テーブル UPDATE
                        │
                        └─ Auditor.audit ───▶ audit_events テーブル INSERT
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sessions_controller.rb | `app/controllers/sessions_controller.rb` | コントローラー | Passkey認証処理の制御 |
| passkeys.html.haml | `app/views/devise/sessions/passkeys.html.haml` | ビュー | Passkey認証画面テンプレート |
| passkey_authentication_data.rb | `app/helpers/passkey_authentication_data.rb` | ヘルパー | WebAuthn認証データ生成 |
| webauthn.js | `app/assets/javascripts/webauthn/` | JavaScript | WebAuthn認証処理 |
| passkeys_helper.rb | `app/helpers/passkeys_helper.rb` | ヘルパー | Passkey関連ヘルパー |
