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.
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
- https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app — Account permissions allow your app to access resources related to a user if the user has also authorized your app, which is the mechanism controlling user-level endpoints for GitHub Apps rather than OAuth scopes.
- https://docs.github.com/en/rest/users/emails — GET /user/emails documents that OAuth app tokens and personal access tokens (classic) need the user:email scope, indicating scope-based access applies to OAuth apps and PATs rather than GitHub App user tokens.