かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

TypeScript jsonwebtoken で JWT を verify しようとしたら Right-hand side of 'instanceof' is not an object というエラーになった件

Next.js で jsonwebtoken を使って作成した JWT から中に含まれるデータを取り出そうとま verify しようとしたらエラーになってしまったので原因と解決策のメモ

環境

  • Next.js 13.2.1
  • React 18.2.0
  • TypeScript 4.9.5
  • jsonwebtoken 9.0.0

状況

// api
import { sign } from "jsonwebtoken";
export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>,
) {
  // 略
  const token = sign(payload, SECRET_KEY, {algorithm: 'HS256', expiresIn: '60'});
  return res.status(200).json({ token });  
}

フロントエンドで token の有効期限確認と token に含まれる値を取り出して使いたかった

import { verify } from "jsonwebtoken";
export const useAuth = () => {
  const token = getToken(token); // 保存場所から token を取得
  try {
    const decode = verify(token, SECRET_KEY, { algorithms: ["HS256"] });
    return { verify: true, data: decode };
  } catch (error) {
    // token が無効 / 有効期限切れ
    return { verify: false, data: null };
  }
};

JWT token の発行は問題がないが useAuth 内の verify(token, SECRET_KEY, { algorithms: ["HS256"] }) の部分で Right-hand side of 'instanceof' is not an object というエラーが発生しました

jsonwebtoken v9 からはブラウザで JWT を sign / verify するとエラーになる

jsonwebtoken is a Node.js module, its use in a browser was never intended. Versions before 9.0.0 could use webpack's polyfill of the Node.js built-in modules. This most likely a) relied on slow js cryptography that isn't maintained anymore and lacks feature parity with Node's crypto and b) increased your js bundle size considerably. FWIW webpack 5 also no longer defaults to using these questionable crypto polyfills anymore.

It is better to rely on JWT modules made to be consumed in browser environments. You can discover such modules on jwt.io under "JavaScript" libraries.
cf. Version 9.0.0 - `sign` function throws error on frontend (in browser) · Issue #863 · auth0/node-jsonwebtoken · GitHub

Update Node verson to V12.0+ works for me, hope it can help you

In addition to this, when using node with version 18, jsonwebtoken v.9 will not work anymore in browsers. At least not in Edge/Chrome
cf. Version 9.0.0 - `sign` function throws error on frontend (in browser) · Issue #863 · auth0/node-jsonwebtoken · GitHub

元々 Node module でありブラウザでの処理は推奨されてなかった。今までは polyfill が変換していたためにブラウザでも動作してしまっていたトノコト。
ブラウザで JWTトークンの sign / verify をしようとすると今回のエラー ( Right-hand side of 'instanceof' is not an object) が発生してしまうようです!

解決方法

  1. jsonwebtoken のバージョンをダウングレードする
  2. JWT をさわる処理は全てサーバーサイドで行うようにする

ダウングレードが楽ですが セキュリティの問題 があったり元々推奨されてない事だったので通信が増えてしまうのですが JWT token を Next.js の API に投げて結果を返すように変更しました

完全に理解した!!
おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]