netgusto
netgusto

Reputation: 191

How to securely associate a Github App Install ID with the account of a website integrating with the GitHub App?

I'm in the process of building a website integrated around a GitHub App of mine.

This website has its own users (from Google oAuth), who can connect their account to their GitHub account by installing my GitHub application.

There's something in the GitHub App install process I cannot wrap my head around:

After a user installs my App on GitHub:

The install ID is a sensible info, as if a malicious user of my website (the attacker) can trick my website into associating their account with the GitHub Install ID of somebody else (the victim), my website would operate on the GitHub API of the victim on behalf of the attacker (which is bad!).

Now, my goal is to securely bind this install ID to the user of my website. By secure, I mean that it is impossible for my website to grant an attacker permissions on a victim GitHub install of my app.

Using the GitHub install ID provided in the "Post install Setup URL" to bind this install to an account of my website is insecure, as I have no way to validate that this install ID "belongs" to the user of my website, as the URL can be forged by an attacker knowing a valid install ID of a victim.

Imperfect mitigations:

Am I missing something, or is this a flaw of the App authorization model ?

Upvotes: 11

Views: 1789

Answers (2)

Pēteris Caune
Pēteris Caune

Reputation: 45182

I'm looking into the exact same problem, and here's the plan I have currently pieced together:

I have a SaaS app, let's call it FooApp, which has "GitHub integrations" – my app's users can configure my app to open new issues in user-selected repos. The flow for setting up a new GitHub integration:

  • In FooApp, the user clicks on a "Connect GitHub" button
  • FooApp performs an OAuth web application flow to get user's access token:
    • FooApp redirects the user to https://github.com/login/oauth/authorize?client_id=...&state=....
    • User accepts authorization request, GitHub redirects back to my app, and passes a code query parameter
    • FooApp exchanges the code for user access token ("ghu_***") by calling https://github.com/login/oauth/access_token
  • FooApp looks up what installations the user has access to by calling https://api.github.com/user/installations and using user's access token for authentication
  • For each installation, FooApp loads the list of repos by calling https://api.github.com/user/installations/INSTALLATION_ID/repositories and using user's access token for authentication
  • FooApp presents the list of available repos to the user and asks the user to pick one
  • The user picks a repo. FooApp stores the selected repo name and corresponding installation_id in the database

When it is time to perform an action (say, create an issue) in user's selected repository, FooApp loads the installation_id and repo name from the database, acquires installation access token ("ghs_***") for it, and then makes the "create issue" API call using the installation access token for authentication.

Notes:

When FooApp presents the list of available repos, it should also include a comment along the lines of "Don't see the repo you are looking for? [Click Here] to install FooApp in you GithHub personal or organization account". The link would take the user to the GitHub app's installation page. And if the list of repositories is empty, FooApp can redirect to the app's installation page without asking.

Suppose Eve somehow finds out Alice's installation_id, and tries to set up a GitHub integration in FooApp that points to one of Alice's repos. Eve cannot impersonate Alice in the OAuth flow (as Eve is not logged into GitHub as Alice), so FooApp receives Eve's user access token. FooApp uses Eve's user access token to read the installations and repos Eve has access to, and only lets Eve choose a repo from those. Even if Eve knows one of Alice's installation_ids, the app does not give Eve the opportunity to smuggle it in. Or at least that's the idea.


What I find confusing is that GitHub docs doesn't seem to have clear guidance on associating installation ids with users in 3rd party apps. Given that developers are often happy to use the first solution that appears to work, the security risks are high here. And I still have no idea if the above flow I cobbled together is secure, or I missed something...

Upvotes: 0

netgusto
netgusto

Reputation: 191

Found the answer:

I needed to activate "Request user authorization (OAuth) during installation". This way, GitHub answers with a secure token that I can use to validate the installation instead of just the installation ID.

Documentation: https://docs.github.com/en/free-pro-team@latest/developers/apps/identifying-and-authorizing-users-for-github-apps#web-application-flow

Upvotes: 7

Related Questions