Node.js による LINE WORKS トークBot 開発 | JWT 作成と access_token 発行
概要
kintone 絡みで Line WorksのトークBotを作る事になってるのですが、開発時に必要なJWT作成とaccess_token発行にハマってしまったので、作業ログとしていくつかNode.jsスクリプトを残しておきます。
最初はPowerShellでサクッと作ろうかと思ってやってたのですが、情報が少なく、サンプルも見当たらなかったのでNode.jsに切り替えましたが、それでも時間掛かった。。。
公式ページにサンプルコードが欲しかったです。。。
公式のLine Worksの開発概要はこちら。
公式のトークBot開発概要はこちら。
この記事で扱うのは、サーバーAPI呼び出し時に必要な access_token の発行の仕方です。
公式ページでは、こちらのAPI認証の準備におけるサーバーAPIの記述部分になります。
やりたい事
公式ページの記載を引用すると以下の事がやりたいのです。
このJWTの生成の仕方が正直言って良くわかりませんでした。。。
JWTは以下の形式にするそうなんですが、ドット区切りの3つ目のブロックで電子署名のやり方がよく分からず苦戦しました。
{header BASE64 エンコード}.{JSON Claim set BASE64 エンコード}.{signature BASE64 エンコード}
JWT生成
ネット上のサンプルを色々あさり、結果的には以下のコードでJWTは生成できました。
ほぼパクリなので参考程度にしてください。
const crypto = require('crypto') const fs = require('fs') const path = require('path') const privateKeyPath = '.\\private_xxxxxxxxxxxxx.key' const payloadServerId = 'xxxxxxxxxxxxxxxxxxxxxxxxxx' const base64 = json => { const jsonStr = JSON.stringify(json) const jsonB64 = Buffer.from(jsonStr).toString('base64').replace(/={1,2}$/,"") return jsonB64 } const createSignature = data => { const sign = crypto.createSign('RSA-SHA256') sign.update(data) const privateKey = fs.readFileSync(path.resolve(privateKeyPath), "utf8"); const signedData = sign.sign(privateKey, 'base64').replace(/={1,2}$/,"") return signedData } const header = { alg: 'RS256', typ: 'JWT' } const startTime = new Date() const endTime = new Date(startTime.getTime() + 1000 * 60 * 30) const payload = { iss: payloadServerId, iat: Math.floor(startTime.getTime() / 1000), exp: Math.floor(endTime.getTime() / 1000) } const unsignedToken = `${base64(header)}.${base64(payload)}` const signature = createSignature(unsignedToken) const jwt = `${unsignedToken}.${signature}` console.log(jwt)
base64エンコード時に最後に付加される==を削っているのは、JWTで生成する文字列はURLで使用して安全な文字列にするのが原則であるためです。
ただ、==が付いた状態で次の access_token 発行処理をやっても問題はありませんでした。
何故かは分かりませんが。。。
どっかで削除してくれてるのかも。。。
access_token 発行
肝心の access_token は以下のようにPOST送信で発行します。
JWTが生成できればここは問題ないです。
var request = require('request'); const bodyGrantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer' const bodyAssertion = '(JWT)' var options = { uri: 'https://auth.worksmobile.com/b/(API ID)/server/token', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', }, form: { 'grant_type': bodyGrantType, 'assertion': bodyAssertion } }; request.post(options, function(error, response, body){ console.log(response.body); });
4行目に前段で作成したJWTをセットします。
7行目のAPI IDはDeveloper Consoleで確認してください。
実行すると以下のように レスポンスで access_token が取得できます。
{ "access_token":"(access_token)", "token_type":"Bearer", "expires_in":xxxxx }
参考
以下、参考にさせていただいたページ。
https://qiita.com/0xfffffff7/items/e96bcebfddb4a736ffc1
https://qiita.com/tokotan/items/f615f4a62219d655436f
https://qiita.com/tokotan/items/976d35ca56132e0bb5c1
https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/
以下、JWTを生成してくれるページ。便利。
以上
コメントを投稿するにはログインしてください。