Skip to content

Instantly share code, notes, and snippets.

@danydodson
Last active November 15, 2022 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danydodson/de6d30d95773be5ea8d15ea72533cee0 to your computer and use it in GitHub Desktop.
Save danydodson/de6d30d95773be5ea8d15ea72533cee0 to your computer and use it in GitHub Desktop.
nginx jwt tools

JWT tools

create_jwt.sh Reads a JSON payload and creates a JWT, with or without a signature

decode_jwt.sh Reads a JWT from stdin and decodes as human-readable JSON to stdout

#!/bin/bash
# create_jwt.sh (c) NGINX, Inc. [v0.3 10-Jul-2019] Liam Crilly <liam.crilly@nginx.com>
#
# This script accepts a JSON claimset (JWT payload) and creates produces a
# JOSE-signed token to stdout using one of the supported signature algorithms.
#
# CHANGELOG
# v0.1 Initial version (hs256 only)
# v0.2 Added support for various hs signature lengths
# v0.3 Checks for expired exp claims, option to specify exp duration
if [ $# -eq 0 ]; then
echo "USAGE: ${0##*/} [-exp <mins>] <alg [secret]> <payload>"
echo " -exp will set or override the exp claim with the specified duration"
echo " alg may be 'none' or 'hs*'"
echo " secret will be used for HMAC (hs*) signature"
echo " payload of '-' will read from stdin"
exit 1
fi
# Check that jq is installed so we can check/modify the exp claim
#
hash jq 2> /dev/null
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: please install 'jq' for 'exp' payload manipulation"
exit
fi
# Command line processing
#
VALIDITY_MINS=0
if [ "$1" == "-exp" ]; then
VALIDITY_MINS=$2
shift; shift
fi
case $1 in
"none")
HEADER='{"alg":"none","typ":"JWT"}'
PAYLOAD=$2
shift
;;
"hs256"|"hs384"|"hs512")
LENGTH=`echo $1 | awk -F"hs" '{print $2}'`
HEADER="{\"alg\":\"HS$LENGTH\",\"typ\":\"JWT\",\"kid\":\"0001\"}"
SECRET=$2
shift; shift
;;
*)
echo "${0##*/}: ERROR: unrecognised or unsupported algorithm, $1"
exit 1
;;
esac
if [ "$1" == "-" ]; then
PAYLOAD=$(cat)
else
PAYLOAD=$1
fi
# Check payload is valid JSON
#
if [ `echo $PAYLOAD | jq -r . 2>&1 | grep -c ^parse` -gt 0 ]; then
echo "${0##*/}: ERROR: JWT payload is invalid (not JSON)"
echo $PAYLOAD | jq .
exit 1
fi
if [ $VALIDITY_MINS -gt 0 ]; then
# Set/update the exp claim
EXP_CLAIM=`date -v +${VALIDITY_MINS}M +%s`
PAYLOAD=`echo $PAYLOAD | jq ".exp = $EXP_CLAIM"`
else
# Check/warn if exp is in the past
EXP_CLAIM=`echo $PAYLOAD | jq -r .exp`
if [ "$EXP_CLAIM" != "null" ] && [ $EXP_CLAIM -lt `date +%s` ]; then
echo "${0##*/}: WARNING: exp claim is in the past, `date -j -f %s $EXP_CLAIM`" 1>&2
fi
fi
JWT=`echo -n $HEADER | base64 | tr '+\/' '-_' | tr -d '='`.`echo -n $PAYLOAD | base64 | tr '+\/' '-_' | tr -d '='`
if [ "$LENGTH" != "" ]; then
SIG=`echo -n $JWT | openssl dgst -binary -sha$LENGTH -hmac $SECRET | base64 | tr '+\/' '-_' | tr -d '='`
fi
echo $JWT.$SIG
#!/usr/bin/env bash
#
# decode_jwt.sh (c) NGINX, Inc. [v0.5 19-Nov-2018] Liam Crilly <liam.crilly@nginx.com>
#
# This script accepts a JWT on stdin and decodes the header and payload into
# human-readable JSON texts. It does not perform signature validation.
#
# CHANGELOG
# v0.4 [28-Jul-2016] Stable
# v0.5 [19-Nov-2018] Support for multiple JSON-prettifiers, reports on decode failure
if [ $# -gt 0 ]; then
echo "${0##*/}: reads a JWT from stdin and decodes as human-readable JSON to stdout"
exit 1
fi
for json_cli in "jq -C ." "python -m json.tool"; do
hash ${json_cli%% *} 2> /dev/null # Remove chars beyond space
if [ $? -eq 0 ]; then
DO_JSON=$json_cli
break #for
fi
done
if [ "$DO_JSON" == "" ]; then
echo "${0##*/}: WARNING: please install 'jq' or 'python' for prettified JSON output"
DO_JSON=cat
fi
jwt=$(cat)
for section in `echo -n $jwt | cut -f1-2 -d . | tr '.' ' '`; do
padding="="
while [ `echo -n "$padding" | wc -c` -lt 4 ]; do
decoded=`echo -n "${section}$padding" | base64 -D`
if [ $? -eq 0 ]; then
# Decoded OK, see if we can prettify the JSON (might need a trailing '}')
echo $decoded | $DO_JSON 2>&1 | grep -ve ^Ex -e ^parse
if [ $? -eq 1 ]; then
echo $decoded} | $DO_JSON 2>&1 | grep -ve ^Ex -e ^parse
fi
# Failed to parse JSON, show what's wrong
if [ $? -eq 1 ]; then
echo "${0##*/}: ERROR parsing JSON"
echo $decoded
echo $decoded} | $DO_JSON
fi
break #while
fi
padding="${padding}="
done
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment