エラーメッセージ
invalid algorithm
このエラーの意味
トークンの alg ヘッダーの値が、検証者が受け入れるアルゴリズムのリストに含まれていません。jsonwebtoken は署名を確認する前にこのチェックを行うため、トークン自体は正しく署名されている可能性があります。単に、許可していない方式で署名されているだけです。このチェックは設計どおりに動作しているセキュリティ機能であり、解析のバグではありません。
発生する理由
移行後に発行者と検証者の設定が食い違っている
よくある発行者が RS256 から ES256 に(またはその逆に)切り替えたのに、検証者はアルゴリズムの許可リストで古い値に固定したままです。その結果、新しいトークンはすべて失敗し、キャッシュされた古いトークンは引き続き通るため、切り替え時の障害が断続的なものに見えます。
誤った鍵の種類から許可リストが推測された
よくあるv9 以降、algorithms オプションを渡さないと、jsonwebtoken は鍵から許可リストを推測します。RSA 公開鍵を渡すと、ES256 のトークンは、許可するつもりだったとしても「invalid algorithm」になります。RS256 だけを許可した状態で EC 鍵を渡しても、同じように失敗します。(algorithms: ["ES256"] を指定して RSA 鍵を渡すと、このチェックは通過しますが、次のチェックで「"alg" parameter for "rsa" key type must be one of: RS256, PS256, …」というエラーになります。)
別の発行者のトークン
ときどきマルチテナントのシステムでは、別の ID プロバイダーが異なる署名方式で発行したトークンを受け取ることがあります。その場合、alg の不一致は症状にすぎません。本当の問題は、そもそもこのトークンがこの検証者に届くべきではないということです。
修正方法
- 1.
許可リストを発行者が実際に使うアルゴリズムに固定する
ヘッダーをデコードして実際の alg を確認し、許可リストをその値だけにしてください。あわせて、鍵の種類が一致していることも確認してください(ES256 には EC 鍵、RS256 には RSA 鍵)。
js const { header } = jwt.decode(token, { complete: true }); console.log(header.alg); // e.g. "ES256" jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] }); - 2.
アルゴリズムの変更は 2 段階で展開する
鍵やアルゴリズムのローテーション中は、検証者は短期間だけ両方の方式を受け入れなければなりません。その際、それぞれの方式を kid で専用の鍵に結び付けます。ローテーションが済んだら、受け入れる方式を 1 つに戻します。
js // transition window only: jwt.verify(token, keyForKid(header.kid), { algorithms: ["ES256", "RS256"] }); // after all RS256 tokens expired: jwt.verify(token, ecPublicKeyPem, { algorithms: ["ES256"] });