
2026/06/17 1:49
JWT の使用をやめよう
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
改善されたサマリー:
通常のクッキーセッションは、Web アプリケーションにおけるユーザー認証の管理において優れており、JSON Web トークン(JWT)と比較してより高いセキュリティと柔軟性を提供します。JWT は厳密に約 5 分以内という極めて短い期間のために設計されていますが、セッションは個別のデータストアを各リクエストに依存させることなく、より長いライフサイクルを安全に管理します。現在の JWT の使用における重大な欠陥は、仕様が偽造トークンの作成を可能にしている点であり、標準的なセッション管理はこのリスクを効果的に排除します。
本文
JWT(JSON Web Tokens)をセッション保持に使用すべきではない理由
結論:通常のクイークセッションへの移行を推奨します
ユーザーのログイン状態(セッション)を保持させる目的で JWT を使用するのは非推奨です。
- JWT はもともとセッション管理のために設計されたものではありません。
- セッション管理には、はるかに**優れた「通常のクイークセッション」**が利用可能です。
詳しく知りたい場合は、以下のプレゼンテーションをご覧いただくことを強く推奨します。
📺 [推奨動画] Session tokens, statelessness, and why you should stop using JWT: https://www.youtube.com/watch?v=pYeekwv3vC4
⚠️ 注意: 本動画では CSRF 保護など他の重要なトピックに深く触れられていないため、それらについては別途学習が必要です。また、動画で言及されている「JWT の妥当なユースケース」については、より安全性が高く優れたツール(例:PASETO)で代替可能です。
🔒 認証情報の保存に関する重要注意点
認証情報(JWT トークンを含む)を
localStorage や sessionStorage に直接保存すべきではありません。
JWT を避けるべき具体的な理由
1. 有効期限の制約との矛盾
- JWT の仕様は、極めて短い有効期限(約 5 分以下)を持つトークンのみで設計されています。
- セッション管理にはそれよりも長いライフタイムが必要であり、この要件を満たすことができません。
2. 「ステートレス」認証の非現実性
- 「ステートレス」という概念は誤解を招く言葉であり、真に安全な状態なし認証を実現するには莫大なリソースが必要です。
- トークンを安全に扱うためには、何らかの状態情報(state)を保持する必要があるため、データストアの利用は避けられません。
- その際も、データを一元保存するアプローチの方が望ましいです。
システムに欠陥が生じているケースは存在しますが、決して同じ過ちを繰り返すべきではありません。 セキュリティ専門家から信頼されていないのは、JWT 仕様自体の構造的な欠陥(なりすまされたトークンの作成が容易であったり、重大な脆弱性を抱えていたりする可能性)が理由です。
よくある反論に対する回答
❓「しかし Google は JWT を使っています!」
- 事実: Google はブラウザ上のユーザーセッションには、JWT ではなく通常のクッキーベースのセッションを採用しています。
- JWT の真の用途: Google は JWT を「シングルサインオン(SSO)」のためのトランスポートとして利用しています。つまり、一つのサーバーで確立したログインセッションを別のサーバーへ安全に移動させる際のみ使用しているためです。
- 本質の違い: Google はセキュリティ専門家や堅牢な実装を維持するリソースを持っているため、一般的な開発者環境とは異なります。他の組織が単純に「Google が使っているから」と真似するのは不適切です。
❓「しかしステートレスの方が良い!」
- 前述の通り、ステートレスで安全であるためには莫大なリソースが必要であり、現実的ではありません。
❓「セッションの仕組みがわかりません!」
- セッション技術は特に新しいものではありませんが、セットアップに関するドキュメントが少ない傾向があります。
- セッション機能はほぼすべてのウェブサーバーフレームワークに標準搭載されており、有効化も簡単です(デフォルトではオフの場合が多いですが)。
具体的な実装例(Node.js / Express)
独自に複雑なセットアップをする必要はありません。以下のミドルウェアを組み合わせるだけで可能です。
// express-session と connect-session-knex の組み合わせ例 const session = require('express-session'); const KnexStore = require('connect-session-knex')(session); const knex = require('knex')({ /* DB 設定 */ }); const store = new KnexStore({ knex: knex, tableName: 'sessions' }); app.use(session({ secret: 'your-secret', resave: false, saveUninitialized: true, store: store, // データストア(PostgreSQL/MySQL/SQLite など)を利用 cookie: { secure: process.env.NODE_ENV === 'production' } // HTTPS の場合のみ有効化推奨 }));
代替方案:短命トークンの必要性について
短期間有効な署名付きトークンをどうしても必要とする場合でも、PASETO というより安全に設計された別の仕様があります。
⚠️ 重要: ただし、PASETO もセッション保持(ログイン状態の長期保存)には使用しないでください。
JWT や PASETO のようなトークンは、あくまで認証情報の一時渡しや SSO などの特定の用途に限定して使用するべきです。
さらに詳しい情報
セッションの仕組みについて深く知りたい場合は、以下のgist をご参照ください。
- 作成者: joepie91(本記事の著者)
- 詳細解説: Session Mechanics Gist (※原文 URL が省略されているため、検索して確認することを推奨します)