コンテンツにスキップ

WordPress-RAG SSO連携 要件定義書

項目 内容
作成日 2024年12月24日
バージョン 1.0
ステータス 承認済み

1. 概要

1.1 目的

WordPress PWAアプリケーションにログイン済みのユーザーが、別ドメインで稼働するRAGシステム(KnowledgeYard)に自動的にログインできるSSO(シングルサインオン)連携を実現する。

1.2 スコープ

機能 優先度 担当
SSO連携(トークン発行・受け取り) P1 WordPress + RAG
ユーザー一括インポート P1 RAG
部署ベース権限制御 P2 RAG
文書権限管理UI P2 RAG

1.3 システム構成

┌─────────────────────────────────┐     ┌─────────────────────────────────┐
│         WordPress PWA           │     │      RAGシステム (KnowledgeYard) │
│         (別ドメイン)             │     │         (別ドメイン)             │
├─────────────────────────────────┤     ├─────────────────────────────────┤
│                                 │     │                                 │
│  ・社員番号でログイン            │     │  ・Azure Functions API          │
│  ・1600名(関連会社含む)        │     │  ・Azure AI Search              │
│  ・本社280名がRAG利用対象        │     │  ・Azure Table Storage          │
│  ・部署情報を管理・調整          │     │  ・React フロントエンド          │
│                                 │     │                                 │
└─────────────────────────────────┘     └─────────────────────────────────┘
              │                                       │
              │         SSO連携フロー                  │
              │◀─────────────────────────────────────▶│
              │                                       │

2. SSO連携仕様

2.1 認証フロー

[WordPress]                              [RAGシステム]
     │                                        │
     │ ① ユーザーがWordPressにログイン済み     │
     │                                        │
     │ ② 「RAG検索」ボタンをクリック           │
     │    ↓                                   │
     │ ③ PHP: 署名付きリクエストを生成         │
     │    - user_id (社員番号)                │
     │    - timestamp (UNIX時間)              │
     │    - signature (HMAC-SHA256)           │
     │    ↓                                   │
     │ ④ POST /api/auth/sso-token ──────────→ │
     │                                        │ ⑤ 署名を検証
     │                                        │ ⑥ タイムスタンプ有効期限チェック(5分)
     │                                        │ ⑦ ユーザー存在確認
     │                                        │    - 存在しない → エラー返却
     │                                        │    - 存在する → JWTトークン生成
     │ ⑧ JWTトークン受信 ←─────────────────── │
     │    ↓                                   │
     │ ⑨ 新規タブでRAGを開く                   │
     │    URL: https://rag.example.com?sso_token=xxx
     │                                        │ ⑩ URLパラメータからトークン取得
     │                                        │ ⑪ トークンをlocalStorageに保存
     │                                        │ ⑫ URLからパラメータを削除
     │                                        │ ⑬ 認証済み状態でアプリ表示

2.2 共有シークレット

項目
名称 SSO_SHARED_SECRET
形式 64文字以上のランダム文字列
設定場所(WordPress) wp-config.php または環境変数
設定場所(RAG) Azure Functions アプリケーション設定

重要: 本番環境では安全な方法でシークレットを共有してください。

2.3 署名生成アルゴリズム

signature = HMAC-SHA256(
    key: SSO_SHARED_SECRET,
    message: "{user_id}:{timestamp}"
)
  • user_id: 社員番号(文字列)
  • timestamp: UNIX時間(秒)
  • 署名は16進数文字列(小文字)で送信

3. API仕様

3.1 SSOトークン発行 API

【RAG側で実装】

項目 内容
エンドポイント POST /api/auth/sso-token
認証 不要(署名で認証)

リクエスト

{
  "user_id": "12345",
  "timestamp": 1703404800,
  "signature": "a1b2c3d4e5f6..."
}
フィールド 必須 説明
user_id string 社員番号
timestamp integer UNIX時間(秒)
signature string HMAC-SHA256署名(16進数)

レスポンス(成功: 200)

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "user_id": "12345",
    "display_name": "山田太郎",
    "role": "user",
    "department": "総務部",
    "email": "yamada@example.com"
  },
  "expires_in": 86400
}

レスポンス(エラー)

HTTPステータス エラーコード 説明
400 INVALID_REQUEST リクエスト形式が不正
401 INVALID_SIGNATURE 署名が一致しない
401 EXPIRED_TIMESTAMP タイムスタンプが期限切れ(5分超過)
404 USER_NOT_FOUND ユーザーが登録されていない
{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "指定されたユーザーは登録されていません"
  }
}

3.2 ユーザー一括インポート API

【RAG側で実装】

項目 内容
エンドポイント POST /api/manage/users/bulk
認証 Bearer Token(adminロール必須)

リクエスト

