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:
You can use these tokens to authenticate to GitHub and perform actions with it, like cloning repositories, making API calls, etc.
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):
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.
Additionally, they are linked to a user, so when that user leaves the company (and the user account is disabled): all automations using their PAT will stop working!
Note: the only valid reason for using the GitHub Token is for accessing things in the API from the Enterprise level, in case you need to automate things like the creation of users, which should be done with SCIM as a best practice. So still, most of this reason is not valid 😏.
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
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.
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 (by installing the App on only their repositories and not all repos in the organization). Since this token is tied to the installation of the App, we call this an installation token.
With a GitHub App, you get an AppId and a private key in the PEM format. You can create a GitHub App on a 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.
There are multiple options to get the token, depending where you want to use it:
I have a GitHub Gist that shows you how to get an access token from a GitHub App from shell scripts (I have an example how to call the shell script from PowerShell as well).
The steps are:
You can then use this token for any API call you want to make (and that is accessible for an App. Creating codespaces is not for example, since you can only create a codespace for your own user account).
In the gist you also find an example of using git config rewriting to overwrite the global git config with a rule that maps a SSH setup to a HTTPS setup that includes the access token. This can be helpful to help custom scripts / tools that can are preconfigured with only SSH support.
Inside of a workflow I always use the action from Peter Murray. It takes an application_id and an application_private_key and generates a token that can be used to access the repositories. You can even give the token it creates a scope by sending in the
My buddy Bassem Dghaidi has created a bash library that does the work for you, and can be included in the GitHub CLI. You can find it in this repo with all the setup needed. You can for example use this easily in a Docker container when you are automating things.
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 (like a PAT).
There are some downsides as well: