LoginSignup
21
10

More than 3 years have passed since last update.

OpenID ConnectのJWTとJWKを手軽につくりたい

Last updated at Posted at 2019-07-25

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などの値を変えてトークンの検証が失敗するテストケースなど。

参考

21
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
10