Skip to content

Instantly share code, notes, and snippets.

@stokito
Last active January 9, 2022 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stokito/43afca84fc34d1d362bf210cd941a366 to your computer and use it in GitHub Desktop.
Save stokito/43afca84fc34d1d362bf210cd941a366 to your computer and use it in GitHub Desktop.
OpenWrt specific shell (ash) script to decode JWT token and verify it's signature. Based on https://gist.github.com/stokito/f2d7ea0b300f14638a9063559384ec89

You'll need to instll OpenSSL and it will use about 1.3Mb. So check that it's enought of available space:

df -h | grep /overlay

Then install it:

opkg install openssl-util

It also will install libopenssl1.1 and libopenssl-conf.

#!/bin/ash
# Usage: cat /id_token.txt | jwt-decode.sh --no-verify-sig" > jwt_payload.json
. /usr/share/libubox/jshn.sh
base64_padding()
{
local len=$(( ${#1} % 4 ))
local padded_b64=''
if [ ${len} = 2 ]; then
padded_b64="${1}=="
elif [ ${len} = 3 ]; then
padded_b64="${1}="
else
padded_b64="${1}"
fi
echo -n "$padded_b64"
}
base64url_to_b64()
{
base64_padding "${1}" | tr -- '-_' '+/'
}
# read the JWT from stdin and split by comma into three variables
IFS='.' read -r JWT_HEADER_B64URL JWT_PAYLOAD_B64URL JWT_SIGNATURE_B64URL
JWT_PAYLOAD_B64=$(base64url_to_b64 "${JWT_PAYLOAD_B64URL}")
JWT_PAYLOAD=$(echo "${JWT_PAYLOAD_B64}" | base64 -d)
if [ "$1" != "--no-verify-sig" ]; then
if [ -z $(command -v openssl) ]; then
>&2 echo "Error 2: To verify signature install openssl-util"
exit 2
fi
JWT_HEADER_B64=$(base64url_to_b64 "${JWT_HEADER_B64URL}")
JWT_SIGNATURE_B64=$(base64url_to_b64 "${JWT_SIGNATURE_B64URL}")
JWT_HEADER=$(echo "${JWT_HEADER_B64}" | base64 -d)
json_init
json_load "$JWT_HEADER"
json_get_var JWT_ALG alg
json_get_var JWT_KID kid
# verify signature
if [ "${JWT_ALG}" = "RS256" ]; then
PUB_KEY_FILE="/var/tmp/oauth/$JWT_KID.key.pub.pem"
if [ ! -f $PUB_KEY_FILE ]; then
>&2 echo "No pub key $JWT_KID"
json_init
json_load "$JWT_PAYLOAD"
json_get_var JWT_ISS iss
if [ $JWT_ISS = "https://accounts.google.com" ]; then
mkdir -p /var/tmp/oauth/
# use old jwks_url which return certs in PEM format
OAUTH_CERTS_URL="https://www.googleapis.com/oauth2/v1/certs"
echo "Fetch it from $OAUTH_CERTS_URL"
wget $OAUTH_CERTS_URL -q -O /tmp/jwks.json
CERT_FILE="/tmp/$JWT_KID.crt"
jsonfilter -i /tmp/jwks.json -e "@.$JWT_KID" > "$CERT_FILE"
rm /tmp/jwks.json
openssl x509 -pubkey -in "$CERT_FILE" -noout > "$PUB_KEY_FILE"
rm "$CERT_FILE"
else
>&2 echo "Error 4: Unable to get public key"
exit 4
fi
fi
SIG_FILE=$(mktemp)
echo -n "$JWT_SIGNATURE_B64" | base64 -d > "${SIG_FILE}"
JWT_BODY=$(echo -n "$JWT_HEADER_B64URL.$JWT_PAYLOAD_B64URL")
JWT_SIG_VERIFY_ERR=$(echo -n "$JWT_BODY" | openssl dgst -sha256 -verify "${PUB_KEY_FILE}" -signature "${SIG_FILE}")
JWT_SIG_VERIFY_CODE=$?
rm "${SIG_FILE}"
if [ ${JWT_SIG_VERIFY_CODE} -ne 0 ]; then
>&2 echo "Error 1: Bad Signature: Code $JWT_SIG_VERIFY_CODE $JWT_SIG_VERIFY_ERR"
exit 1
fi
else
>&2 echo "Error 3: Unsupported signature algorithm $JWT_ALG"
exit 3
fi
fi
echo -n "${JWT_PAYLOAD}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment