Organizations may have a need to write applications or scripts which call GitHub APIs.
One common method for authenticating against GitHub APIs is to use personal access tokens (PATs), which are user-generated, fine-grained tokens. These tokens can be limited to specific repositories, and their permissions can be scoped to specific API operations. However, they do have potential drawbacks:
1) PATs are associated with a specific-user, so if these tokens are associated with a workflow, the original user who created the token must manage the lifecycle of these tokens, which includes creation, deletion, or re-generation of these tokens.
2) PATs typically have an expiration time of seven, 30, 60, or 90 days, or no expiration at all. Custom expiration dates can be specified, so the minimum time a new token would be valid would be the next calendar date – tokens can’t be set to expire for time periods less than a calendar day. If these tokens are exposed or exfiltrated, they could potentially be used improperly for the duration of their validity.
GitHub Applications allow for short-lived credentials which are associated with an organization to be created, instead of an individual. Similar to PATs, their permissions can be limited, and their access can be restricted to specific repositories. By default, the tokens generated by GitHub Apps have an expiration time of 8 hours.
Creating a GitHub Application
To create a GitHub application, go to your organization settings. Under Developer Settings, select GitHub Apps.

Then, click New GitHub App.

At a minimum, you will need to specify a GitHub App name and a home page URL:

Examine the remainder of the default settings to decide whether they need to be modified. If this GitHub App is only replacing a PAT, it should not be necessary to specify a webhook; in that case, mark the webhook as Inactive:

Next, configure the GitHub App with the appropriate permissions for your use case:

Finally, you can choose whether to limit usage of this GitHub App to your current account, or whether you want to make it a public application available to all accounts. Click Create GitHub App:

After creating your GitHub App, you will be taken to the Github app settings page. Click on Install App in the settings column:

You should see a list of available organizations in which you can install the application. Select the appropriate organization and click Install.
Assuming you selected app permissions that require repository access, you will see a dialog asking you to allow access to all of your organization repositories, or specific repositories.

After installation, return to the GitHub App settings page. You will need to create a private key to sign token access requests:

The GitHub App Installation ID is found embedded in the URL of the app under the Third-Party Access section of your GitHub organization settings:

After you click Generate a private key, a key will be generated and a PEM file will be downloaded to your system. Save this file, as it will be needed for generating GitHub App tokens.
Generating an Installation Access Token
Now that we have created a GitHub App, we can now generate a bearer token that can be used in GitHub API requests instead of a PAT. This bearer token is referred to as an Installation Access Token in the GitHub documentation. The process of generating an Installation Access Token has two steps:
- Create a JWT using the GitHub App Client ID and the previously downloaded PEM file.
- Generate the Installation Access Token using the JWT from the previous step along with the GitHub App Installation ID.
In order to perform these steps, let’s retrieve our GitHub App Client ID and the GitHub App Installation ID.
The Client ID is found on the GitHub App settings page:

Find your App, and click Configure:

After clicking Configure, examine the URL of the page in your browser. It should have the following format:
https://github.com/organizations/$ORGANIZATION/settings/installations/$INSTALLATION_ID
Copy the $INSTALLATION_ID portion of the URL; that is your GitHub App Installation ID.
Generate the JWT
Instructions for generating the JWT programmatically are here.
Code examples are provided. Provide the previously obtained Client ID and the location of your downloaded private key (PEM) file.
Generate the Installation Access Token
Now that we have a JWT, we can call the API to retrieve an Installation Access Token:
curl -s --request POST \
--url "https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens" \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer $JWT" \
--header "X-GitHub-Api-Version: 2022-11-28"
Replace $INSTALLATION_ID with the previously obtained GitHub App Installation ID, and $JWT with the previously generated JWT value.
This API will return an Installation Access Token which can now be used to invoke GitHub APIs.
Calling a GitHub API
Using curl as an example, if we were using a PAT, a GitHub API would be invoked as follows:
curl -u “$USERNAME:$TOKEN” $API_URL
$USERNAME would be replaced with the GitHub username of the PAT owner; $TOKEN is the actual PAT value.
In comparison, when invoking a GitHub API using a GitHub Application, the API invocation would appear as follows:
curl -H "Authorization: Bearer $TOKEN" $API_URL
$TOKEN would be replaced with the Installation Access Token generated in the previous section.
For example, if I wanted to call an API to get all the GitHub Action Runs for a particular repository (and assuming I set up my GitHub App permissions correctly), I would call the following:
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/aembit/$REPO/actions/runs?branch=main&per_page=100"
I would replace $TOKEN with the generated Installation Access Token, and replace $REPO with the name of my GitHub repository.
Conclusion
Now that we have created a GitHub App, we can integrate the steps of this workflow into our processes which call GitHub APIs. The GitHub App is managed under our organization settings, so its lifecycle management is not limited to a single GitHub user.
And since the installation access tokens are valid for eight hours by default, we don’t have to worry about rotating installation access tokens as we do for PATs, and we limit the window of opportunity for improper usage of a leaked or compromised token.