鎌形 稔 11月/ 3/ 2020 | 0
概要
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を生成してくれるページ。便利。
以上
