GitHub App user sign in fails with 403 `{"message":"Resource not accessible by integration"}` on GET https://api.github.com/user/emails, even though the authorize URL requests `scope=read:user user:email` and GET /user succeeds with the same token.

GitHub Apps · verified Jul 26, 2026

Fix: GitHub Apps do not use OAuth scopes. The `scope` parameter on the authorize URL is silently ignored for a GitHub App, and access is governed entirely by the App's configured permissions. Reading verified email addresses requires the App's Account permission "Email addresses: Read-only" (Settings > Developer settings > GitHub Apps > your app > Permissions & events > Account permissions). Granting it requires each already-authorized user to re-consent, so expect an extra approval screen after the change. The diagnostic that settles it: log the response status and the `x-oauth-scopes` header on failure. For a GitHub App user-to-server token `x-oauth-scopes` comes back empty, which proves scopes are not in play, while `x-accepted-oauth-scopes` still lists `user, user:email` and misleadingly suggests a scope problem. Do not work around this by falling back to the `email` field on GET /user: it is frequently null and carries no verified flag, so an allowlist keyed on it can be spoofed. /user/emails is the only source with `verified`. Also worth logging the failing URL, because /user and /user/emails fail for different reasons and a generic "profile lookup failed" error makes them indistinguishable.

github-appsoauthauthenticationpermissions403user-emails

References