{
  "users": [
    {
      "user_id": "12345",
      "display_name": "山田太郎",
      "department": "総務部",
      "email": "yamada@example.com",
      "role": "user"
    },
    {
      "user_id": "12346",
      "display_name": "鈴木花子",
      "department": "人事部",
      "email": "suzuki@example.com",
      "role": "user"
    }
  ],
  "update_existing": true
}
フィールド 必須 説明
users array ユーザー情報の配列(最大100件)
users[].user_id string 社員番号
users[].display_name string 表示名(氏名)
users[].department string 部署名
users[].email string メールアドレス
users[].role string ロール(デフォルト: "user")
users[].password string パスワード(省略時: user_idと同じ)
update_existing boolean true: 既存ユーザーを更新(デフォルト: false)

レスポンス(成功: 200 または 207)

{
  "created": 45,
  "updated": 5,
  "skipped": 0,
  "errors": [
    {
      "index": 50,
      "user_id": "99999",
      "error": "display_name is required"
    }
  ],
  "total_requested": 51
}

4. WordPress側 実装要件

4.1 SSO連携機能

4.1.1 設定ファイル

// wp-config.php に追加
define('RAG_SSO_SECRET', 'your-64-character-secret-key-here...');
define('RAG_API_URL', 'https://rag.example.com/api');
define('RAG_APP_URL', 'https://rag.example.com');

4.1.2 SSOトークン取得関数

<?php
/**
 * RAGシステム用のSSOトークンを取得する
 * 
 * @param string $user_id 社員番号
 * @return array|WP_Error トークン情報またはエラー
 */
function get_rag_sso_token($user_id) {
    $timestamp = time();
    $message = $user_id . ':' . $timestamp;
    $signature = hash_hmac('sha256', $message, RAG_SSO_SECRET);

    $response = wp_remote_post(RAG_API_URL . '/auth/sso-token', [
        'headers' => [
            'Content-Type' => 'application/json',
        ],
        'body' => json_encode([
            'user_id' => $user_id,
            'timestamp' => $timestamp,
            'signature' => $signature,
        ]),
        'timeout' => 30,
    ]);

    if (is_wp_error($response)) {
        return $response;
    }

    $status_code = wp_remote_retrieve_response_code($response);
    $body = json_decode(wp_remote_retrieve_body($response), true);

    if ($status_code !== 200) {
        return new WP_Error(
            $body['error']['code'] ?? 'UNKNOWN_ERROR',
            $body['error']['message'] ?? 'RAGシステムへの接続に失敗しました'
        );
    }

    return $body;
}

4.1.3 RAG起動ボタン/リンクの実装

<?php
/**
 * RAGシステムを開くURLを生成する
 * ログインユーザーの社員番号を使用
 */
function get_rag_launch_url() {
    if (!is_user_logged_in()) {
        return null;
    }

    $current_user = wp_get_current_user();
    $user_id = $current_user->user_login; // 社員番号

    $result = get_rag_sso_token($user_id);

    if (is_wp_error($result)) {
        // エラーログ記録
        error_log('RAG SSO Error: ' . $result->get_error_message());
        return null;
    }

    $token = $result['token'];
    return RAG_APP_URL . '?sso_token=' . urlencode($token);
}

/**
 * RAG起動ボタンのショートコード
 * 使用例: [rag_button text="RAG検索を開く"]
 */
function rag_button_shortcode($atts) {
    $atts = shortcode_atts([
        'text' => 'RAG検索',
        'class' => 'rag-launch-button',
    ], $atts);

    $url = get_rag_launch_url();

    if (!$url) {
        return '<span class="rag-error">RAGシステムを利用できません</span>';
    }

    return sprintf(
        '<a href="%s" target="_blank" class="%s" rel="noopener noreferrer">%s</a>',
        esc_url($url),
        esc_attr($atts['class']),
        esc_html($atts['text'])
    );
}
add_shortcode('rag_button', 'rag_button_shortcode');

4.1.4 JavaScript版(AJAX対応)

/**
 * RAGシステムを新規タブで開く
 * トークンを取得してからURLにパラメータ付きで開く
 */
async function openRAGSystem() {
    try {
        const response = await fetch('/wp-json/rag/v1/get-token', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-WP-Nonce': wpApiSettings.nonce,
            },
        });

        if (!response.ok) {
            const error = await response.json();
            alert(error.message || 'RAGシステムへの接続に失敗しました');
            return;
        }

        const data = await response.json();
        const ragUrl = `${RAG_APP_URL}?sso_token=${encodeURIComponent(data.token)}`;
        window.open(ragUrl, '_blank', 'noopener,noreferrer');

    } catch (error) {
        console.error('RAG SSO Error:', error);
        alert('RAGシステムへの接続に失敗しました');
    }
}

4.2 ユーザーCSVエクスポート

月次インポート用に、本社280名のユーザー情報をCSV出力する機能が必要です。

4.2.1 CSVフォーマット

