← Anatomy of a JWT
Decode the payload properly
Learn
Why base64 -d breaks on the payload
Try base64 -d on segment 2 and it fails with invalid input, for two reasons:
- the segment contains
_(or-), which plain base64 doesn't allow; - its length isn't a multiple of 4, because the
=padding was stripped.
Undo both and it decodes. Writing this once as a function makes it reusable for all three segments:
b64url_decode() {
local s
s=$(tr '_-' '/+') # base64url -> base64 alphabet
while (( ${#s} % 4 )); do s+="="; done # restore padding
printf '%s' "$s" | base64 -d
}
A function in a pipeline reads from stdin, so tr with no file argument consumes
whatever is piped in: echo "$token" | cut -d. -f2 | b64url_decode.
Your task
Plain base64 -d fails on this payload. Write a b64url_decode function that reads stdin, maps base64url back to base64 (_→/, -→+), adds = padding until the length is a multiple of 4, and decodes. Use it to decode the payload (segment 2) into a payload variable, and pretty-print it with jq.