Closed11
LINE Messaging API で Authentication failed
このスクラップについて
このスクラップでは LINE Messaging API を利用している時に発生した下記のエラーメッセージの問題解決をしていく。
Authentication failed. Confirm that the access token in the authorization header is valid.
対象のソースコード
line-access-token.ts
import { JWS } from 'node-jose';
import fetch from 'node-fetch';
// LINE Messaging API のチャンネルトークン v2.1 を取得します
// https://developers.line.biz/ja/docs/messaging-api/generate-json-web-token/
export async function getLineAccessToken(
privateKey: string,
keyId: string,
channelId: string,
): Promise<string> {
// チャネルアクセストークンを取得するための JWT を発行します
const header = {
alg: 'RS256',
typ: 'JWT',
kid: keyId,
};
const payload = {
iss: channelId,
sub: channelId,
aud: 'https://api.line.me/',
exp: Math.floor(new Date().getTime() / 1000) + 60 * 30,
token_exp: 60 * 60 * 24 * 30,
};
const jwt =
(await JWS.createSign(
{
format: 'compact',
fields: header,
},
JSON.parse(privateKey),
)
.update(JSON.stringify(payload))
.final()) + '';
// エンドポイントからチャネルアクセストークンを取得します
const accessTokenUrl = 'https://api.line.me/oauth2/v2.1/token';
const accessTokenResponse = await fetch(accessTokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_assertion_type:
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: jwt,
}).toString(),
});
const accessTokenBody: any = await accessTokenResponse.json();
return accessTokenBody.access_token;
}
テストコード
line-access-token.e2e-spec.ts
import { getLineAccessToken } from '../src/lib/line-access-token';
describe('LINE Webhook', () => {
it('/ (GET)', async () => {
const channelAccessToken = await getLineAccessToken(
process.env.LINE_SECRET_KEY,
process.env.LINE_KEY_ID,
process.env.LINE_CHANNEL_ID,
);
console.log({ channelAccessToken });
});
});
コンソール出力
{ channelAccessToken: undefined }
アクセストークンが undefined になっている。
accessTokenBody
console.log() で出力してみたら下記のように表示された。
コンソール出力
{
message: 'The maximum number of access tokens has already been issued'
}
原因
Cloud Run でデプロイしていて accessToken を保持しておくのが面倒だったので API にアクセスする度にアクセストークンを発行するようにしていたのだがどうやらそれがいけなかったようだ。
ドキュメントに発行上限について書いてある
さすが LINE だ。
長期アクセストークンの発行
長期のチャネルアクセストークンは、LINE Developersコンソールの[チャネル設定]タブでMessaging APIチャネルを選択して、[Messaging API設定]タブで発行できます。
チャネルアクセストークンは乱発禁止
エンドポイントを呼び出すたびに、チャネルアクセストークンを再発行しないでください。
チャネルアクセストークン v2.1 の運用
LINE 公式ドキュメント より引用
チャネルアクセストークンを正しく管理している場合は、グループごとに一時的に最大2つのチャネルアクセストークンを発行すると、サービスを途切れることなく提供できます。
Cloud Scheduler などを使って定期的にアクセストークンを更新すれば良さそう。
当然だがアクセストークンを安全に保存する場所が必要になる。
やっぱり DB じゃダメかな?
面倒な場合は
長期のアクセストークンを使えば良いが何か落とし穴がある気がする。
教訓
今後はドキュメントをもう少しちゃんと読む。
このスクラップは2023/05/05にクローズされました