社員番号,氏名,部署,メールアドレス
12345,山田太郎,総務部,yamada@example.com
12346,鈴木花子,人事部,suzuki@example.com
...
カラム 必須 説明
社員番号 ユーザーID兼パスワード
氏名 表示名
部署 権限制御に使用
メールアドレス 任意

4.2.2 エクスポート対象

  • 本社社員のみ(関連会社1600名のうち280名程度)
  • WordPressで調整済みの部署情報を使用

5. RAG側 実装要件

5.1 SSO連携

実装対象 ファイル
SSOトークン発行API app/api/routes/auth.py
Azure Functions ルーティング app/api/function_app.py
フロントエンド トークン受け取り app/web/src/context/authContext.tsx
CORS設定更新 app/api/function_app.py

5.2 ユーザー管理拡張

実装対象 ファイル
一括インポートAPI app/api/routes/admin.py
UserEntityに部署追加 app/api/services/table_storage.py
JWTに部署情報追加 app/api/services/auth.py

5.3 環境設定

Azure Functions に以下の設定を追加:

設定キー 説明
SSO_SHARED_SECRET WordPress共有シークレット
SSO_TIMESTAMP_TOLERANCE タイムスタンプ許容秒数(デフォルト: 300)
WORDPRESS_DOMAIN WordPressドメイン(CORS許可用)

6. 部署権限制御仕様(P2)

6.1 権限チェックフロー

① ロールチェック
   ├─ admin / developer → 全文書アクセス可 ✓
   └─ user → ②へ進む

② 部署チェック(userロールのみ)
   ├─ 文書の allowed_departments = ["*"] → アクセス可 ✓
   ├─ ユーザーの department ∈ allowed_departments → アクセス可 ✓
   └─ それ以外 → 検索結果から除外 ✗

6.2 文書権限データ構造

{
  "document_id": "doc-001",
  "title": "人事評価マニュアル",
  "allowed_departments": ["人事部", "総務部"]
}
意味
["*"] 全員アクセス可(デフォルト)
["部署A", "部署B"] 指定部署のみアクセス可
[] admin/developerのみ

6.3 既存文書の扱い

  • 既存の全文書は allowed_departments = ["*"] として扱う
  • 管理画面から個別に権限を変更可能

7. セキュリティ要件

7.1 SSO連携

項目 対策
署名検証 HMAC-SHA256で改ざん防止
リプレイ攻撃防止 タイムスタンプ有効期限5分
トークン漏洩対策 URLパラメータは即座に削除、履歴に残さない
HTTPS必須 全通信をHTTPS化

7.2 シークレット管理

環境 管理方法
開発 環境変数または設定ファイル
本番(WordPress) wp-config.php(.gitignore対象)
本番(RAG) Azure Key Vault推奨

7.3 CORS設定

許可オリジン: https://wordpress.example.com
許可メソッド: POST, OPTIONS
許可ヘッダー: Content-Type, Authorization

8. 運用手順

8.1 月次ユーザー同期

1. WordPress管理画面から本社社員CSVをエクスポート
2. CSV→JSON変換スクリプトを実行
3. POST /api/manage/users/bulk でRAGにインポート
4. 結果を確認(created/updated/errors)

8.2 新規社員の追加

  • 月次同期で自動的に追加される
  • 即時対応が必要な場合は個別登録

8.3 退職者の対応

  • is_active: false に設定(論理削除)
  • または月次同期から除外

9. 実装スケジュール

Phase 1(P1): SSO連携・ユーザー管理

担当 タスク 見積もり
RAG SSOトークン発行API 0.5日
RAG ユーザーテーブル拡張(部署追加) 0.5日
RAG 一括インポートAPI 1日
RAG フロントエンド SSOトークン受け取り 0.5日
RAG CSV変換スクリプト 0.5日
WordPress SSO連携機能(トークン取得・RAG起動) 1日
WordPress ユーザーCSVエクスポート機能 0.5日
共通 結合テスト 1日

合計: 約5.5日

Phase 2(P2): 部署権限制御

担当 タスク 見積もり
RAG 検索フィルタリング実装 1日
RAG 文書権限管理API 1日
RAG 管理画面UI 2日
共通 テスト 1日

合計: 約5日


10. 付録

10.1 エラーコード一覧

コード HTTPステータス 説明
INVALID_REQUEST 400 リクエスト形式が不正
INVALID_SIGNATURE 401 署名が一致しない
EXPIRED_TIMESTAMP 401 タイムスタンプ期限切れ
USER_NOT_FOUND 404 ユーザー未登録
UNAUTHORIZED 401 認証トークンが無効
FORBIDDEN 403 権限不足

10.2 ロール定義

ロール 説明 文書アクセス
admin 管理者 全文書
developer 開発者 全文書
user 一般ユーザー 部署制限あり

10.3 連絡先

担当 連絡先
RAG開発 (記入してください)
WordPress開発 (記入してください)

更新履歴

日付 バージョン 変更内容
2024-12-24 1.0 初版作成