adding-project-secret-api-key-auth について
PostHog の API エンドポイントに Project Secret API Key(PSAK)認証を追加する開発者向けガイドです。スコープ認可、認証設定、レート制限、合成ユーザーの扱い、必要なテストを説明します。
主な機能
- 01プロジェクト単位のサービス資格情報の説明
- 02スコープ許可リストの設定
- 03エンドポイント認証と操作認可
- 04キー単位・チーム単位のレート制限
- 05合成ユーザーと権限の処理
活用シーン
- 01API 操作で PSAK 認証を有効化
- 02付与可能なキーのスコープを設定
- 03合成ユーザーの権限エラーを回避
- 04認可・チーム紐付け・制限をテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ posthog --skill adding-project-secret-api-key-authインストール後、Claude Code で/adding-project-secret-api-key-authを入力して読み込まれたか確認します。
詳細
エンドポイントへのプロジェクトシークレット API キー(PSAK)認証の追加
PSAK とは
ProjectSecretAPIKey は、プロジェクトスコープでユーザーに紐づかないサービス認証情報です(posthog/models/project_secret_api_key.py)。個人用 API キーのように動作しますが、ユーザーがプロジェクトを離れても存続し、独自のスコープを持ち、実際の User 行ではなく合成ユーザーとして認証します。
- トークン形式:
phs_...(Bearer ヘッダーのみ — レガシートークンと異なりボディからのフォールバックはありません)。 - スコープはリソースタイプ内でプロジェクト全体にわたり、オブジェクトレベルのアクセス制御(リソース単位の RBAC)を意図的に無視します。
TeamSecretTokenAuthenticationと混同しないでください — こちらはレガシーなチーム単位のTeam.secret_api_token(同じくphs_プレフィックス)を検証するもので、フィーチャーフラグのローカル評価や同様の PSAK 以前のサーフェスにのみ使用されます。いずれ PSAK へ移行することが決まっています。
キーは POST /api/environments/:id/project_secret_api_keys で管理されます(ラベル + スコープ、平文の値は一度だけ返却、roll アクションでローテーション、プロジェクトごとに最大 50 個、ワイルドカード * スコープは不可)。
viewset アクションの配線 — チェックリスト
仕組みはすでに実装されていますが、まだ何も配線されていません — 最初の想定利用者は endpoints(プロダクト)の run アクションです。必要なのは以下の 4 点、すべて必須です:
1. スコープ/アクションのペアをホワイトリストに登録する
PSAK で割り当て可能なスコープは posthog/scopes.py にあるグローバルな許可リストです:
PROJECT_SECRET_API_KEY_ALLOWED_API_SCOPE_ACTION: list[tuple[APIScopeObject, APIScopeActions]] = [("endpoint", "read")]
プロダクトが記載されていない場合、認証が試みられる前にキー作成がスコープを拒否します。まずここに (scope_object, action) タプルを追加してください。
同じスコープを frontend/src/lib/scopes.tsx の PROJECT_SECRET_API_KEY_ALLOWED_API_SCOPE_ACTION にも追加してください。プロジェクト設定のスコープピッカーはそのリストからチェックボックスを生成するため、バックエンドのみの変更ではユーザーがスコープを付与する手段がなくなります。posthog/test/test_scopes.py が両方のリストを比較します。
2. オーセンティケータを追加し、アクションをオプトインする
class MyViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet):
scope_object = "endpoint"
authentication_classes = [ProjectSecretAPIKeyAuthentication] # extends, TeamAndOrgViewSetMixin keeps session/PAK auth
psak_allowed_actions = ["run"]
psak_allowed_actions はデフォルト拒否です: APIScopePermission はアクションが記載されていない PSAK リクエストを拒否します(「This action does not support project secret API key access」)。プログラムによるアクションのみを記載してください — 人間主導であるべき CRUD は決して含めないでください。
APIScopePermission はチームのバインディングも自動的に強制します: PSAK は view.team == key.team に対してのみ機能するため、PSAK 認証はプロジェクトスコープのルート(/api/environments/:id/...)でのみ意味を持ちます。
3. PSAK 対応のスロットルを使用する
PersonalApiKeyRateThrottle のサブクラスは PSAK リクエストを暗黙的にバイパスします(個人キーがなければスロットリングもなし)。posthog/rate_limit.py の PSAK 対応ペアを使用してください:
PersonalOrProjectSecretApiKeyRateThrottle— キー単位のバジェット(psak:{key_id}をキーとする)、個人キーも引き続きスロットリングします。ProjectSecretApiKeyTeamRateThrottle— チーム単位の集計(psak-team:{team_id}をキーとする)、プロジェクトがいくつのキーを発行しても PSAK の総負荷に上限を設けます。キー単位のスロットルと並べてスタックしてください。
これらをサブクラス化してプロダクト固有の scope/rate を設定してください。各スロットルは scope 文字列ごとに独自のキャッシュバケットを保持することに注意してください。
4. 合成ユーザーを処理する
request.user は User ではなく ProjectSecretAPIKeyUser(SyntheticUser、posthog/synthetic_user.py)です:
-
user.idはNoneです — 外部キーとして絶対に使用しないでください。user.current_team_idを使用してください。 -
has_perm()は常にFalseを返します — Django のパーミッションチェックは暗黙的に拒否します。 -
これに対するオブジェクト単位のアクセス制御チェックはスキップしてください(PSAK スコープは設計上プロジェクト全体に及びます):
if is_authenticated_via_project_secret_api_key(request): return # PSAK bypasses object-level RBAC deliberatelyisinstance(user, ProjectSecretAPIKeyUser)は、リクエストがスコープ内に存在しない場合にのみ使用してください。 -
report_user_actionは合成ユーザーを破棄します — PSAK で認証された呼び出しの分析が必要な場合は、posthoganalytics.capture(distinct_id=user.distinct_id, ...)で明示的にキャプチャし、auth_methodプロパティを含めて、両方のパスが同じイベント形状を出力するようにしてください。 -
HogQL システムテーブル:
Database.create_forは、キーのスコープがカバーしていない RBAC スコープ付きシステムテーブルを非表示にします(readable_system_table_access_scopes()を経由)。
分岐が必要な場合に posthog/permissions.py にあるヘルパー:is_authenticated_via_project_secret_api_key(request) および is_service_auth(request)(PSAK + レガシーチームトークンをカバー)。
無料で得られるもの
- クエリタグ付け:オーセンティケーターが
tag_authentication(access_method=AccessMethod.PROJECT_SECRET_API_KEY, api_key_mask=..., api_key_label=...)を呼び出すため、ClickHouse のquery_logによる帰属がエンドポイントごとのコードなしで機能します。新しいオーセンティケーターを追加する場合は、tag_authentication(posthog/clickhouse/query_tagging.py内の単一のファネル)を通じてタグ付けしてください — アドホックなtag_queries呼び出しでは行わないでください。 last_used_atトラッキング:.update()を経由して最大 1 時間ごとに更新されます(ModelActivityMixinをバイパスするため、定期的な認証がアクティビティログをスパムしません)。- アクティビティログ:キーの作成/更新/ロール/削除時。
PSAK でゲートされたエンドポイントを呼び出す
curl -s https://us.posthog.com/api/environments/<project_id>/<your_action_path>/ \
-H "Authorization: Bearer phs_<key>" \
-H "Content-Type: application/json" \
-d '{...}'
テスト
posthog/api/test/test_authentication.py、posthog/test/test_permissions.py、posthog/test/test_rate_limit.py の PSAK セクションを踏襲してください。最低限以下をカバーしてください:
- 正しいスコープでの許可されたアクション → 200
psak_allowed_actionsに含まれないアクション → 403- スコープの欠落/誤り → 403
- 別のチームのプロジェクトのキー → 403
- 同じアクションに対する非 PSAK 認証は引き続き機能する