JWTとは何か?毎日使っているこの技術をわかりやすく解説
English · 繁中 · Español · 日本語 · Português (BR)
著者: Danko Peng(@dankopeng)
更新: 2026年3月
読了時間: 約8分
まずリアルなシーンから始めよう
アプリを開いて、アカウントとパスワードを入力してログインする。
その後、あるページに移動し、また別のページに移動する。システムは毎回あなたが誰かを知っていて、再ログインを求めない。
これは当たり前のことに思えるが、裏には一つの問題がある:
HTTPは「記憶なし」のプロトコルだ。
リクエストのたびにサーバーにとっては完全に新しいやりとりだ——「前のリクエストが誰から来たか」を自動では覚えていない。ログインした後、次のページを開いたとき、サーバーはどうやってまだ同じあなただとわかるのか?
これがJWTが解決する問題だ。
JWTとは何か?
JWT(JSON Web Token) はサーバーが「あなたが誰か」を「覚える」ための方法だ。
デジタル通行証と考えるとわかりやすい:
- ログインすると、サーバーがアカウントとパスワードを確認する
- サーバーがあなたに通行証(JWTトークン)を渡す
- 以降のすべてのリクエストにこの通行証を添付する
- サーバーは通行証を見て、あなたが誰で、どんな権限があるかを確認する
このプロセスでサーバーが何も記憶する必要はない——すべての情報は通行証の中にある。
JWTはどんな形をしているのか?
JWTは非常に長い文字列で、こんな形をしている:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywiZW1haWwiOiJ1c2VyQGV4YW1wbGUuY29tIiwicm9sZSI6InVzZXIiLCJleHAiOjE3MDk0NTEyMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c複雑に見えるが、実は3つの部分に分かれていて、.で区切られている:
[Header].[Payload].[Signature]Header(ヘッダー)
このトークンがどのアルゴリズムで暗号化されているかを示す:
{
"alg": "HS256",
"typ": "JWT"
}Payload(ペイロード)
実際のデータが入る——誰か、どんな権限があるか、このトークンの有効期限:
{
"userId": 123,
"email": "user@example.com",
"role": "user",
"exp": 1709451200
}この部分は暗号化されていない、Base64エンコードされているだけだ。誰でもトークンを取得すればデコードしてこの内容を見れる——だからパスワードや機密データをここに入れてはいけない。
Signature(署名)
これが核心だ。サーバーは自分だけが知っているシークレットキーを使って最初の2つの部分に署名する:
HMACSHA256(
base64(header) + "." + base64(payload),
secret_key
)署名の役割:偽造防止だ。
誰かがトークンを入手して、ペイロードのrole: "user"をrole: "admin"に変えようとしても、署名が合わなくなる。サーバーが検証すれば、このトークンが改ざんされたとすぐにわかり、拒否する。
JWTと従来のセッションの違いは?
もう一つの一般的な認証方法は Session だ:
| Session | JWT | |
|---|---|---|
| サーバーの状態保存 | ✅ 必要(セッションデータを保存) | ❌ 不要(情報はトークンの中) |
| 分散システムへの適合 | ❌ 複雑(複数サーバーでセッション共有が必要) | ✅ 自然に適合(どのサーバーでも検証可能) |
| トークンの取り消し | ✅ 簡単(セッションを削除するだけ) | ⚠️ 複雑(追加の仕組みが必要) |
| エッジコンピューティング対応 | ❌ 困難 | ✅ 完全対応 |
JWTはエッジコンピューティング(Cloudflare Workers)に特に向いている。Workersはステートレスだから——各リクエストは異なるエッジノードで処理される可能性があり、セッションメモリを共有できない。JWTはすべての情報をトークンに入れているため、どのノードでもリクエストを受け取れば自分で検証でき、データベースを参照する必要がない。
だからvibefast.appがセッションではなくJWTを選んでいるのはこれが理由だ。
JWTのセキュリティポイント
シークレットキーは強力に、そして秘密に
JWTのセキュリティは完全にシークレットキーにかかっている。誰かがシークレットキーを入手すれば、誰のトークンでも偽造でき、adminを含む任意のユーザーになりすまされる。
シークレットキーは環境変数から読み込む必要があり、コードに直接書いてはいけない。ランダムで強力なシークレットを生成するコマンド:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"生成した値をCloudflare Workersの環境変数に保存し、コードファイルには絶対に現れないようにする。
トークンには有効期限を設定する
通行証は永遠に有効であるべきではない。JWTのexpフィールドで有効期限を設定し、期限切れのトークンはサーバーが拒否する。
一般的なアプローチはaccess tokenの有効期間を15分から7日間とし、セキュリティ要件に応じて調整する。期限切れになるとユーザーは再ログインが必要になる。
トークンは安全な場所に保管する
トークンをどこに保管するかは重要だ:
| 保管場所 | リスク |
|---|---|
| localStorage | ⚠️ XSS攻撃で盗まれやすい |
| sessionStorage | ⚠️ 同上 |
| HttpOnly Cookie | ✅ 比較的安全、JSから読めない |
| メモリ(Reactのstate) | ✅ 安全だがページ更新で消える |
vibefast.appはHttpOnly Cookieでトークンを保管する。これが現在最も一般的な安全な方法だ。
Payloadには機密データを入れない
JWTのpayloadはBase64エンコードであり、暗号化ではない。トークンを入手した人は1秒で中身をデコードして見ることができる。
だからpayloadには本人確認情報(userId、role、email)だけを入れて、パスワード、クレジットカード番号、公開できないデータは絶対に入れてはいけない。
JWTの完全なフロー
わかりやすい言葉でフロー全体を追ってみよう:
1. ユーザーがアカウントとパスワードを入力 → バックエンドに送信
2. バックエンドがデータベースを確認し、パスワードが正しいことを確認
3. バックエンドがシークレットキーでJWTトークンを生成:
payload = { userId: 123, role: "user", exp: 明日 }
token = sign(payload, secret_key)
4. トークンをHttpOnly Cookieに入れて、ブラウザに返す
5. 以降のすべてのリクエストで、ブラウザが自動的にCookieを送信
6. バックエンドがリクエストを受け取る:
- トークンを取り出す
- シークレットキーで署名を検証する
- 有効期限を確認する
- payloadからuserIdを取り出して誰かを確認する
7. リクエストを処理して結果を返すこのフローはvibefast.appにすべて実装済みで、自分で書く必要はない。
よくある質問
Q:JWTトークンが盗まれたらどうする?
JWTについて最もよく聞かれる質問だ。一度発行されたトークンは有効期限が切れるまで取り消すのが難しい(ブラックリストを管理する方法もあるが、JWTのステートレスな利点が失われる)。
解決策は:トークンの有効期限を短くして(例えば1時間)、refresh tokenの仕組みで自動更新する。vibefast.appは現在7日間の有効期限を使用しており、ほとんどのWebアプリに適している。
Q:必ずJWTを使わなければならないのか?
いいえ。Session + Cookieも成熟した方法で、従来のサーバー環境では完全に機能する。しかしCloudflare WorkersのようなエッジコンピューティングではJWTがより自然な選択だ。
Q:JWTとOAuthの関係は?
OAuthは認可フレームワーク(「Googleでログイン」のように、サードパーティアプリが代わりにリソースにアクセスする仕組み)だ。JWTはOAuthフローでよく使われるトークン形式だが、JWTはOAuthなしで独立して使えるし、必ずしもOAuthと組み合わせる必要はない。
まとめ
JWTはデジタル通行証で、ステートレスなHTTPシステムがユーザーの身元を確認できるようにする。Cloudflare Workersのようなエッジコンピューティング環境に特に向いている理由:
- サーバーがセッション状態を保存する必要がない
- どのエッジノードでも自分で検証できる
- 署名の仕組みが偽造を防ぐ
JWTを使う3つのセキュリティポイント:シークレットキーを秘密に保つ、有効期限を設定する、payloadに機密データを入れない。
Danko Peng
X · YouTube · Threads
完全なCloudflareフルスタックテンプレートを今すぐ使い始めたい方へ:
👉 vibefast.app — アーリーバード $99、2026年8月1日より $199 に値上がり。