# 機能設計書 88-認証

## 概要

本ドキュメントは、「認証」機能の設計を定義する。認証機能は、スタッフユーザー（管理者、編集者等）およびメンバーの認証処理を行い、セッション管理、パスワードリセット、2要素認証（メールMFA）をサポートする。

### 本機能の処理概要

認証サービスは、Ghost AdminへのログインおよびAPIアクセスの認証を提供する。セッションベース認証とAPIキー認証の両方をサポートし、セキュリティを確保するための各種機能を提供する。

**業務上の目的・背景**：Ghost Adminおよび管理APIへのアクセスを適切に制御し、不正アクセスを防止する。スタッフユーザーとメンバーで異なる認証フローを提供し、それぞれの要件に対応する。

**機能の利用シーン**：
- スタッフユーザーのGhost Adminへのログイン
- Admin APIへのアクセス認証
- メンバーのマジックリンク認証
- パスワードリセット
- 2要素認証（メールMFA）

**主要な処理内容**：
1. セッション認証（Cookie + CSRF保護）
2. APIキー認証（JWT）
3. パスワードリセットトークン生成・検証
4. OTPコード生成・検証（メールMFA）
5. セッション検証状態管理

**関連システム・外部連携**：
- express-session - セッション管理
- jsonwebtoken - JWT処理
- @tryghost/security - トークン・OTP生成
- メールサービス - パスワードリセット・MFAコード送信

**権限による制御**：認証後、ロールに基づいた権限チェックが別途実施される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | サインイン画面 | 主画面 | メールアドレスとパスワードによる認証 |
| 2 | サインイン確認画面 | 主画面 | 2段階認証コードの検証 |
| 4 | パスワードリセット画面 | 主画面 | パスワードリセットトークンの検証 |
| 5 | サインアウト | 主画面 | セッションの終了 |

## 機能種別

認証 / セキュリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| email | string | Yes | メールアドレス | メール形式 |
| password | string | Yes | パスワード | - |
| token | string | No | MFAトークン/リセットトークン | 6桁数字（MFA） |
| Authorization | header | No | APIキー認証ヘッダー | Ghost JWT形式 |

### 入力データソース

- HTTPリクエスト（ログインフォーム）
- HTTPヘッダー（Authorization）
- Cookie（セッション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| session | object | セッション情報（user_id, origin, verified等） |
| user | object | 認証されたユーザー情報 |
| api_key | object | APIキー情報 |

### 出力先

- セッションストア（sessions テーブル）
- HTTPレスポンス（Set-Cookie）
- req.user（Expressリクエストオブジェクト）

## 処理フロー

### 処理シーケンス

```
1. ログインリクエスト受信
   └─ email/passwordでユーザー検証
2. セッション作成
   └─ user_id, origin, user_agent, ip を設定
   └─ MFAトークン検証（提供された場合）
3. 2FA確認（設定有効時）
   └─ OTPコード生成・メール送信
   └─ コード検証後にsession.verified = true
4. 以降のリクエスト
   └─ セッションCookie検証
   └─ CSRF保護（Origin検証）
   └─ ユーザー情報取得
```

### フローチャート

