Beim ersten Mal, wenn du eine GitHub-Integration baust, verbringst du eine Stunde damit, herauszufinden, ob du eine GitHub App oder eine OAuth App willst. Die Docs behandeln sie als gleichwertige Optionen. Sind sie nicht. Allein die Webhook-Geschichte reicht meist, um dir die Wahl abzunehmen.
Die sehr kurze Zusammenfassung
- GitHub App: auf Accounts oder Repositories installiert, hat feingranulare Berechtigungen, empfängt Webhooks für die Ressourcen, auf denen sie installiert ist, authentifiziert sich als sie selbst mit kurzlebigen Tokens.
- OAuth App: Nutzer autorisieren sie, sie handelt in deren Namen mit deren Berechtigungen, empfängt Webhooks nur, wenn sie sie wie jedes Drittanbieter-Tool einrichtet, authentifiziert sich als der Nutzer mit langlebigen Tokens.
Baust du etwas, das ohne aktiven Nutzer arbeitet — einen CI-Bot, eine Code-Review-Automation, irgendetwas Geplantes —, willst du eine GitHub App. Baust du ein Tool, das Aktionen im Namen eines eingeloggten Nutzers ausführt (etwa eine Code-Such-UI), ist eine OAuth App die richtige Form.
Wie sie Webhooks empfangen
GitHub Apps
Du konfigurierst eine Webhook-URL beim Erstellen der App. Installiert ein Nutzer die App auf einem Account oder Repository, beginnt GitHub, Events für diesen Scope an deine URL zu senden. Events umfassen installation (Install-/Uninstall-Lebenszyklus), installation_repositories (hinzugefügte oder entfernte Repos) und die Event-Typen, die deine App abonniert hat (push, pull_request usw.).
Jedes Event enthält einen X-GitHub-Hook-Installation-Target-Type-Header („integration") und eine Installation-ID, mit der du ein Token für diesen konkreten Install minten kannst. Die Signatur ist HMAC SHA-256 in X-Hub-Signature-256 — dieselbe Form wie Repository-Webhooks.
OAuth Apps
OAuth Apps haben kein eingebautes Webhook-Abo. Um Webhooks zu empfangen, müssen die autorisierten Nutzer der App Repository- oder Organisations-Webhooks erstellen, die auf die URL der App zeigen. Damit hängt die Webhook-Reichweite der App davon ab, wo ihre Nutzer Abos eingerichtet haben, nicht davon, wo die App selbst „installiert" ist.
Manche Teams bauen OAuth Apps, die nach der Autorisierung automatisch Webhooks über die GitHub-API anlegen. Das funktioniert, aber du verwaltest dann den Webhook-Lebenszyklus pro Nutzer neben der eigentlichen App-Logik.
Die Authentifizierung ist der echte Unterschied
GitHub Apps authentifizieren sich über JWT-signierte Requests, um kurzlebige Installation-Tokens (1 Stunde) pro Install zu minten. Das JWT wird mit einem Private Key signiert, den du beim Erstellen der App generierst. Dein Code:
// 1. JWT mit dem Private Key der App signieren (10-Min-Ablauf)
const jwt = createAppJwt(APP_ID, PRIVATE_KEY);
// 2. JWT gegen ein Installation-Token tauschen (1 Stunde gültig)
const token = await fetchInstallationToken(jwt, INSTALLATION_ID);
// 3. API-Aufrufe mit diesem Token machen
const res = await fetch('https://api.github.com/repos/x/y/issues', {
headers: { Authorization: `token ${token}` },
});
Installation-Tokens sind auf den Install begrenzt und laufen automatisch ab — ein Leak hat begrenzten Schaden.
OAuth Apps authentifizieren sich mit User-Access-Tokens aus dem Standard-OAuth-Flow. Diese Tokens sind standardmäßig langlebig und handeln als der Nutzer — ein Leak bedeutet, ein Angreifer kann alles tun, was dieser Nutzer könnte. Die GitHub-Docs schubsen dich auch deshalb zu GitHub Apps für neue Integrationen.
Berechtigungen: scoped vs. breit
GitHub Apps lassen dich granulare Berechtigungen anfordern: Issues lesen, Checks schreiben, Pull Requests lesen, sonst kein Zugriff. Jede Berechtigung ist unabhängig. Der Nutzer sieht die genaue Liste und kann ablehnen.
OAuth Apps nutzen das ältere Scope-System: repo, read:user usw. Scopes sind gröber. Der repo-Scope gewährt Lese- und Schreibzugriff auf alle Repositories, die der Nutzer sehen kann — es gibt keine „nur-lesen auf bestimmten Repos"-Variante.
Für einen Code-Review-Bot, der nur Code lesen und Check-Runs schreiben muss, ist eine GitHub App mit zwei spezifischen Berechtigungen weit weniger invasiv als eine OAuth App, die vollen repo-Zugriff verlangt.
Lokales Testen mit beiden
Die Webhook-Signatur-Mechanik ist identisch — siehe GitHub-Webhook-Local-Testing für das Setup. Der Unterschied ist, wie du die URL registrierst.
- GitHub App: Setze die Webhook-URL auf der Settings-Seite deiner App. Installiere die App auf einem Test-Repository. Löse Events aus. Fertig.
- OAuth App: Die App selbst hat keine Webhooks. Füge einen Repository-Webhook hinzu (manuell über die Repo-Settings oder programmatisch per API), der auf deine Tunnel-URL zeigt.
Bei OAuth Apps musst du auch den OAuth-Callback-Flow selbst testen — siehe wie man OAuth-Callbacks lokal testet.
Zwischen beiden zu migrieren ist schmerzhaft
Startest du mit einer OAuth App und merkst später, dass du eine GitHub App brauchst, kannst du nicht migrieren. Nutzer müssen die neue App neu autorisieren, du musst gespeicherte Tokens neu ausstellen, und alle über die OAuth App eingerichteten Repository-Webhooks feuern weiter, bis sie gelöscht sind. Investiere vorab zehn Minuten, um den richtigen Typ zu wählen.
Wann was wählen
Wähle eine GitHub App, wenn:
- Deine Integration auf eigenem Zeitplan oder als Reaktion auf Events läuft, ohne eingeloggten Nutzer.
- Du scoped Berechtigungen auf bestimmten Repositories oder Organisationen willst.
- Du Webhooks an den Install-Scope gebunden willst, nicht pro Repo konfiguriert.
- Du etwas baust, das irgendwann im GitHub Marketplace gelistet wird.
Wähle eine OAuth App, wenn:
- Dein Tool eine UI ist, in die sich Nutzer einloggen und in ihrem eigenen GitHub-Account Dinge tun.
- Du genau als der Nutzer handeln musst, samt seiner Zugriffsmuster.
- Du keine Webhooks brauchst oder sie manuell pro Repo einrichtest.
Zu den zugrunde liegenden Details der Signaturprüfung siehe den Leitfaden zur Signaturprüfung. Tritt der PortPreview-Warteliste bei für einen Tunnel, der GitHubs Webhook-Timing und Erfassung zur Wiederholung beherrscht.