DEV Community

Rob Bos
Rob Bos

Posted on • Originally published at devopsjournal.io on

GitHub Tokens explained

There is a lot of confusion of what GitHub tokens are and how you should use them for automating things inside of GitHub. There are three main types of tokens:

  1. Personal Access Tokens (PATs)
  2. The GITHUB_TOKEN environment variable
  3. An access token created from a GitHub App

You can use these tokens to authenticate to GitHub and perform actions with it, like cloning repositories, making API calls, etc.

Photo of an old lock

Photo by James Sutton on Unsplash

1. Personal Access Tokens (PATs)

This type of token is often the first thing that people start to use when automating things. It is the same for different CI/CD systems like Azure DevOps that I’ve used before. A personal access token is inked to a user account and can be set to automatically expire. These days they are prefixed with ghp so that the secret scanner can detect them more easily.

You can use the PAT to do anything the user account that created them can do (as long as it is given the appropriate scopes for it):

  • Create repositories
  • Create issues
  • Create pull requests
  • Read security alerts
  • etc.

The downside of Personal Access Tokens

This token can actually do anything the user can do, but for anything the user has access to! If the user has access to repos, organizations or enterprises that have internal/private repos, the PAT has access to it! The only thing you can do is limit the scope it has, but not organizations or repos. (note: this is planned on the roadmap and very needed).

Because of this, using a PAT poses a big security risk. Do not hand them out to any random action in your workflows: if they store the PAT somewhere, they can read all your private repos (and more!). I recommend to stay away from using PATs if you can help it.

2. The GITHUB_TOKEN environment variable

The GITHUB_TOKEN is an environment variable you can use in your workflows by injecting it wherever you need it: $. The token is autogenerated and is not stored anywhere. It is a token that is only valid for the duration of the workflow it was created for. By default it has read and write access to the repository the workflow is running for. That means you cannot use this token for another repository. You can use it to do things like create issues, create pull requests, or comment on them. Depending on the context, it might get less permissions, for example: when running on a Pull Request coming from a fork, it will only have read access to the repository.

You can also give it a specific scope by setting that inside the workflow:

permissions:
  contents: read
  pull-requests: write

Enter fullscreen mode Exit fullscreen mode

This way, the token cannot be used for creating an issue for example, so even if the action you use tries to create an issue, the token doesn’t have the permissions to do so and thus it will fail.

If you want to learn more on the GITHUB_TOKEN, I have explained its use and how to limit what it can do in this short video.

3. An access token created from a GitHub App

You can use a GitHub App to have very specific access to one or more repositories. I use this for example for setting up a (lot of) Jenkins connections: each team at my customer has their own set of Jenkins jobs that should trigger when someone pushes a new commit to their GitHub repository. By giving each team their own GitHub App, I can limit the access the App has to only the repos that are relevant to them.

Note: on github.com you can only create 100 apps per organization. On GitHub Enterprise Server this restriction does not apply.

With a GitHub App, you get an AppId and a private key. You can create a GitHub App on website and then install it on the repositories (or organizations) you want to use it for. You can then use the AppId and the private key to create an access token that can be used to access the repositories. I have a GitHub Gist that shows you how to get an access token from a GitHub App. The steps are:

  1. Get the AppId and the private key from the GitHub App you created
  2. Generate a signed JWT token with the AppId and the private key
  3. With the JWT toke, get the installations of the app (you need the installation id to create the token)
  4. Create a token for the installation
  5. Use the token to access the repositories
Note: this token is only valid for 1 hour, after that you need to refresh it or your calls will fail

The downside of using GitHub Apps

GitHub Apps are great for automating things: they have more access then the GITHUB_TOKEN (across repositories for example) and do not have the issue that they operate from a user account and have access to everything the user has access to. There are some downsides as well:

  • only 100 apps per organization on github.com (so public repos or GitHub Enterprise Cloud: GHEC)
  • you cannot use this token to create repositories, users or teams
  • only minimal options to automate the setup of the apps themselves: you can use a manifest to create them, but installing them on repositories (even the ones you own), is not possible with an API.
  • little to no support on external tools: most of them want to have the token and cannot generate that token from the AppId and the private key, so you need to do that yourself (and be aware of the 1 hour expiration!)

Some things I have used GitHub Apps for:

  • Installing and configuring self hosted runners.
  • Configuring access from Jenkins pipelines to GitHub repos.
  • Inside workflows everywhere: I like the limited access the App has and do not want to give anything my PAT as it has way to much access!

Top comments (0)