OpenID ConnectのJWT(IDトークン)とJWKを、ペイロードの値を色々変えながら作りたいと思って、シェル上で作るスクリプトを作成しました。
必要なツール
- openssl
- nodejs
- jq
結論
#/bin/sh
header='
{
"kid": "12345",
"alg": "RS256"
}'
payload='
{
"iss": "https://example.com",
"sub": "user-id-123",
"aud": "client-app-id-123",
"exp": 1735689600,
"iat": 1563980400
}'
function pack() {
# Remove return and space
echo $1 | sed -e "s/[\r\n]\+//g" | sed -e "s/ //g"
}
if [ ! -f private-key.pem ]; then
# Private and Public keys
openssl genrsa 2048 > private-key.pem
openssl rsa -in private-key.pem -pubout -out public-key.pem
fi
# Base64 Encoding
b64_header=$(pack "$header" | openssl enc -e -A -base64)
b64_payload=$(pack "$payload" | openssl enc -e -A -base64)
signature=$(echo -n $b64_header.$b64_payload | openssl dgst -sha256 -sign private-key.pem | openssl enc -e -A -base64)
# Export JWT
echo $b64_header.$b64_payload.$signature > jwt.txt
# Create JWK from public key
if [ ! -d ./node_modules/pem-jwk ]; then
# A tool to convert PEM to JWK
npm install pem-jwk
fi
jwk=$(./node_modules/.bin/pem-jwk public-key.pem)
# Add additional fields
jwk=$(echo '{"use":"sig"}' $jwk $header | jq -cs add)
# Export JWK
echo '{"keys":['$jwk']}'| jq . > jwks.json
echo "--- JWT ---"
cat jwt.txt
echo -e "\n--- JWK ---"
jq . jwks.json
Generate private and public keys, and create JWT and JWKs
解説
秘密鍵と公開鍵の作成
if [ ! -f private-key.pem ]; then
# Private and Public keys
openssl genrsa 2048 > private-key.pem
openssl rsa -in private-key.pem -pubout -out public-key.pem
fi
署名の作成
ヘッダとペイロードをBase64エンコードして、上記で作成した秘密鍵で署名を作成し、Base64エンコード。pack()
は改行文字とスペースの削除用に定義した関数。
function pack() {
# Remove return and space
echo $1 | sed -e "s/[\r\n]\+//g" | sed -e "s/ //g"
}
b64_header=$(pack "$header" | openssl enc -e -A -base64)
b64_payload=$(pack "$payload" | openssl enc -e -A -base64)
signature=$(echo -n $b64_header.$b64_payload | openssl dgst -sha256 -sign private-key.pem | openssl enc -e -A -base64)
JWT(IDトークン)を作成
echo $b64_header.$b64_payload.$signature > jwt.txt
PEM形式の公開鍵をJWKに変換
pem-jwk - npmを使いました。
if [ ! -d ./node_modules/pem-jwk ]; then
# A tool to convert PEM to JWK
npm install pem-jwk
fi
jwk=$(./node_modules/.bin/pem-jwk public-key.pem)
# Add additional fields
jwk=$(echo '{"use":"sig"}' $jwk $header | jq -cs add)
# Export JWK
echo '{"keys":['$jwk']}'| jq . > jwks.json
まとめ
出力サンプル
--- JWT ---
eyJraWQiOiIxMjM0NSIsImFsZyI6IlJTMjU2In0K.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoidXNlci1pZC0xMjMiLCJhdWQiOiJjbGllbnQtYXBwLWlkLTEyMyIsImV4cCI6MTczNTY4OTYwMCwiaWF0IjoxNTYzOTgwNDAwfQo=.J7GjvEODv1NeEJ3uOK99unlrtOtqMdJNydYmSStdLuiq5h+ut6E0edMjTqgJZfOMNr3vM23EJXOmk+kit/j1zGJBHgev0DoTIWrrN+fjeE7seCVZGf0eblC9VZbq9FU0t8WQz4vQeZpy1oRLIUPj6go0gw5ed8Yo+pBZi+/nPJsmy450ChfFpE1cx58VQ4zM9eEnQz4jKInevyR5cTn1iYuLhDhPQmRDdlLg3IuxgRjwxsLBjZjtiyn6mntZHOeTSAlLfmoWKNiMtN1qNoEf2e9s3pqctIwRQQKsPAfO64q//te8jGGxzTFLUV2JP23AxwzrOEcfuZyCLB5u4RKI/Q==
--- JWK ---
{
"keys": [
{
"use": "sig",
"kty": "RSA",
"n": "4iNwSXpIvLz4DbG5HUyy5jUOnsdOD99dCA56oDWU6PSV3lTbPBWyngrdcpoC50MT_yqBMiQvaNRZRgcH82jsRrs_HPGDSMO1hEv7LUlwJy5MWBOcKeGLpAL9P9FXKnjvx2dQpWlXZC3D5KsdHc8dsMnxR8D3-T5XWDGwqnEMLWoG1uRPG7lual2PhrX3wpZMY3gmgx4WnElxv8DZs9GArvMzsojtPpgJ1cmnlzDzZbQWd5lJwW_k7S8jcEiBEwfoITzY1umQKWetMe9id1-ohH1tbe7vXpxpm59j4Fo5HZoTA3VUR6Jkbnjqf6TPhEOwJUnf-DMyewZXW2dxjvTPPw",
"e": "AQAB",
"kid": "12345",
"alg": "RS256"
}
]
}
各種クレームの値を変えて、IDトークンの検証をテストしたいときなどに便利かもしれないです。iss
, exp
, aud
などの値を変えてトークンの検証が失敗するテストケースなど。