# 機能設計書 42-AWS Cognito GitHub Proxyバックエンド

## 概要

本ドキュメントは、AWS Cognitoを経由してGitHub APIにプロキシアクセスするバックエンド（`decap-cms-backend-aws-cognito-github-proxy`）の機能設計を記述する。GitHubバックエンドを継承し、AWS Cognito認証を統合した特殊バックエンドである。

### 本機能の処理概要

**業務上の目的・背景**：GitHubリポジトリをバックエンドとして使用する際、GitHub OAuthの代わりにAWS Cognitoによるユーザー管理・認証を利用したいケースがある。本バックエンドは、AWS Cognito User PoolでPKCE OAuthフローを行い、取得したトークンをBearer tokenとしてGitHub APIへのプロキシアクセスに使用する。これにより、企業のAWS Cognito基盤と連携したCMS認証を実現する。

**機能の利用シーン**：AWS Cognitoで認証基盤を構築している組織がDecap CMSを利用する場合に使用される。config.ymlで`backend.name: aws-cognito-github-proxy`を指定し、base_url、app_idなどのCognito設定を行うことで有効化される。

**主要な処理内容**：
1. GitHubバックエンドを継承し、全てのGitHub API操作機能を利用可能にする
2. PKCE OAuth認証フローによるAWS Cognito認証
3. CognitoのuserInfoエンドポイントからユーザー情報を取得
4. Bearer tokenキーワードによるAPI認証（デフォルトのtokenキーワードではなく）
5. アプリトークンに対する書き込みアクセスチェックのバイパス

**関連システム・外部連携**：AWS Cognito User Pool（OAuth2認証）、GitHub API（リポジトリ操作）

**権限による制御**：AWS Cognitoで認証されたユーザーのみがCMS操作を行える。トークンの有効期限管理はCognito側で行われ、401レスポンス時は自動ログアウトされる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | PKCE認証画面 | 主画面 | AWS Cognito PKCE OAuthフローによる認証。PKCEAuthenticationPageを使用 |

## 機能種別

データ連携 / 認証

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| config.backend.base_url | string | No | CognitoのベースURL | デフォルト: '' |
| config.backend.app_id | string | No | CognitoアプリクライアントID | デフォルト: '' |
| config.backend.auth_endpoint | string | No | 認証エンドポイント | デフォルト: 'oauth2/authorize' |
| config.backend.auth_token_endpoint | string | No | トークンエンドポイント | デフォルト: 'oauth2/token' |
| token | string | Yes | CognitoのOAuthトークン | - |

### 入力データソース

- CMS設定ファイル（config.yml）: バックエンド設定パラメータ
- AWS Cognito: OAuthトークン

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| user | GitHubUser | ユーザー情報（name: email, login: owner, avatar_url） |
| pullRequestAuthor | string | PRの作成者ログイン名 |

### 出力先

- CMS状態管理（Redux Store）: ユーザー情報
- GitHub API: GitHubバックエンド継承による各種操作

## 処理フロー

### 処理シーケンス

```
1. コンストラクタでの初期化
   └─ GitHubBackendの初期化 + bypassWriteAccessCheckForAppTokens=true, tokenKeyword='Bearer'
2. 認証ページ表示
   └─ PKCEAuthenticationPageをラップして返却
3. PKCE認証フロー
   └─ PkceAuthenticatorでCognitoへのOAuth2認証を実行
4. ユーザー情報取得
   └─ baseUrl + '/oauth2/userInfo' へBearerトークン付きGETリクエスト
   └─ 401レスポンス時は自動ログアウト
   └─ レスポンスからemail, owner情報を構築
5. GitHub API操作
   └─ GitHubBackendの各メソッドがBearerトークンで実行される
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザーアクセス] --> B[PKCEAuthenticationPage表示]
    B --> C[PKCE OAuth認証開始]
    C --> D[AWS Cognito認証]
    D --> E{認証成功?}
    E -->|Yes| F[トークン取得]
    E -->|No| G[エラー表示]
    F --> H[currentUser - userInfo取得]
    H --> I{401?}
    I -->|Yes| J[自動ログアウト]
    I -->|No| K[GitHubUser構築]
    K --> L[CMS操作開始]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | Bearer認証 | tokenKeywordを'Bearer'に設定（GitHubデフォルトの'token'ではない） | 全API通信時 |
| BR-42-02 | 書き込みチェックバイパス | アプリトークンに対する書き込みアクセスチェックをバイパスする | 常時 |
| BR-42-03 | 401時自動ログアウト | userInfo取得で401が返された場合、自動的にログアウトする | currentUser呼び出し時 |
| BR-42-04 | owner情報の導出 | originRepoからオーナー名を'/'で分割して取得する | currentUser呼び出し時 |
| BR-42-05 | PRの作成者 | PullRequestのauthorはpullRequest.user.loginから取得 | getPullRequestAuthor呼び出し時 |

### 計算ロジック

- `avatar_url`の算出: `https://github.com/${owner}.png`（ownerはoriginRepoの2番目のパス要素）

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

