#!/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 |
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.
Hi, @michaelsync!
That's a fair question. I have been ussing it like this:
So from what I can tell both the
Authorization
andAccept
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