Першого разу, будуючи інтеграцію з GitHub, ви витратите годину, зʼясовуючи, що вам потрібно — GitHub App чи OAuth App. Документація подає їх як рівноцінні варіанти. Це не так. Самої історії з вебхуками здебільшого досить, щоб вибір зробився сам.
Дуже коротке резюме
- GitHub App: встановлюється на акаунти чи репозиторії, має тонко налаштовувані права, отримує вебхуки для ресурсів, де встановлена, автентифікується як вона сама короткоживучими токенами.
- OAuth App: користувачі її авторизують, вона діє від їхнього імені з їхніми правами, отримує вебхуки лише якщо налаштує їх як будь-який сторонній інструмент, автентифікується як користувач довгоживучими токенами.
Якщо ви будуєте щось, що працює без активного користувача — CI-бота, автоматизацію код-рев’ю, щось за розкладом — вам потрібна GitHub App. Якщо будуєте інструмент, що виконує дії від імені залогіненого користувача (наприклад, UI пошуку по коду), правильна форма — OAuth App.
Як вони отримують вебхуки
GitHub Apps
Ви налаштовуєте один URL вебхука при створенні застосунку. Коли користувач встановлює застосунок на акаунт чи репозиторій, GitHub починає слати події цього охоплення на ваш URL. Серед подій — installation (життєвий цикл установки/видалення), installation_repositories (додані чи прибрані репозиторії) і ті типи подій, на які підписаний ваш застосунок (push, pull_request тощо).
Кожна подія містить заголовок X-GitHub-Hook-Installation-Target-Type («integration») та installation ID, яким можна випустити токен для цієї конкретної установки. Підпис — HMAC SHA-256 у X-Hub-Signature-256 — та сама форма, що у вебхуків репозиторію.
OAuth Apps
В OAuth Apps немає вбудованої підписки на вебхуки. Щоб отримувати вебхуки, авторизовані користувачі застосунку мають створити вебхуки репозиторію чи організації, що вказують на URL застосунку. Це означає, що охоплення вебхуків застосунку привʼязане до того, де його користувачі налаштували підписки, а не до того, де «встановлено» сам застосунок.
Деякі команди будують OAuth Apps, що після авторизації автоматично створюють вебхуки через API GitHub. Працює, але тепер ви керуєте життєвим циклом вебхуків для кожного користувача поряд із власною логікою застосунку.
Автентифікація — ось де справжнє розходження
GitHub Apps автентифікуються запитами, підписаними JWT, щоб випускати короткоживучі installation-токени (1 година) на кожну установку. JWT підписується приватним ключем, який ви генеруєте при створенні застосунку. Ваш код:
// 1. Підписати JWT приватним ключем застосунку (термін 10 хв)
const jwt = createAppJwt(APP_ID, PRIVATE_KEY);
// 2. Обміняти JWT на installation-токен (дійсний 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}` },
});
Installation-токени обмежені установкою й закінчуються автоматично — тож витік має обмежений радіус ураження.
OAuth Apps автентифікуються користувацькими access-токенами зі стандартного OAuth-флоу. Ці токени за замовчуванням довгоживучі й діють як користувач — витік одного означає, що зловмисник може все, що міг би цей користувач. Документація GitHub підштовхує до GitHub Apps для нових інтеграцій частково з цієї причини.
Права: обмежені проти широких
GitHub Apps дозволяють запитувати гранульовані права: читати issues, писати checks, читати pull requests, без доступу до решти. Кожне право незалежне. Користувач бачить точний список і може відмовити.
OAuth Apps використовують старішу систему на основі scope: repo, read:user тощо. Scope грубіші. Scope repo дає доступ на читання й запис до всіх репозиторіїв, які бачить користувач, — версії «лише читання на конкретних репозиторіях» немає.
Для бота код-рев’ю, якому треба лише читати код і писати check runs, GitHub App із двома конкретними правами значно менш інвазивна за OAuth App, що просить повний доступ repo.
Локальне тестування обох
Механіка підпису вебхука однакова — про налаштування див. локальне тестування вебхуків GitHub. Різниця в тому, як ви реєструєте URL.
- GitHub App: вкажіть URL вебхука на сторінці налаштувань застосунку. Встановіть застосунок на тестовий репозиторій. Запустіть події. Готово.
- OAuth App: у самого застосунку вебхуків немає. Додайте вебхук репозиторію (вручну на сторінці налаштувань репозиторію або програмно через API), що вказує на ваш URL тунелю.
Для OAuth Apps потрібно також протестувати сам OAuth-колбек-флоу — див. як тестувати OAuth-колбеки локально.
Міграція між ними болісна
Якщо почали з OAuth App і згодом зрозуміли, що потрібна GitHub App, мігрувати не можна. Користувачам доведеться заново авторизувати новий застосунок, вам — заново випускати збережені токени, а всі вебхуки репозиторію, налаштовані через OAuth App, спрацьовуватимуть, поки їх не видалять. Витратьте десять хвилин на початку на вибір правильного типу.
Коли що обирати
Обирайте GitHub App, коли:
- Ваша інтеграція працює за власним розкладом або у відповідь на події, без залогіненого користувача.
- Вам потрібні обмежені права на конкретні репозиторії чи організації.
- Вам потрібні вебхуки, привʼязані до охоплення установки, а не налаштовані за репозиторіями.
- Ви будуєте щось, що згодом потрапить до GitHub Marketplace.
Обирайте OAuth App, коли:
- Ваш інструмент — це UI, у який користувачі входять і діють у власному акаунті GitHub.
- Потрібно діяти точно як користувач, включно з його патернами доступу.
- Вебхуки не потрібні, або ви налаштуєте їх вручну за репозиторіями.
Про деталі перевірки підпису див. посібник з перевірки підписів. Приєднайтеся до списку очікування PortPreview заради тунелю, що дає раду з таймінгом вебхуків GitHub і захопленням для повтору.