本機能はデータベースを直接操作しない。GitHub APIおよびAWS Cognito APIとの通信で全ての操作を行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | トークン期限切れ | 自動ログアウト後に再認証 |
| - | PKCE認証エラー | Cognito認証失敗 | loginErrorとして画面表示 |

### リトライ仕様

401エラー時のリトライは行わず、自動ログアウトで対処する。

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

外部API通信のため、トランザクション制御はGitHub API側で行われる。

## パフォーマンス要件

GitHubバックエンドと同等。追加のネットワークホップ（AWS Cognito経由）が発生するが、トークン取得は認証時のみ。

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

- PKCE OAuthフローによるセキュアな認証（認可コード横取り攻撃の防止）
- Bearerトークンの使用
- userInfoエンドポイントのHTTPSアクセス
- トークン期限切れ時の自動ログアウト

## 備考

- GitHubBackendクラスを完全に継承しているため、GitHub APIの全操作（エントリCRUD、メディア管理、ワークフロー等）がそのまま利用可能
- `_currentUserPromise`によるユーザー情報のキャッシュ（同一セッション中は1回のみ取得）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | implementation.tsx | `packages/decap-cms-backend-aws-cognito-github-proxy/src/implementation.tsx` | GitHubUser型のインポートとAwsCognitoGitHubProxyBackendクラスの構造 |

**読解のコツ**: このバックエンドはGitHubBackendを`extends`している。GitHubバックエンドの全機能を継承し、認証部分のみをオーバーライドしている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/decap-cms-backend-aws-cognito-github-proxy/src/index.ts` | AwsCognitoGitHubProxyBackendとAPIをエクスポート |

**主要処理フロー**:
1. **1行目**: GitHubバックエンドのAPIをインポート
2. **3行目**: AwsCognitoGitHubProxyBackendをインポート

#### Step 3: コンストラクタとオーバーライドメソッド

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | implementation.tsx | `packages/decap-cms-backend-aws-cognito-github-proxy/src/implementation.tsx` | コンストラクタ（10-15行目）とauthComponent（17-24行目）とcurrentUser（26-47行目） |

**主要処理フロー**:
- **10-15行目**: コンストラクタ。super()でGitHubBackend初期化後、`bypassWriteAccessCheckForAppTokens=true`と`tokenKeyword='Bearer'`を設定
- **17-24行目**: `authComponent()` - PKCEAuthenticationPageをラップして返却。backendプロパティを追加
- **26-47行目**: `currentUser()` - CognitoのuserInfoエンドポイントからユーザー情報取得。401時はログアウト
- **49-53行目**: `getPullRequestAuthor()` - PRの作成者をpullRequest.user?.loginから取得

#### Step 4: 認証ページを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AuthenticationPage.js | `packages/decap-cms-backend-aws-cognito-github-proxy/src/AuthenticationPage.js` | PKCEフローの認証ページ。PkceAuthenticator利用 |

**主要処理フロー**:
- **21-51行目**: `componentDidMount()` - PkceAuthenticatorの初期化とcompleteAuth（リダイレクト後の認証完了処理）
- **53-61行目**: `handleLogin()` - PKCE認証開始。scope指定あり（`https://api.github.com/repo openid email`）
- **30-35行目**: Cognito設定パラメータの取得（base_url, app_id, auth_endpoint, auth_token_endpoint）

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

```
AwsCognitoGitHubProxyBackend
    |
    +-- extends GitHubBackend (全GitHub API操作を継承)
    |
    +-- constructor()
    |       +-- super(config, options) [GitHubBackend初期化]
    |       +-- bypassWriteAccessCheckForAppTokens = true
    |       +-- tokenKeyword = 'Bearer'
    |
    +-- authComponent()
    |       +-- PKCEAuthenticationPage (ラップ)
    |           +-- PkceAuthenticator
    |               +-- completeAuth() [リダイレクトバック時]
    |               +-- authenticate() [ログイン開始時]
    |
    +-- currentUser({ token })
    |       +-- fetch(baseUrl + '/oauth2/userInfo')
    |       +-- GitHubUser構築
    |
    +-- getPullRequestAuthor(pullRequest)
            +-- pullRequest.user?.login
```

### データフロー図

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

ユーザー操作        ──▶  PKCEAuthenticationPage    ──▶  AWS Cognito
(ログインボタン)          PkceAuthenticator               (OAuth2認証)

Cognito Token      ──▶  currentUser()              ──▶  GitHubUser
(Bearer Token)           fetch(/oauth2/userInfo)          (name, login, avatar_url)

CMS操作            ──▶  GitHubBackend継承メソッド   ──▶  GitHub API
(エントリ/メディア)       Bearer Token認証               (リポジトリ操作)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| implementation.tsx | `packages/decap-cms-backend-aws-cognito-github-proxy/src/implementation.tsx` | ソース | メインバックエンド実装 |
| index.ts | `packages/decap-cms-backend-aws-cognito-github-proxy/src/index.ts` | ソース | パッケージエントリポイント |
| AuthenticationPage.js | `packages/decap-cms-backend-aws-cognito-github-proxy/src/AuthenticationPage.js` | ソース | PKCE認証ページ |
