#!/bin/bash # Reads a JWT on stdin and outputs the number of seconds until it expires # If a JWT has expired, the output will be the seconds since expiration as a negative number # # Examples: # # # Token expired 5 minutes ago # echo "eyJhbGc..." | ./jwt_expires.sh # -300 # # # Token expires in 1 hour from now # echo "eyJhbGciOiJFZ..." | ./jwt_expires.sh # 3600 # Read JWT token from stdin read -r jwt_token # Check if token was provided if [ -z "$jwt_token" ]; then echo "Error: No JWT token provided via stdin" >&2 echo "Usage: echo 'your_jwt_token' | $0" >&2 exit 1 fi # Function to decode base64url base64url_decode() { local input=$1 local padding=$((4 - ${#input} % 4)) if [ $padding -ne 4 ]; then input="${input}$(printf '=%.0s' $(seq 1 $padding))" fi echo "$input" | tr '_-' '/+' | base64 -d 2>/dev/null } # Split the JWT token into parts IFS='.' read -r header payload signature <<< "$jwt_token" # Check if we have all three parts if [ -z "$header" ] || [ -z "$payload" ] || [ -z "$signature" ]; then echo "Error: Invalid JWT format. Token must have three parts separated by dots." >&2 exit 1 fi # Decode the payload decoded_payload=$(base64url_decode "$payload") # Check if decoding was successful if [ -z "$decoded_payload" ]; then echo "Error: Failed to decode JWT payload" >&2 exit 1 fi # Extract the exp claim using grep and sed exp=$(echo "$decoded_payload" | grep -o '"exp":[0-9]*' | sed 's/"exp"://') # Check if exp claim exists if [ -z "$exp" ]; then echo "Error: No 'exp' claim found in JWT token" >&2 exit 1 fi # Get current timestamp current_time=$(date +%s) # Calculate time difference time_diff=$((exp - current_time)) echo $time_diff