JSON Web Tokens

Example token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Note tokens can be much different sizes depending on what algorithm is used.

Three Parts

echo $JWT | cut -d "." -f1
#+RESULTS:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
echo $JWT | cut -d "." -f2
#+RESULTS:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
echo $JWT | cut -d "." -f3
#+RESULTS:
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

All three parts are base64url-encoded (rfc). Neither base64 nor jq fully support base64url encoding, though it works sometimes. The first two parts are JSON, the third is…? The third part is a signature.

In the example token, the first part decodes properly, second part does not.

Works:

echo $JWT | cut -d "." -f1 | base64 --decode
#+RESULTS:
{"alg":"HS256","typ":"JWT"}

Does not completey work, missing last } character:

echo $JWT | cut -d "." -f2 | base64 --decode
#+RESULTS:
{"sub":"1234567890","name":"John Doe","iat":1516239022

More reliable decoding, using only jq:

echo $JWT | jq -R 'gsub("-";"+") | gsub("_";"/") | split(".") | .[1] | @base64d | fromjson'
#+RESULTS:
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}