JWT認証とは何か？ログインとの違いを理解する

# JWT認証とは何か？ログインとの違いを理解する

## 混乱したきっかけ

```typescript
@Post('login')  // 認証不要（ログイン用）
login(@Body() loginDto: LoginDto) {
  return this.authService.login(loginDto);
}

@UseGuards(JwtAuthGuard)  // ← このメソッドは認証必要
@Get('profile')
getProfile(@Request() req) {
  return req.user;
}
```

**「ログインは認証不要なのに、プロフィール取得は認証必要？」**

Nest.js触りたてで、この疑問がでてきたので、Claude Sonnet4さんにJWT認証の本質と仕組みを聞きました。
（※ そのまま回答を載せています）

## JWT認証が解決する問題

### 従来の課題：「誰がリクエストしているか分からない」

```http
GET /api/profile
# このリクエストは誰から？本当に信頼できる？
```

Webは基本的に**ステートレス**なので、サーバーはリクエストを送った人が誰なのか分かりません。

### JWT認証の解決策：「身分証明書」の仕組み

```http
GET /api/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# ↑ これが「デジタル身分証明書」
```

## ログインとJWT認証の関係

### 2段階のプロセス

#### 1段階目：ログイン（身分証明書の発行）
```typescript
@Post('login')  // 認証不要
login(@Body() loginDto: LoginDto) {
  // 1. ユーザー名・パスワードをチェック
  // 2. 正しければJWTトークン（身分証明書）を発行
  return { accessToken: 'jwt-token-here' };
}
```

**なぜ認証不要？**
- まだJWTトークンを持っていないから
- ユーザー名・パスワードで本人確認する
- 成功したらJWTトークンを渡す

#### 2段階目：JWT認証（身分証明書の確認）
```typescript
@UseGuards(JwtAuthGuard)  // 認証必要
@Get('profile')
getProfile(@Request() req) {
  // JWTトークンで「この人は〇〇さんです」と確認済み
  return req.user;
}
```

**なぜ認証必要？**
- 個人情報を扱うから
- JWTトークン（身分証明書）で本人確認する
- 偽造されていないかチェックする

## 具体的な流れ

### 実際のやり取り

```
1. 初回ログイン
Client → Server: POST /auth/login { email, password }
Server → Client: { accessToken: "jwt-token" }

2. 以降のAPIアクセス
Client → Server: GET /api/profile (Authorization: Bearer jwt-token)
Server → Client: { user: { name: "田中", email: "tanaka@example.com" } }
```

### 身分証明書の例で理解

```
1. パスポート申請（ログイン）
あなた → 役所: 「戸籍謄本と住民票を提出」
役所 → あなた: 「パスポートを発行」

2. 海外旅行（JWT認証）
あなた → 空港: 「パスポートを提示」
空港 → あなた: 「確認OK、通過してください」
```

## なぜこの仕組みが必要？

### 問題1：毎回パスワードを送るのは危険
```typescript
// ❌ 毎回パスワードを送信（危険）
@Get('profile')
getProfile(@Body() loginDto: LoginDto) {
  // 毎回ユーザー名・パスワードをチェック
}
```

### 問題2：サーバーがセッションを覚えるのは大変
```typescript
// ❌ サーバーがセッション管理（大変）
// 「user123がログイン中」を覚え続ける
// マイクロサービスでは不可能
```

### JWT認証の解決策
```typescript
// ✅ 安全で効率的
// 1. 最初だけパスワードチェック
// 2. 以降はJWTトークンで確認
// 3. サーバーはセッション情報を保持不要
```

## JWTトークンの中身

### 実際のJWTトークン
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLWlkIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIiwiaWF0IjoxNjM5NTIzNDAwfQ.signature
```

### デコードすると
```json
{
  "sub": "user-id",
  "email": "test@example.com", 
  "iat": 1639523400,
  "exp": 1639609800
}
```

**重要：** トークン自体に「誰の」「いつまで有効」が含まれている

## 認証が必要なAPI vs 不要なAPI

### 認証不要（誰でもアクセス可能）
```typescript
@Post('login')     // ログイン処理
@Post('register')  // 新規登録
@Get('public')     // 公開情報
@Get('health')     // ヘルスチェック
```

### 認証必要（本人確認が必要）
```typescript
@Get('profile')         // 個人情報
@Put('profile')         // 個人情報更新
@Get('my-orders')       // 注文履歴
@Post('logout')         // ログアウト
@Delete('account')      // アカウント削除
```

## JWT認証の流れ（完全版）

### 初回ログイン
```
1. ユーザー：「メール・パスワードでログインしたい」
2. サーバー：「確認します」→ データベースチェック
3. サーバー：「OK！JWTトークンをどうぞ」
4. ユーザー：JWTトークンを保存
```

### 以降のAPIアクセス
```
1. ユーザー：「プロフィール見たい」+ JWTトークン
2. サーバー：「トークンを確認...OK、田中さんですね」
3. サーバー：「田中さんのプロフィールをどうぞ」
```

### ログアウト後
```
1. ユーザー：JWTトークンを削除
2. 以降のAPIアクセスは「認証なし」扱い
```

## まとめ

**JWT認証とは：**
- **ログイン後の身分証明システム**
- 毎回パスワードを送らずに済む仕組み
- 「この人は確実に〇〇さんです」を証明

**ログインとの違い：**
- **ログイン**: 身分証明書をもらう手続き
- **JWT認証**: 身分証明書を見せて本人確認

**なぜ必要？**
- セキュリティ（パスワードを毎回送らない）
- 効率性（サーバーがセッション管理不要）
- スケーラビリティ（マイクロサービス対応）

```
つまり：ログイン = 身分証明書発行、JWT認証 = 身分証明書確認
```