Skip to content

Instantly share code, notes, and snippets.

@floudet
Created September 28, 2017 03:19
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 floudet/5f5870d0551fcdb663969df6fcf7bfce to your computer and use it in GitHub Desktop.
Save floudet/5f5870d0551fcdb663969df6fcf7bfce to your computer and use it in GitHub Desktop.
Request OAuth2.0 Access tokens for Box.com using JWT
#!/bin/bash
#
# Request OAuth2.0 Access tokens for Box.com using JWT
#
# Thanks:
# https://developer.box.com/v2.0/docs/construct-jwt-claim-manually
# https://developer.box.com/v2.0/blog/box-tokener-a-nodejs-command-line-tool-to-generate-box-api-tokens
# http://willhaley.com/blog/generate-jwt-with-bash/
PRIVATE_KEY=""
PASSPHRASE=""
CLIENT_ID=""
CLIENT_SECRET=""
KEY_ID=""
USER_ID=""
EXP=30
# Display Usage
_usage() {
echo "Usage: $0 -k private_key -p passphrase -c client_id -s client_secret -i key_id -u user_id [ -e expiration ]"
echo "Mandatory: "
echo " -k file path to private key"
echo " -p passphrase associated with the private key"
echo " -c Client ID (API key for Box Platform)"
echo " -s Client Secret"
echo " -i the public key id found in developer console"
echo " -u User ID"
echo "Optional: "
echo " -e JWT expiration in seconds (max 60, default 30)"
exit -1
}
# Get options from command line
if [[ -z $1 ]]; then _usage; exit -1; fi
if [[ $1 == "--help" ]]; then _usage; exit -1; fi
while getopts "k:p:c:s:i:u:e:" ARG
do
case "$ARG" in
k)
PRIVATE_KEY=$OPTARG
;;
p)
PASSPHRASE=$OPTARG
;;
c)
CLIENT_ID=$OPTARG
;;
s)
CLIENT_SECRET=$OPTARG
;;
i)
KEY_ID=$OPTARG
;;
u)
USER_ID=$OPTARG
;;
e)
EXP=$OPTARG
;;
*) _usage
;;
esac
done
# Check options
if [[ -z $PRIVATE_KEY || $PRIVATE_KEY == "" ]];then
echo "-k option is mandatory"
_usage
fi
if [[ -z $PASSPHRASE || $PASSPHRASE == "" ]];then
echo "-p option is mandatory"
_usage
fi
if [[ -z $CLIENT_ID || $CLIENT_ID == "" ]];then
echo "-c option is mandatory"
_usage
fi
if [[ -s $CLIENT_SECRET || $CLIENT_SECRET == "" ]];then
echo "-s option is mandatory"
_usage
fi
if [[ -s $KEY_ID || $KEY_ID == "" ]];then
echo "-i option is mandatory"
_usage
fi
if [[ -s $USER_ID || $USER_ID == "" ]];then
echo "-u option is mandatory"
_usage
fi
if [[ $EXP -lt 1 || $EXP -gt 60 ]];then
echo "JWT expiration should be between 1 and 60"
exit -1
fi
TOKEN_EXP=$(($(date +%s) + $EXP)) # max 60s
JTI=$(cat /dev/urandom | LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)
# RS256 = RSA Signature with SHA-256
read -r -d '' JA_HEADER << EOM
{
"alg": "RS256",
"typ": "JWT",
"kid": "$KEY_ID"
}
EOM
# CLAIM = PAYLOAD
read -r -d '' JA_CLAIM << EOM
{
"iss": "$CLIENT_ID",
"sub": "$USER_ID",
"box_sub_type": "user",
"aud": "https://api.box.com/oauth2/token",
"jti": "$JTI",
"exp": $TOKEN_EXP
}
EOM
function base64_encode() {
declare INPUT=${1:-$(</dev/stdin)}
echo -n "${INPUT}" | openssl enc -base64 -A
}
function json() {
declare INPUT=${1:-$(</dev/stdin)}
echo -n "${INPUT}" | jq -c .
}
function rs256_sign() {
declare INPUT=${1:-$(</dev/stdin)}
echo -n "${INPUT}" | openssl dgst -sha256 -sign $PRIVATE_KEY -passin pass:$PASSPHRASE
}
JA_HEADER_BASE64=$(echo "${JA_HEADER}" | json | base64_encode)
JA_CLAIM_BASE64=$(echo "${JA_CLAIM}" | json | base64_encode)
JA_HEADER_CLAIM=$(echo "${JA_HEADER_BASE64}.${JA_CLAIM_BASE64}")
JA_SIGNATURE=$(echo "${JA_HEADER_CLAIM}" | rs256_sign | base64_encode)
JWT_ASSERTION=$(echo "${JA_HEADER_CLAIM}.${JA_SIGNATURE}")
curl https://api.box.com/oauth2/token \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&assertion=$JWT_ASSERTION" \
-X POST
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment