-
-
Save carestad/bed9cb8140d28fe05e67e15f667d98ad to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
# Generate JWT for Github App | |
# | |
# Inspired by implementation by Will Haley at: | |
# http://willhaley.com/blog/generate-jwt-with-bash/ | |
# From: | |
# https://stackoverflow.com/questions/46657001/how-do-you-create-an-rs256-jwt-assertion-with-bash-shell-scripting | |
thisdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
set -o pipefail | |
# Change these variables: | |
app_id=1337 | |
app_private_key="$(< $thisdir/app.key)" | |
# Shared content to use as template | |
header='{ | |
"alg": "RS256", | |
"typ": "JWT" | |
}' | |
payload_template='{}' | |
build_payload() { | |
jq -c \ | |
--arg iat_str "$(date +%s)" \ | |
--arg app_id "${app_id}" \ | |
' | |
($iat_str | tonumber) as $iat | |
| .iat = $iat | |
| .exp = ($iat + 300) | |
| .iss = ($app_id | tonumber) | |
' <<< "${payload_template}" | tr -d '\n' | |
} | |
b64enc() { openssl enc -base64 -A | tr '+/' '-_' | tr -d '='; } | |
json() { jq -c . | LC_CTYPE=C tr -d '\n'; } | |
rs256_sign() { openssl dgst -binary -sha256 -sign <(printf '%s\n' "$1"); } | |
sign() { | |
local algo payload sig | |
algo=${1:-RS256}; algo=${algo^^} | |
payload=$(build_payload) || return | |
signed_content="$(json <<<"$header" | b64enc).$(json <<<"$payload" | b64enc)" | |
sig=$(printf %s "$signed_content" | rs256_sign "$app_private_key" | b64enc) | |
printf '%s.%s\n' "${signed_content}" "${sig}" | |
} | |
sign |
Hi, Thanks for sharing this script.
What do we need to pass to the authorization? I tried as below but both of them didn't work.
Hi, @michaelsync!
That's a fair question. I have been ussing it like this:
#!/bin/bash
generated_jwt=$(./github-app-jwt.sh)
curl -s \
-H "Authorization: Bearer ${generated_jwt}" \
-H "Accept: application/vnd.github.machine-man-preview+json" \
"${github_api_url}"
So from what I can tell both the Authorization
and Accept
headers are different. But I use it to authorize use with a Github App, which might work a bit differently. More info about how to auth as a Gitub app here: https://docs.github.com/en/free-pro-team@latest/developers/apps/authenticating-with-github-apps#authenticating-as-a-github-app
Thanks. Where do you get "generated_jwt"? I don't see it in your script. Is "generated_jwt" as same as ${sig}?
I am trying to find out which one is the JWT token. Is it "${sig}
or Is it "${signed_content}"."${sig}"
?
I figure it out. The JWT is "${signed_content}"."${sig}"
Thanks.
Thanks. Where do you get "generated_jwt"? I don't see it in your script. Is "generated_jwt" as same as ${sig}?
I am trying to find out which one is the JWT token. Is it
"${sig}
or Is it"${signed_content}"."${sig}"
?
I see you figured it out, @michaelsync. $generated_jwt
is basically the output of the entire script there. I will update my previous response so it is more clear 👍
It helped me a lot. THX!
Thanks! Works great. Strange that Gihub doesn't give bash script as official example, only Ruby.
Jesus - finally. Went in circles looking for a solution but this one works.
Just wanted to say thanks for this. Very helpful!
Thanks a lot, I tried with several methods to create this token without lucky until I used this method.
On MacOS i do get the following error:
line 42: ${algo^^}: bad substitution
Any idea why?
@89pleasure I got the same error. I worked around it using an Ubuntu Docker container.
For others with this problem you will have to upgrade your version of the bash shell. OSX ships with v3, and the latest is v5.
brew install bash
/opt/homebrew/Cellar/bash/5.2.15/bin/bash script.sh
Hi, Thanks for sharing this script.
What do we need to pass to the authorization? I tried as below but both of them didn't work.
With SIG only
With SIG + content