Skip to content

Instantly share code, notes, and snippets.

@timmc
Last active April 15, 2025 09:23
Show Gist options
  • Select an option

  • Save timmc/d2814d7da19521dda1883dd3cc046217 to your computer and use it in GitHub Desktop.

Select an option

Save timmc/d2814d7da19521dda1883dd3cc046217 to your computer and use it in GitHub Desktop.
#!/bin/bash
echo "DO NOT USE -- incorrect signature format, see comments on gist."
exit 1
# Create and sign a JWT token with ES256 given the path to an ECDSA
# private key and a JSON payload.
# $0 path/to/keypair.der '{"JSON": "payload"}'
# Example keypair creation:
# openssl ecparam -name prime256v1 -genkey -noout -outform DER > example-keypair.der
# A few tips for generating the payload:
# - Pipe raw strings through `jq --raw-input .` to encode them as
# JSON strings. https://stedolan.github.io/jq/
# - GNU date is great for generating the iat, nbf, and exp time
# fields: `date --date="15 minutes" +"%s"`
set -eu -o pipefail
keypair_path="$1"
payload="$2"
function base64_urlsafe {
# Implement own URL-safe Base64 based on standard version. Delete
# padding, undo wrapping, and swap out chars 62 and 63. Not all
# versions of `base64` have the `--wrap=0` that GNU coreutils has.
base64 | tr -d '\r\n=' | tr '+/' '-_'
}
header_enc="$(echo -n '{"typ":"JWT","alg":"ES256"}' | base64_urlsafe)"
payload_enc="$(echo -n "$payload" | base64_urlsafe)"
message="$header_enc.$payload_enc"
# If you're on a Mac, you might have a really old version of openssl
# that doesn't support ECDSA signing this way.
sig="$(echo -n "$message" | openssl dgst -sha256 -sign "$keypair_path" -keyform DER | base64_urlsafe)"
echo -n "$message.$sig"
@stefanrenne
Copy link

I combined all the above with results from multiple stack overflow topics into the following, hopefully it helped someone :)

kid="3UT......."
iss="69a6de78-....."
keyPath="somepath/AuthKey.p8"

iat=$(date +"%s")
exp=$(date --date="15 minutes" +"%s")
header=$(echo -n '{"alg": "ES256", "kid": "'$kid'", "typ": "JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
payload=$(echo -n '{"iss": "'$iss'", "iat": '$iat', "exp": '$exp', "aud": "appstoreconnect-v1"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
sig=$(echo -n "$header.$payload" | openssl dgst -sha256 -sign "$keyPath" -keyform PEM | openssl asn1parse -inform DER | perl -n -e'/INTEGER           :([0-9A-Z]*)$/ && print $1' | xxd -p -r | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
jwt=$(echo -n "$header.$payload.$sig")

curl -X GET \
  -H "Authorization: Bearer $jwt" \
  -H "Content-Type: application/json" \
  https://api.appstoreconnect.apple.com/v1/apps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment