* _____ _ *_ _______ * _ * * ** *
/ ____| |* | | |__ __| | | * * π¦ *
| | *__| |_*| | βοΈ | | ___ | | _____*_ __ * *
| | |_ |* __ *| |*|/ _ \| |/ / _ \ '_ \ * *
| |__| | | | | * | | (_)*| < __/ | | | *
\_____|_| |_| |_|\___/|_|\_\___|_| |_| *
Create an installation access token for a GitHub app from your terminal
Creates an installation access token that enables a GitHub App to make authenticated API requests for the app's installation on an organization or individual account.
Installation tokens expire 1 hour from the time you create them. Using an expired token produces a status code of 401 - Unauthorized
, and requires creating a new installation token.
You can use this access token to make pretty much any REST or GraphQL API call the app is authorized to make!
In order to use GitHub's REST or GraphQL APIs you will need either a Personal Access Token (PAT) or a GitHub App.
PATs are dangerous, they:
- have a very wide scope that spans across multiple organizations
- never (automatically) expire. They have an indefinite lifetime (or at least until you regenerate them)
- cannot be revoked (they're only revoked when a new one is generated)
With an access token generated with a GitHub App you don't have to worry about the concerns above. These tokens have a limited scope and lifetime. Just make sure you handle the token safely (avoid leaking). In the worst case scenario, the token will expire in 1 hour from creation time.
Bash 5.x+
jq
shasum
Download ghtoken
from the main branch
# Download a file, name it ghtoken then do a checksum
wget -O ghtoken \
https://raw.githubusercontent.com/Link-/gh-token/main/gh-token && \
echo "11630050d3859d7fcaa42fad08c184cfe2ceeb3887779dc76394c4dba80903ef ghtoken" | \
shasum -c - && \
chmod u+x ./ghtoken
# Download a file, name it ghtoken following [L]ocation redirects, and
# automatically [C]ontinuing (resuming) a previous file transfer then
# do a checksum
curl -o ghtoken \
-O -L -C - \
https://raw.githubusercontent.com/Link-/gh-token/main/gh-token && \
echo "11630050d3859d7fcaa42fad08c184cfe2ceeb3887779dc76394c4dba80903ef ghtoken" | \
shasum -c - && \
chmod u+x ./ghtoken
You can install ghtoken
as a gh cli extension!
gh extensions install Link-/gh-token
# Verify installation
gh token
All the commands and parameters remain the same, the only different is you now can use gh token
instead of ghtoken
.
Follow these steps
Compatible with GitHub Enterprise Server.
Usage:
ghtoken generate (--key <key> | --base64_key <key>) --app_id <id> [--duration <minutes>] [--installation_id <id>] [--hostname <hostname>] [--install_jwt_cli]
ghtoken installations (--key <key> | -base64_key <key>) --app_id <id> [--duration <minutes>] [--hostname <hostname>] [--install_jwt_cli]
ghtoken revoke --token <token> [--hostname <hostname>]
ghtoken -h | --help
ghtoken --version
Options:
-h --help Display this help information.
--version Display version information.
-k <key>, --key <key> Path to a PEM-encoded certificate and key. [required]
-b <key>, --base64_key <key> Base64 encoded PEM certificate and key. [optional]
-i <id>, --app_id <id> GitHub App Id. [required]
-d <minutes>, --duration <minutes> The expiration duration of the JWT in minutes. [default: 10]
-o <hostname>, --hostname <hostname> The API URL of GitHub. [default: api.github.com]
-j, --install_jwt_cli Install jwt-cli (dependency) on the current system. [optional]
-l <id>, --installation_id <id> GitHub App installation id. [default: latest id]
-t <token>, --token <token> Access token to revoke. [required]
You can use the gh-token
tool as a GitHub Action. All you need to do is load the Action's parameters, and your off to creating jobs that generate
, revoke
, or fetch installations
details.
steps:
- name: "Generate Token"
uses: link-/gh-token@v1
with:
# Default action: generate | Options: generate, revoke, installations
# ACTION 'generate' will return environment variable: GENERATED_TOKEN
# ACTION 'installations' will return environment variable: INSTALLATIONS
# ACTION 'revoke' will only pass or fail with successful revoke of token
ACTION: generate
# Path to the private key, or base64 encoded string
PRIVATE_KEY: folder/key.pem
# GitHub App ID
APP_ID: 1234
# Duration of the JWT to live. | Default 10 min
DURATION: 15
# URRL to GitHub API. | Default: api.github.com
GITHUB_HOSTNAME: api.github.com
# Installation ID from GitHub App. Used only for checking installations
INSTALLATION_ID:
Once this is set, it will run the selected action. If you are running the action generate
, It will return the value GENERATED_TOKEN
back to the environment for usage.
# Assumed starting point
.
βββ .keys
βΒ Β βββ private-key.pem
βββ README.md
βββ ghtoken
1 directory, 3 files
# Run ghtoken
$ ghtoken generate \
--key ./.keys/private-key.pem \
--app_id 1122334 \
| jq
{
"token": "ghs_g7___MlQiHCYI__________7j1IY2thKXF",
"expires_at": "2021-04-28T15:53:44Z"
}
# Assumed starting point
.
βββ .keys
βΒ Β βββ private-key.pem
βββ README.md
βββ ghtoken
1 directory, 3 files
# Run ghtoken and add --install_jwt_cli
$ ghtoken generate \
--key ./.keys/private-key.pem \
--app_id 1122334 \
--install_jwt_cli \
| jq
{
"token": "ghs_8Joht_______________bLCMS___M0EPOhJ",
"expires_at": "2021-04-28T15:55:32Z"
}
# jwt-cli will be downloaded in the same directory
.
βββ .keys
βΒ Β βββ private-repo-checkout.2021-04-22.private-key.pem
βββ README.md
βββ ghtoken
βββ jwt
# Assumed starting point
.
βββ README.md
βββ ghtoken
1 directory, 2 files
# Run ghtoken and add --install_jwt_cli
$ ghtoken generate \
--base64_key $(printf "%s" $APP_KEY | base64) \
--app_id 1122334 \
--install_jwt_cli \
| jq
{
"token": "ghs_GxVel5cp__________DOaCv8eDs___2l94Ta",
"expires_at": "2021-04-28T16:30:59Z"
}
# Assumed starting point
.
βββ .keys
βΒ Β βββ private-key.pem
βββ README.md
βββ ghtoken
1 directory, 3 files
# Run ghtoken and specify the --hostname
$ ghtoken generate \
--key ./.keys/private-key.pem \
--app_id 2233445 \
--installation_id 5 \
--install_jwt_cli \
--hostname "github.example.com" \
| jq
{
"token": "v1.bb1___168d_____________1202bb8753b133919",
"expires_at": "2021-04-28T16:01:05Z"
}
# Assumed starting point
.
βββ .keys
βΒ Β βββ private-key.pem
βββ README.md
βββ ghtoken
1 directory, 3 files
# Run ghtoken and specify the --hostname
$ ghtoken installations \
--key ./.keys/private-key.pem \
--app_id 2233445 \
--install_jwt_cli \
--hostname "github.example.com" \
| jq
Response
[
{
"id": 1,
"account": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"access_tokens_url": "https://api.github.com/installations/1/access_tokens",
"repositories_url": "https://api.github.com/installation/repositories",
"html_url": "https://github.com/organizations/github/settings/installations/1",
"app_id": 1,
"target_id": 1,
"target_type": "Organization",
"permissions": {
"checks": "write",
"metadata": "read",
"contents": "read"
},
"events": [
"push",
"pull_request"
],
"single_file_name": "config.yaml",
"has_multiple_single_files": true,
"single_file_paths": [
"config.yml",
".github/issue_TEMPLATE.md"
],
"repository_selection": "selected",
"created_at": "2017-07-08T16:18:44-04:00",
"updated_at": "2017-07-08T16:18:44-04:00",
"app_slug": "github-actions",
"suspended_at": null,
"suspended_by": null
}
]
# Run ghtoken with the revoke command
$ ghtoken revoke \
--token "v1.bb1___168d_____________1202bb8753b133919"
--hostname "github.example.com"
204: Token revoked successfully
Integrate with GitHub's CLI
You can use ghtoken alongside gh cli by setting these aliases:
# Add ghtoken to a folder included in your PATH environment variable
ln -s <PATH TO THE SCRIPT>/ghtoken /usr/local/bin/ghtoken
# Set a token generation alias. This will always generate a token from
# the app ID and key supplied.
$ gh alias set token -s 'ghtoken generate --key /tmp/private-key.pem --app_id 112233'
# Usage
$ gh token
{
"token": "ghs_1gCKrYvkh3_______7JZFlZw______w1FE",
"expires_at": "2021-05-15T22:34:10Z"
}
# You can also set an alias to revoke tokens
$ gh alias set revokeToken -s 'ghtoken revoke --token "$1"'
# Usage
$ gh revokeToken "ghs_1gCKrYvkh3_______7JZFlZw______w1FE"
204: Token revoked successfully
Make sure your pem
file has the extension .pem
. This is necessary for jwt-cli
to be able to determine the type of key it's trying to parse.
If you see this response:
{
"token": null,
"expires_at": null
}
This is an indication that the script was not able to fetch an installation id
and that the GitHub App has not been installed
for an Organization or User.
Make sure you're running bash 5.x+
. If you're running MacOS, the version of bash
installed is 3.2
which is not compatible with this tool.
# Upgrade bash and that should resolve your problem
brew upgrade bash
You can install a GitHub on 1 or more organizations. As such, the installation ID points to a specific installation on a specific organization. By default gh-token
will use the latest installation id, however, you have the option to point to any installation and you can fetch that ID with the installations
command. Check the Fetch list of installations for an app
above for more details.
These are not endorsements, just a listing of similar art work