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
) が発生してしまうようです!
解決方法
- jsonwebtoken のバージョンをダウングレードする
- JWT をさわる処理は全てサーバーサイドで行うようにする
ダウングレードが楽ですが セキュリティの問題 があったり元々推奨されてない事だったので通信が増えてしまうのですが JWT token を Next.js の API に投げて結果を返すように変更しました
完全に理解した!!
おわり ₍ ᐢ. ̫ .ᐢ ₎
[参考]
- GitHub - auth0/node-jsonwebtoken: JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
- javascript - Right-hand side of 'instanceof' is not an object, jsonwebtoken - Stack Overflow
- jwt.verify()でRight-hand side of ‘instanceof’ is not an objectとなる原因 – 上尾市のWEBプログラマーによるブログ
- RS256 と HS256 ってなにが違うの - Qiita
- JWTライブラリの危機的な脆弱性について調べた - Qiita