すべての記事
GitHubGitHub AppsOAuthwebhook design

GitHub Apps と OAuth Apps:Webhook を並べて比較

初めて GitHub 連携を作るとき、GitHub App と OAuth App のどちらが欲しいのかを見極めるのに 1 時間を費やすことになります。ドキュメントは両者を同等の選択肢として扱います。違います。Webhook の話だけでも、たいていは選択が自ずと決まります。

ごく短い要約

  • GitHub App: アカウントやリポジトリにインストールされ、きめ細かい権限を持ち、インストールされたリソースの Webhook を受け取り、短命トークンで自分自身として認証します。
  • OAuth App: ユーザーが認可し、その権限で本人の代わりに動作し、サードパーティツールのように自分で設定したときだけ Webhook を受け取り、長命トークンでユーザーとして認証します。

アクティブなユーザーなしで動くもの——CI ボット、コードレビュー自動化、スケジュール実行など——を作るなら GitHub App が欲しいはずです。ログイン中のユーザーの代わりにアクション(コード検索 UI など)を行うツールなら、OAuth App が適した形です。

Webhook の受け取り方

GitHub Apps

アプリ作成時に Webhook URL を 1 つ設定します。ユーザーがアカウントやリポジトリにアプリをインストールすると、GitHub はその範囲のイベントをあなたの URL へ送り始めます。イベントには installation(インストール/アンインストールのライフサイクル)、installation_repositories(追加・削除されたリポジトリ)、アプリが購読したイベント型(push、pull_request など)が含まれます。

各イベントには X-GitHub-Hook-Installation-Target-Type ヘッダー(「integration」)と installation ID が含まれ、その特定のインストール向けトークンを発行できます。署名は X-Hub-Signature-256 の HMAC SHA-256——リポジトリ Webhook と同じ形です。

OAuth Apps

OAuth Apps には組み込みの Webhook 購読がありません。Webhook を受け取るには、認可したユーザーがアプリの URL を指すリポジトリまたは組織の Webhook を作成する必要があります。つまりアプリの Webhook の到達範囲は、アプリ自身がどこに「インストール」されているかではなく、ユーザーがどこに購読を設定したかに紐づきます。

認可後に GitHub API 経由で自動的に Webhook を作る OAuth Apps を作るチームもあります。動きますが、アプリ自身のロジックに加えてユーザーごとの Webhook ライフサイクルを管理することになります。

認証こそ本当の分岐点

GitHub Apps は JWT 署名リクエストで認証し、インストールごとに短命のインストールトークン(1 時間)を発行します。JWT はアプリ作成時に生成する秘密鍵で署名します。コードは:

// 1. アプリの秘密鍵で JWT を署名(有効期限 10 分)
const jwt = createAppJwt(APP_ID, PRIVATE_KEY);

// 2. JWT をインストールトークンに交換(有効 1 時間)
const token = await fetchInstallationToken(jwt, INSTALLATION_ID);

// 3. そのトークンで API 呼び出し
const res = await fetch('https://api.github.com/repos/x/y/issues', {
  headers: { Authorization: `token ${token}` },
});

インストールトークンはインストールに限定され自動的に失効するため、漏洩しても影響範囲は限られます。

OAuth Apps は標準 OAuth フローで得たユーザーアクセストークンで認証します。これらは既定で長命でユーザーとして動作するため、1 つ漏れればそのユーザーにできることすべてを攻撃者ができます。GitHub のドキュメントが新規連携で GitHub Apps を勧めるのは一部この理由です。

権限:限定 対 広範

GitHub Apps では細かい権限を要求できます。issues を読む、checks を書く、pull requests を読む、それ以外はアクセスなし。各権限は独立しています。ユーザーは正確な一覧を見て拒否できます。

OAuth Apps は古い scope ベースのシステムを使います:reporead:user など。scope は粗いです。repo scope はユーザーが見えるすべてのリポジトリに読み書きを与えます——「特定リポジトリのみ読み取り」版はありません。

コードを読み check runs を書くだけのコードレビューボットには、2 つの具体的な権限を持つ GitHub App のほうが、完全な repo アクセスを求める OAuth App よりはるかに侵襲が少ないです。

両方のローカルテスト

Webhook 署名の仕組みは同一です——セットアップは GitHub Webhook のローカルテストを参照。違いは URL の登録方法です。

  • GitHub App: アプリの設定ページで Webhook URL を設定。テスト用リポジトリにアプリをインストール。イベントを発火。以上。
  • OAuth App: アプリ自体に Webhook はありません。トンネル URL を指すリポジトリ Webhook を(リポジトリ設定ページから手動、または API で)追加します。

OAuth Apps では OAuth コールバックフロー自体もテストが必要です——OAuth コールバックをローカルでテストする方法を参照。

両者間の移行は苦痛

OAuth App で始めて後から GitHub App が必要だと気づいても、移行はできません。ユーザーは新アプリを再認可し、保存済みトークンは再発行し、OAuth App 経由で設定したリポジトリ Webhook は削除するまで発火し続けます。最初の 10 分を正しい種類選びに使いましょう。

どちらを選ぶか

GitHub App を選ぶのは:

  • 連携が独自のスケジュールやイベントへの反応で、ログイン中のユーザーなしに動く。
  • 特定のリポジトリや組織に限定された権限が欲しい。
  • リポジトリごとの設定ではなく、インストール範囲に紐づく Webhook が欲しい。
  • いずれ GitHub Marketplace に掲載されるものを作っている。

OAuth App を選ぶのは:

  • ツールがユーザーのログインする UI で、ユーザー自身の GitHub アカウント内で操作する。
  • アクセスパターンを含めユーザーとして正確に動作する必要がある。
  • Webhook が不要、またはリポジトリごとに手動で設定する。

署名検証の基礎は 署名検証ガイドを参照。GitHub の Webhook タイミングと再送用の捕捉を扱うトンネルは PortPreview のウェイトリストへ。

よくある質問

GitHub App と OAuth App のどちらを作るべきですか?
自律的に動く、限定権限が要る、インストール範囲に紐づく Webhook が欲しい連携なら GitHub App。ログイン中のユーザーの代わりに動くツールなら OAuth App。アクティブなユーザーがいない(ボット、自動化、定期タスク)なら、ほぼ常に GitHub App です。
GitHub App の Webhook はリポジトリ Webhook とどう違いますか?
GitHub Apps は、すべてのインストール範囲のイベントとインストールのライフサイクルイベントを受け取る、設定済みの Webhook URL を 1 つ持ちます。リポジトリ Webhook はリポジトリごとに設定し、インストールイベントは含みません。署名の仕組み(HMAC SHA-256、X-Hub-Signature-256)は同じです。
OAuth App を GitHub App に変換できますか?
直接はできません。新しい GitHub App を作り、ユーザーにインストールを依頼し、保存済みの認証情報を再発行し、OAuth App が設定したリポジトリ Webhook を片付けます。組み込みの移行はありません。ユーザーが認可を始める前に、種類を慎重に選びましょう。