Skip to content

GitHub Authentication Notes

Karen Cranston edited this page Nov 12, 2020 · 2 revisions

These are notes from the November 2020 change in how we generate tokens for GitHub API authentication. See GitHub blog post for motivation.

Existing abc-classroom git actions

We access git and github functionality two ways in abc-classroom:

  1. Command-line git operations (e.g. git commit or git clone) implemented as python subprocess calls in the _call_git function. This simply runs with the user's local git setup and SSH keys.
  2. GitHub operations, implemented through the GitHub API. These are the ones that need to change for the upcoming deprecation.

In the abc-init script, we set up GitHub API api authentication by authenticating with a username and password, and use that authentication to generate a personal access token. We save the token to a local file and read it back in when we make an API call.

The other abc scripts access git and github actions as follows:

abc-quickstart : no git or github steps

abc-new-template and abc-update-template use the following methods:

  • init_and_commit : command-line git
  • remote_repo_exists : GitHub API call
  • create_repo : GitHub API call
  • add_remote : command-line git
  • push_to_github : local git action

abc-clone uses only command-line git actions (calling pull_from_github, clone_repo), as does abc-feedback (calling commit_all_changes and push_to_github)

So, the only two API calls that we use are:

create an organization repository - requires authentication

get-a-repository - this does not need authentication for public repos, but does for private repos (which is true in our case)

Authentication

We are proceeding by creating a GitHub App for accessing the API, abc-classroom-bot. We install the app on the organization(s) that we need access to, and then authenticate as a user that has read + write access to the organization repos. The app is currently installed on earthlab-education (production) and earth-analytics-edu (dev, the pig organization).

There are two types of authentication methods for a GitHub app. You can authenticate as the installed app (so actions are done on behalf of the app), or you can authenticate as a user (so actions are done on behalf of the user).

Installation-based authentication requires that the app has access to its private key in order to generate the JSON Web Token (JWT). It is unclear to me how to handle this with a command-line app that is installed on the user's computer (with a web-based app, you would have the private key on a server that is not accessible to the user.)

Therefore, I've gone with user-based authentication via the device flow process, which generates a 'user-to-server' access token. See the GitHub docs for user-based authentication. I am not using expiring user tokens at this point, as refreshing the token this would require the app to have access to the client secret (the private key).

The permissions are much more fine-grained than with a personal access token. With a personal access token (the method we are using now), the token allows you to anything through the API that you can do via the GitHub web interface.

With the GitHub App, you set the precise permissions that you need on each type of resource (repos, issues, pull requests, etc). The app then only has access to a resource when it is requested by the app and available to the
authenticated user.

Gory details of authentication

The authentication workflow is as follows (when you run abc-init):

  • Try existing token: the app tries to read the token from the .abc-classroom.tokens.yml file in the user's home directory
    • if there is no file, it generates a new token
    • if there is a token, it tests to see if it is valid by making a call to get the authenticated user. This returns a 404 if there is no authentication
  • If the existing token is missing or invalid, we generate a new one:
    • Step 1: Call https://github.com/login/device/code using the client_id of the GitHub App. This id is unique to abc-classroom-bot and is hardcoded. This call returns a device_code to the app.
    • Step 2: Print a message to the user on the command line asking them to go to https://github.com/login/device in a web browser, enter a temporary user code, and then hit in the terminal when they have done so.
    • Step 3: Call https://github.com/login/oauth/access_token with the device_code. If the user has successfully entered the user code, the app gets back an access_token. We write this to the file .abc-classroom.tokens.yml.
  • Using the token: when making subsequent API calls, we use the access_token in the header of the call (currently by providing it as a parameter to methods in the gthub3 library, but this will likely change in the future to either the pygithub library or by implementing the calls using requests).
Clone this wiki locally