JWTって要するに “改ざんされてない名刺” なんですよね – 図で学ぶセッションレス認証のしくみ

# JWTって要するに “改ざんされてない名刺” なんですよね  
図でわかるセッションレス認証のしくみ

---

最近のWebサービスでは、認証にJWTを使う場面がとても増えてきました。  
特に、マイクロサービスやサーバーレス構成との相性がよく、  
「セッションを持たないのに、ちゃんと認証できる」という仕組みが重宝されています。

この記事では、

- そもそも JWT ってなに？  
- なぜ流行ってるの？  
- どういう構造で どう動くの？  
- なにが嬉しくて、なにに注意が必要？

…を図やコードと一緒にざっくり解説していきます！

---

## 🔐 JWTとは？

JWT（JSON Web Token）は、ユーザーの**認証情報をクライアント側に持たせる**仕組みです。特徴としては：

- セッションテーブルが不要（＝サーバー側が状態を保持しない）
- 各リクエストにトークンを付けて認証する
- 実装によっては認可も付けたり付けなかったり
- サーバーがスケーラブルかつ高速に動けるようになる

ポイントは、JWTは **暗号化されているわけではない** ということ。  
中身は **Base64URLエンコードされているだけ** なので、誰でもデコードできます。  
**だから HTTPS は絶対前提！**

---

## 📦 JWTの構造

JWTは3つのパートに分かれていて、それぞれドット（`.`）で繋がっています：

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

### Header（一例）：
```json
{
  "alg": "RS256",
  "typ": "JWT"
}
```

署名に使うアルゴリズムなどが書かれています。

---

### Payload（一例）：
```json
{
  "sub": "00123",
  "name": "omochi",
  "role": "standard user",
  "iat": 1516239022
}
```

- `sub`: ユーザーID  
- `name`: ユーザー名  
- `role`: 権限（認可情報）  
- `iat`: 発行時刻  

この部分が「名刺」的な役割を果たします。  
※誰でも読めるので、**信頼性の鍵は Signature にかかってます**

---

### Signature（一例）：
```text
RSASHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  秘密鍵
)
```

→ 改ざんを防ぐための署名。トークンが**正しく発行されたことを保証**します。

---

## 🧾 JWT認証の流れ（基本の図）

```mermaid
sequenceDiagram
    participant Client
    participant Server

    Client->>Server: ユーザー名/パスワードでログイン
    Server->>Server: ユーザーデータを照合
    Server-->>Client: JWTを発行
    Client->>Server: JWTを付けてリクエスト
    Server->>Server: JWTを検証
    Server-->>Client: リソースを返す
```

> 🗒️ ※ 図ではサーバー1台ですが、実際にはサーバーが何台あってもOK。  
> JWTを検証できる鍵を各サーバーが持っていれば、**状態を共有しなくても認証できます！**

---

## 🏗️ JWTとスケーラブルな構成（アーキテクチャ図）

```mermaid
graph TD
  subgraph クライアント
    A[ログイン要求]
  end

  subgraph 認証サーバー
    B[ユーザー情報を確認してJWT発行]
  end

  subgraph APIサーバー群
    C1[APIサーバー①]
    C2[APIサーバー②]
    C3[APIサーバー③]
  end

  A --> B --> A
  A --> C1
  A --> C2
  A --> C3
```

→ 初回ログインでJWTを受け取れば、以降はどのAPIサーバーにでもリクエスト可能。  
→ **各サーバーはJWTを検証するだけで、認証済みかどうか判断できます。**

---

## 🔄 セッション管理してないって、どういうこと？

JWTではサーバーが状態（セッション）を持たないため：

```text
「漏れたのですぐ止めたい！」→ セッションぶちっ！…ができない。
```

つまり、**有効期限が長すぎると危険**です。

> 🔸 対策：
> - 有効期限を短くする  
> - リフレッシュトークンを併用する  
> - ブラックリスト方式で制御する（ただし複雑）

---

## 🎉 JWT ってそんなに嬉しい？

たとえば次のような**マイクロサービス構成**ではとても相性が良いです：

```
API Gateway + Lambda  
Fargate上のサービス群  
Kubernetes（EKS）上のマイクロサービス
```

それぞれが独立して動いていても：

- JWTを受け取る  
- 検証用の公開鍵を持っている  
- →「あ、この人は認証済みだな」と自己完結できる！

**つまり、中央のセッションDBが不要**になる！

---

## ✅ マイクロアーキテクチャでは RS256（公開鍵方式）がベスト

- HS256（対称鍵）は秘密鍵の共有が面倒＆セキュリティリスク
- RS256（非対称鍵）は「署名者」と「検証者」を分離できる
- 各サービスが**同じ公開鍵で検証**できるだけでいい！

だから、**マイクロアーキテクチャでは RS256 一択**です。

---

## 🔑 鍵の配布ってどうやるの？ → JWKs！

検証側の各種サービスにどうやって公開鍵を渡すか？という課題も出てきます。

そのときに便利なのが **JWKs（JSON Web Key Set）**。  
これは**複数の公開鍵をJSONで一覧公開**する仕様で、たとえば：

```
https://your-auth.example.com/.well-known/jwks.json
```

こんなURLでホストしておきます。

利用者は `kid` をもとに一致する鍵を選び、JWTの署名を検証できます。

```json
{
  "keys": [
    {
      "kty": "RSA",
      "alg": "RS256",
      "kid": "key1",
      "use": "sig",
      "n": "....",
      "e": "AQAB"
    }
  ]
}
```

→ こうすることで、**発行者と利用者が異なっていても連携できる**ようになります。

---

## 🧠 おまけ：JWTの中身を見てみよう

たとえば以下のようなトークンを https://jwt.io に貼ってみると、中身が読めます：

```
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDEyMyIsIm5hbWUiOiJvbW9jaGkiLCJyb2xlIjoic3RhbmRhcmQgdXNlciIsImlhdCI6MTUxNjIzOTAyMn0.SignatureHere
```

---

## 📝 まとめ

- JWTは「改ざんされていない名刺」のようなもの
- セッションレス認証により、高速＆スケーラブル
- ただし、有効期限や漏洩対策は設計に工夫が必要
- RS256＋JWKsの組み合わせは、マイクロサービス時代の鉄板構成！

---

ここまで読んでくださってありがとうございます！  
どなたかの理解の一助になれば幸いです。コメントなどいただけたら嬉しいです🙌