概要
RubyでLINEのMessaging APIで使用するチャネルアクセストークンv2.1(JWT)を発行します。
公式リファレンスは以下。
https://developers.line.biz/ja/docs/messaging-api/generate-json-web-token/
前提
- アサーション署名キーを発行済みであること(未発行の場合は、上記公式リファレンスを参考に発行すること)
- JWTそのものの概要説明は省きます
背景
アサーション署名キーからJWTの発行に手間取ったので、残しておきます。
・公式リファレンスの実装例がJavaScriptしかない
・ググっても有用な情報が出てこなかった
(Ruby初学者のため、間違いがありましたらコメントいただけると助かります。)
実装
gemのインストール
# Gemfile
gem 'json-jwt'
bundle install
JWT発行
require 'time'
require 'json/jwt'
# アサーション署名キーのJSONをパース
jwk = JSON.parse(Constants::LINE_ASSERTION_SIGN_KEY)
# ペイロードとヘッダーを定義(LINE公式リファレンスより)
payload = { iss: Constants::LINE_CHANNEL_ID,
sub: Constants::LINE_CHANNEL_ID,
aud: "https://api.line.me/",
exp: Time.now.to_i + 60 * 30,
token_exp: 60 * 60 * 24 * 30 }
header = { alg: "RS256",typ: "JWT",kid: jwk["kid"] }
# 未署名のJWTを作成
jwt_nonsig = JSON::JWT.new(payload)
jwt_nonsig.header = header
# アサーション署名キーから秘密鍵を生成
private_key = JSON::JWK.new(jwk).to_key
# 署名付きのJWTを生成
jwt = jwt_nonsig.sign(private_key).to_s
######## あとは公式リファレンスに沿って、APIにPOST
POST例
curl -v -X POST https://api.line.me/oauth2/v2.1/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode '{発行したjwt}'
はまったところ
-
そもそもアサーション署名キーの形式が謎
pem形式のような文字列がザーっと書いてある秘密鍵は見たことがあったが、アサーション署名キーのようなjson形式は初見で、JWTのgemでそのままの形式では使用できなかった。
⇒JWK Set 形式と呼ぶらしい。
https://qiita.com/trysmr/items/e8d4225ff6a603e9e21a -
gem jwk
を使用するとエラーになる
gem jwk
もJWTのライブラリとして有名どころらしく、最初はこちらを使用したが、以下のエラーが発生した。
https://github.com/jwt/ruby-jwt
# railsコンソール
$ JWT::JWK.import(jwk)
JWT::JWKError: Key type (kty) not provided
"kty"には"RSA"が入っている。ソースを見たらktyに何かしら値が入っていればいいみたい(推測)で、読み込めていないのかな(推測)と思い、jwkのハッシュをシンボル化して、再度実行。
# railsコンソール
$ JWT::JWK.import(jwk.symbolize)
NoMethodError: undefined method `tr' for nil:NilClass
Did you mean? try
from /usr/local/lib/ruby/2.6.0/base64.rb:101:in `urlsafe_decode64'
学習不足です。あきらめました・・・
(JWT::JWKでbase64インスタントに対してtrメソッドが呼ばれているところまでは見れましたが、これ以上は時間がかかりそうなのでギブアップ)