```mermaid
flowchart TD
    A[ログインリクエスト] --> B[email/password検証]
    B --> C{認証成功?}
    C -->|No| D[エラー返却]
    C -->|Yes| E[セッション作成]
    E --> F{MFAトークン提供?}
    F -->|Yes| G[OTP検証]
    G --> H{検証成功?}
    H -->|Yes| I[session.verified = true]
    H -->|No| J[verified未設定]
    F -->|No| J
    I --> K[レスポンス返却]
    J --> K

    L[保護リソースアクセス] --> M[セッション検証]
    M --> N{verified?}
    N -->|No| O[2FA要求]
    O --> P[OTPコード送信]
    P --> Q[コード入力]
    Q --> R[verifySession]
    R --> K
    N -->|Yes| K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-88-01 | CSRF保護 | リクエストのOriginがセッションのoriginと一致 | セッション認証時 |
| BR-88-02 | MFA要否 | require_email_mfa設定で2FA要否を決定 | ログイン時 |
| BR-88-03 | トークン有効期限 | パスワードリセットトークンは1日有効 | リセット時 |
| BR-88-04 | セッション情報 | user_agent、IPアドレスを記録 | セッション作成時 |

### 計算ロジック

OTP生成: @tryghost/securityのotp.generate(user_id, secret)を使用

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ログイン | sessions | INSERT/UPDATE | セッション作成・更新 |
| ログアウト | sessions | UPDATE | session.user_id = undefined |
| ユーザー検証 | users | SELECT | メールアドレスでユーザー検索 |

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

#### sessions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | user_id | 認証ユーザーID | - |
| INSERT/UPDATE | session_data | JSON（origin, user_agent, ip, verified） | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | BadRequestError | Origin不一致（CSRF） | エラー返却 |
| - | UnauthorizedError | 認証失敗 | エラー返却 |
| - | EmailError | MFAメール送信失敗 | エラー返却 |

### リトライ仕様

パスワードリセットトークンの再生成は可能

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

セッション操作は個別トランザクション

## パフォーマンス要件

- 認証処理は低レイテンシ
- セッション検索は高速

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

- パスワードはbcryptでハッシュ化
- CSRF保護（Origin検証）
- ブルートフォース対策（別機能で実装）
- セッション固定攻撃対策

## 備考

- メンバー認証はマジックリンク（パスワードレス）

---

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

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

### 推奨読解順序

#### Step 1: サービスエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `ghost/core/core/server/services/auth/index.js` | サブモジュールのエクスポート |
| 1-2 | authenticate.js | `ghost/core/core/server/services/auth/authenticate.js` | 認証ミドルウェアの組み合わせ |

**読解のコツ**: authenticate.jsでAdmin API、Content APIそれぞれの認証ミドルウェアチェーンを確認。

#### Step 2: セッション認証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | session-service.js | `ghost/core/core/server/services/auth/session/session-service.js` | セッション管理サービス |
| 2-2 | middleware.js | `ghost/core/core/server/services/auth/session/middleware.js` | Expressミドルウェア |

**主要処理フロー**（session-service.js）:
- **78-92行目**: cookieCsrfProtection - CSRF検証
- **99-101行目**: isVerificationRequired - MFA要否判定
- **111-136行目**: createSessionForUser - セッション作成
- **245-289行目**: sendAuthCodeToUser - MFAコード送信
- **337-360行目**: getUserForSession - セッションからユーザー取得

#### Step 3: パスワードリセットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | passwordreset.js | `ghost/core/core/server/services/auth/passwordreset.js` | パスワードリセット処理 |

**主要処理フロー**:
- **36-64行目**: generateToken - リセットトークン生成
- **96-162行目**: doReset - パスワード変更実行
- **164-191行目**: sendResetNotification - リセットメール送信

#### Step 4: APIキー認証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | admin.js | `ghost/core/core/server/services/auth/api-key/admin.js` | Admin API認証 |
| 4-2 | content.js | `ghost/core/core/server/services/auth/api-key/content.js` | Content API認証 |

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

```
Auth Module (index.js)
    │
    ├─ authenticate.js
    │      ├─ authenticateAdminApi
    │      │      ├─ apiKeyAuth.admin.authenticate
    │      │      └─ session.authenticate
    │      │
    │      └─ authenticateContentApi
    │             ├─ apiKeyAuth.content.authenticate
    │             └─ members.authenticateMembersToken
    │
    ├─ session/
    │      ├─ session-service.js
    │      │      ├─ createSessionForUser
    │      │      ├─ getUserForSession
    │      │      ├─ sendAuthCodeToUser
    │      │      └─ verifySession
    │      │
    │      └─ middleware.js
    │
    ├─ passwordreset.js
    │      ├─ generateToken
    │      ├─ doReset
    │      └─ sendResetNotification
    │
    └─ api-key/
           ├─ admin.js (JWT認証)
           └─ content.js (APIキー認証)
```

### データフロー図

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

Login Request   ───▶ session-service         ───▶ Session Cookie
  (email/pwd)        createSessionForUser

Session Cookie  ───▶ getUserForSession       ───▶ req.user
  + Request          (CSRF check)

Admin API       ───▶ apiKeyAuth.admin        ───▶ req.api_key
  (JWT Header)       authenticate

Reset Request   ───▶ passwordreset           ───▶ Reset Email
  (email)            generateToken
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `ghost/core/core/server/services/auth/index.js` | ソース | エクスポート |
| authenticate.js | `ghost/core/core/server/services/auth/authenticate.js` | ソース | 認証チェーン |
| session-service.js | `ghost/core/core/server/services/auth/session/session-service.js` | ソース | セッション管理 |
| middleware.js | `ghost/core/core/server/services/auth/session/middleware.js` | ソース | ミドルウェア |
| passwordreset.js | `ghost/core/core/server/services/auth/passwordreset.js` | ソース | パスワードリセット |
| admin.js | `ghost/core/core/server/services/auth/api-key/admin.js` | ソース | Admin APIキー認証 |
| content.js | `ghost/core/core/server/services/auth/api-key/content.js` | ソース | Content APIキー認証 |
| otp.js | `ghost/core/core/server/services/auth/otp.js` | ソース | OTP生成・検証 |
| authorize.js | `ghost/core/core/server/services/auth/authorize.js` | ソース | 認可処理 |
