# チャネルアクセストークンv2.1を発行する
ここでは、アサーション署名キーからJSON Web Token(JWT)を生成する方法と、生成したJWTを使ってチャネルアクセストークンv2.1を発行する方法について説明します。
# アサーション署名キーを発行する
LINE Developersコンソールのチャネル設定からMessaging APIチャネルを選択して、チャネル基本設定タブにアクセスします。次に、アサーション署名キーの横にある[発行]ボタンをクリックして、アサーション署名キーを発行します。チャネルごとに最大2つのキーペアを作成できます。
アサーション署名キーが発行され、秘密鍵がダウンロードされます。秘密鍵は、必ず安全な場所に保管してください。
LINEは公開鍵のみを保管します。秘密鍵は保管しません。秘密鍵は必ず各自で保管してください。秘密鍵は発行時に一度だけ表示されます。
# JWTを生成する
JWTを生成するには、任意のJWTライブラリ (opens new window)を使用することもできますし、アサーション署名キーを使って独自のコードをスクラッチで書くこともできます。
ここでは、JWT (opens new window)で紹介されているJavaScriptライブラリを使用して作成する例を説明します。ここで説明するコードを使用するには、事前に以下をインストールする必要があります。
JWTは、ヘッダー、ペイロード、署名からなる文字列です。すべての項目が必須フィールドです。
ヘッダー
プロパティ | 説明 |
---|---|
alg | 固定プロパティ:RS256 |
typ | 固定プロパティ:JWT |
kid | 「アサーション署名キーを作成する」でダウンロードした秘密鍵のkid プロパティの値を使用します。 |
以下は、ヘッダーの値をデコードした例です。
{
"alg": "RS256",
"typ": "JWT",
"kid": "536e453c-aa93-4449-8e90-add2608783c6"
}
ペイロード
プロパティ | タイプ | 説明 |
---|---|---|
iss | String | チャネルID。LINE Developersコンソールで確認できます。sub と同じ値にします。 |
sub | String | チャネルID。LINE Developersコンソールで確認できます。iss と同じ値にします。 |
aud | String | https://api.line.me/ |
exp | Number | JWTの有効期間。UNIX時間で設定します。JWTアサーションの最大有効期間は30分です。 |
token_exp | Number | チャネルアクセストークンを要求するときに必要です。チャネルアクセストークンの有効期間を秒単位で設定します。チャネルアクセストークンの最大有効期間は30日です。 |
以下は、デコードされたペイロードの例です。
{
"iss": "1234567890",
"sub": "1234567890",
"aud": "https://api.line.me/",
"exp": 1559702522,
"token_exp": 86400
}
署名
アサーション署名キーの秘密鍵で、上記のようなヘッダーとペイロードを署名することでJWTが生成できます。
node-joseを使って秘密鍵で署名してJWTを生成するコードの例です。このコードを使って自分のJWTを作成する場合は、privateKeyを自分のアサーション署名キーの秘密鍵の値に変更し、header
とpayload
の値をそれぞれ変更してから実行します。node-joseの使い方について詳しくは、node-jose (opens new window)を参照してください。内容が改ざんされていないことを証明するために、必ず秘密鍵で署名を行います。
node-joseを使ったコードの例
let jose = require('node-jose');
let privateKey = `
{
"p": "4h8yEw4q9VkzhXMgXZsIZVkEuZ49EmtWYk9zs0hPTa24ejjRMA6KTYh_va0GlaChO9t0MVQVuduznt-OFZyRAinr4svU4MKD2A3gTHJJCxs0xICva8rkHXqxfPwXngpb5L_xFURbXcSTzMcKckWuOpyPznAgY4XsZxw0t7ewj9E",
"kty": "RSA",
"q": "pVhBdRN5K3MEiZzU4__TsrtSBJDD_stu60m73iIvsHIrvK3Dmfl-J1zhsyOvi3NH9mVXpUimBwP8nTe-BlVM71G7_EotFHeKH1zTmBlx6AOngmrc40W2Hd__OZW0NfC_xOTvI_Ea2BNGoGtcrIGVFLTivJ4y9wAVOKA058zJ0ls",
"d": "ObzE_-TROJazDm-ry-8TKRBMGzwcwTK6lMFSk7n-Xp6h7cDauSdRRYnZivC1lh5plVG3I9aUmPTRbVk7nrPqOlp4WWKQ27lyLd5IogbArpXgnBSkp9Zy0lWzvOsI3gHNnYuehyksHB53FIK93t838JfDQoXUUzalNoNwAGfkTNZxT4GIXGMGzNck2Z_urOATMf8-wdad-u4a5IB2KfHugwH2kw-Zig7fbdcN4_DeKWpuigdesa48Yj_hRJRws-mVFp-xHlGJehumnM_v8FLD85ap8L1hwvBqdJQeurcLXYzZbtdp9a5GpJI7gzOTMoEdxIKlEIIbaOKv4rkkztdhoQ",
"e": "AQAB",
"use": "sig",
"kid": "536e453c-aa93-4449-8e90-add2608783c6",
"qi": "XQ2puK9LT5yimyJXlXb4nHEBzPGe3sYbaZW_gMK4iHuM8cseImwLNP8ZIeGaNx5X_hZ6ZOzkjtYJjY85fvaWa2UDGdGlEw3ZO-Nk0Qu_exBrqZgZAsua75TjpJRw01Yd1TNBx5MYuvhltJLsjW-uSjcE-rZoO74FEe9pYYeQjI4",
"dp": "Qq_wlK4Y_ULRbwoFAZY3Y6xdOGDyofwF_fhwpu8sdDxHq8QV7ZZcM4GOKuJcjsRQyNZv7hxeS_H_h1tnC_igy4KRjtGOdrrnJ1DwVZte72eWqF1LXv73R7pnnfS7AmELuOriruL6Dy1qaXpKGmlyeNazkq5-3tsgXUh0Q7po2AE",
"alg": "RS256",
"dq": "Wj1ovDT8lLIZb-Ggby9YotuJT-SSk6UDzHZZikquLGajaD6N2qNILsOKivKXBEzOobN9uj-EHaAXZtbdZyd27cZ2CqORJvJ299b5xLFecXpNGeio1YFee7-c1BjYWfgjMZqgycT1GairizINSjkO3FY8ySSuPBBXhKgrN7eVDrE",
"n": "kgwP0NPaoAwhSh9iLlRaT7FSRbNsl6T5-j-bB3xAT1UbsxOJ9v06S3_54bpYlEAkjlrO-i1vmSzfSVnqFXnjWThWRvPmBDth3Ka7hQm9UXjiAvTzYxXGFjyhALqa_-DQCtdrqIhi8E4hAuSu--kGgnFKg3G-21KJuqnVzsXrClGkxbmVufx0MJjJxr1YGfkTMG8i0dovS9tnkioDAkt1knupiYk5ir_WiNy4T-70T5s3ktC5_4Uz10hS-rWeUxiihzG8G7ceg84-Kt5jKP_AgUnel-ksRyfgSJCYC9nHyz913a3ALj3Dzt7TBaxwAjlxESrdNz5RE9DNDZfPmNWRSw"
}
`;
let header = {
alg: "RS256",
typ: "JWT",
kid: "536e453c-aa93-4449-8e90-add2608783c6"
};
let payload = {
iss: "1234567890",
sub: "1234567890",
aud: "https://api.line.me/",
exp: Math.floor(new Date().getTime() / 1000) + 60 * 30,
token_exp: 60 * 60 * 24 * 30
};
jose.JWS.createSign({format: 'compact', fields: header}, JSON.parse(privateKey))
.update(JSON.stringify(payload))
.final()
.then(result => {
console.log(result);
});
Base64形式でエンコードされたヘッダーとクレーム・セット、および秘密鍵(rsa_private.pemファイルなど)を、ヘッダーで定義したアルゴリズムを使用して署名します。署名後、Base64形式でエンコードされた結果がJWTになります。
エンコードされたJWTの例
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjJjNjU4NWYzLThkZGQtNDZjNC05YmUyLWI1NGE3MGFhOTRlYSJ9.eyJpc3MiOiIxNjUzOTQ3MTcyIiwic3ViIjoiMTY1Mzk0NzE3MiIsImF1ZCI6Imh0dHBzOi8vYXBpLmxpbmUubWUvIiwiZXhwIjoiMTU4NTIwMDA2MiIsInRva2VuX2V4cCI6IjI1OTIwMDAifQ.UVG6PAEub-OPbZ3nJuVxRRPjY6Sz_eIHJV9DTTAHCR79YsG4yWvoa9AeIctibb6IJQKgTEV7mF7LsUDmXldEDqYwyEmKs38zj_995Ntc9SYBFphHpr09NqfMoqMphwKqms2NOnqgcHreFs27d9Q0Qv8Rtv2t7SB2cVO__KrsjzYNs3miTvDdkqYLXFo5fXwuzNtHOCAJomd6bhMR8Yd1-vJmtMCBPK4hmA98w8fG_NhcyLbw-B9AuxQ6z92zXiRhNyPlK_3ce2T7HtgUluJ4xJl4xdLJ_C6hvTAqtQxmSiJKzbjUiANF6hVBTomU8vkaIjEKjnlT1uPMihfrsA3pzQ
# チャネルアクセストークンv2.1を発行する
「JWTを生成する」の手順で生成したJWTアサーションを指定して、チャネルアクセストークンv2.1を発行できます。
- チャネルアクセストークンv2.1発行時のレスポンスには、チャネルアクセストークンとペアになる一意のキーID(
key_id
)が含まれます。チャネルアクセストークンを正しく管理するために、必ずチャネルアクセストークンとキーIDをペアで保管するようにしてください。 - キーIDは、2020年6月22日のMessaging APIのアップデートで追加された識別子です。キーIDを持たないチャネルアクセストークンv2.1をお使いの場合、チャネルアクセストークンv2.1を再発行し、トークンとキーIDのペアを保管することをお勧めします。チャネルアクセストークンを再発行した場合は、必ず新しいトークンを使うようにボットを改修してください。
- 生成したJWTを指定して、チャネルアクセストークンv2.1を発行するエンドポイントを実行し、チャネルアクセストークンを発行します。
- チャネルアクセストークンとキーIDがLINEプラットフォームから返ります。
- チャネルアクセストークンとキーIDをペアにしてデータベースなどに保管します。
# チャネルアクセストークンv2.1を取り消す
チャネルアクセストークンv2.1を取り消すエンドポイントを実行することでチャネルアクセストークンを取り消すことができます。
無効なチャネルアクセストークンを指定して、チャネルアクセストークンv2.1を取り消すエンドポイントを実行した場合も、エラーレスポンスは発生しません。すべての有効なチャネルアクセストークンv2.1のキーIDを取得するエンドポイントを使って、現在有効なチャネルアクセストークンとペアになるキーIDを取得できます。取得したキーIDを、データベースなどに保管したチャネルアクセストークンとキーIDのペアと照合することで、有効なチャネルアクセストークンを識別できます。
- 保存したアサーション署名キーからJWTを再生成します。
- JWTを使ってすべての有効なチャネルアクセストークンv2.1のキーIDを取得するエンドポイントを実行します。
- 有効なチャネルアクセストークンのキーIDがLINEプラットフォームから返ります。
- チャネルアクセストークンとキーIDのペアを保管したデータベースなどを参照します。
- 取得したキーIDと一致する、チャネルアクセストークンとキーIDのペアを検索します。
- 有効なチャネルアクセストークンを取得します。
- 有効なチャネルアクセストークンを指定して、チャネルアクセストークンv2.1を取り消すエンドポイントを実行します。
- LINEプラットフォームからチャネルアクセストークンが取り消されます。