-
-
Save angelo-v/e0208a18d455e2e6ea3c40ad637aac53 to your computer and use it in GitHub Desktop.
# will not work in all cases, see https://gist.github.com/angelo-v/e0208a18d455e2e6ea3c40ad637aac53#gistcomment-3439904 | |
function jwt-decode() { | |
sed 's/\./\n/g' <<< $(cut -d. -f1,2 <<< $1) | base64 --decode | jq | |
} | |
JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ | |
jwt-decode $JWT |
Valid point @philpennock. Do you have a reliable solution?
Just replace the characters? jq -R 'gsub("-";"+") | gsub("_";"/") | split(".") | .[1] | @base64d | fromjson'
JWTs use base64url encoding, which neither
jq
norbase64
(from GNU coreutils) can handle. So the above examples all work some of the time, not reliably.
@philpennock is correct. Here is my solution in a shell script:
#!/bin/bash
# pad base64URL encoded to base64
paddit() {
input=$1
l=`echo -n $input | wc -c`
while [ `expr $l % 4` -ne 0 ]
do
input="${input}="
l=`echo -n $input | wc -c`
done
echo $input
}
# read and split the token and do some base64URL translation
read jwt
read h p s <<< $(echo $jwt | tr [-_] [+/] | sed 's/\./ /g')
h=`paddit $h`
p=`paddit $p`
# assuming we have jq installed
echo $h | base64 -d | jq
echo $p | base64 -d | jq
Oh, I never spoke up, sorry: I use shell around Perl because Perl had the easiest access to base64url when I last went looking, but I was impressed by the solution from @lukaslihotzki using gsub
inside jq
as being the solution with the fewest additional dependencies.
I was also trying to decode a JWT token. I could decode a JWT with:
for line in `echo $JWT | tr "." "\n"`; do echo $line | base64 --decode | jq && echo;done
@seva-ramin's script is fantastic, but just a small bug: tr [+_] [-/]
should be tr [-_] [+/]
@seva-ramin's script is fantastic, but just a small bug:
tr [+_] [-/]
should betr [-_] [+/]
Ugh! what a silly mistake! @danmactough, Thank you for catching that. I have updated my post.
@seva-ramin for me, on OSX Mojave I get base64: invalid option -- d
Changing to -D
works for last two lines:
# assuming we have jq installed
echo $h | base64 -D | jq
echo $p | base64 -D | jq
@seva-ramin for me, on OSX Mojave I get
base64: invalid option -- d
Changing to-D
works for last two lines:# assuming we have jq installed echo $h | base64 -D | jq echo $p | base64 -D | jq
Darn it. They broke base64 in Mojave? I am on Catalina and both options work. Here is the man page for base64 on Catalina.
I additionally had to remove empty parts but then it worked perfectly fine
jq -R 'split(".") | select(length > 0) | .[0],.[1] | @base64d | fromjson' <<< $1
With just jq:
jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$JWT"
@lukaslihotzki thanks, very useful 👍
With just jq:
jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$JWT"
Thanks @lukaslihotzki, very useful!
Or an universal GO approach using RawStdEncoding (with temporary file):
cat << EOFT > ./temp.go && go run ./temp.go $JWT |jq '.|select(.type=="wrapping")' ; rm ./temp.go
package main
import (
"encoding/base64"
"strings"
"fmt"
"os"
)
var encoded = os.Args[1]
func main() {
split := strings.Split(encoded, ".")
for i := 0; i < len(split); i++ {
tokenBytes, err := base64.RawStdEncoding.DecodeString(split[i])
if err != nil {
return
}
var sToken=string(tokenBytes)
fmt.Printf("%s",sToken)
}
}
EOFT
With just jq:
jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$JWT"
Excellent solution, thanks @lukaslihotzki
What about echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" | cut -d '.' -f 2 | base64 -d
what about basenc
it's part of coreutils ?
basenc -d --base64url -i <your_file> | jq
Sure; coreutils 8.31 and newer, so was not in stable OS releases at the time of the gist. Today, I'd recommend basenc.
Oh, beware though that basenc
complains about missing =
signs, even in --base64url
mode, so you'll also need to suppress stderr.
JWTs use base64url encoding, which neither
jq
norbase64
(from GNU coreutils) can handle. So the above examples all work some of the time, not reliably.