# JWTとは何か？毎日使っているこの技術をわかりやすく解説

[English](../en/04-what-is-jwt-authentication-en.md) · [繁中](../zh/04-what-is-jwt-authentication-zh.md) · [Español](../es/04-what-is-jwt-authentication-es.md) · [日本語](../jp/04-what-is-jwt-authentication-jp.md) · [Português (BR)](../pt-br/04-what-is-jwt-authentication-pt-br.md)

**著者：** Danko Peng（[@dankopeng](https://x.com/dankopeng)）  
**更新：** 2026年3月  
**読了時間：** 約8分

-----

## まずリアルなシーンから始めよう

アプリを開いて、アカウントとパスワードを入力してログインする。

その後、あるページに移動し、また別のページに移動する。システムは毎回あなたが誰かを知っていて、再ログインを求めない。

これは当たり前のことに思えるが、裏には一つの問題がある：

**HTTPは「記憶なし」のプロトコルだ。**

リクエストのたびにサーバーにとっては完全に新しいやりとりだ——「前のリクエストが誰から来たか」を自動では覚えていない。ログインした後、次のページを開いたとき、サーバーはどうやってまだ同じあなただとわかるのか？

これがJWTが解決する問題だ。

-----

## JWTとは何か？

**JWT（JSON Web Token）** はサーバーが「あなたが誰か」を「覚える」ための方法だ。

**デジタル通行証**と考えるとわかりやすい：

1. ログインすると、サーバーがアカウントとパスワードを確認する
1. サーバーがあなたに通行証（JWTトークン）を渡す
1. 以降のすべてのリクエストにこの通行証を添付する
1. サーバーは通行証を見て、あなたが誰で、どんな権限があるかを確認する

このプロセスでサーバーが何も記憶する必要はない——すべての情報は通行証の中にある。

-----

## JWTはどんな形をしているのか？

JWTは非常に長い文字列で、こんな形をしている：

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywiZW1haWwiOiJ1c2VyQGV4YW1wbGUuY29tIiwicm9sZSI6InVzZXIiLCJleHAiOjE3MDk0NTEyMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```

複雑に見えるが、実は3つの部分に分かれていて、`.`で区切られている：

```
[Header].[Payload].[Signature]
```

### Header（ヘッダー）

このトークンがどのアルゴリズムで暗号化されているかを示す：

```json
{
  "alg": "HS256",
  "typ": "JWT"
}
```

### Payload（ペイロード）

実際のデータが入る——誰か、どんな権限があるか、このトークンの有効期限：

```json
{
  "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を含む任意のユーザーになりすまされる。

シークレットキーは環境変数から読み込む必要があり、コードに直接書いてはいけない。ランダムで強力なシークレットを生成するコマンド：

```bash
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](https://x.com/dankopeng) · [YouTube](https://www.youtube.com/@DankoPeng) · [Threads](https://www.threads.com/@dankopeng)

-----

👉 [チュートリアルトップに戻る](../README-jp.md)

完全なCloudflareフルスタックテンプレートを今すぐ使い始めたい方へ：  
👉 **[vibefast.app](https://vibefast.app/pricing)** — アーリーバード $99、2026年8月1日より $199 に値上がり。
