クリスマスのお供「JWT」をあなたへ

この記事は [株式会社うるる（ULURU） Advent Calendar 2023](https://qiita.com/advent-calendar/2023/uluru) の24日目の記事です。

# はじめに
クリスマスイブですね、皆様いかがお過ごしでしょうか？？？
私は明日のクリスマスとM1決勝に向けて、気持ちを高めております。

今回は最近触れる機会が多かったJWTについて、自分の備忘録の意味も込めてまとめてみました。
年末の隙間時間にでも見ていただけると嬉しいです。

# JWTとは
JWT（JSON Web Token）は、データの安全な転送を行うためのJSON形式のトークン規格です。ヘッダ、ペイロード、署名から成り立ち、認証や情報共有に使用されます。

```:実際のJWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```

# JWTの構造
JWTは「ヘッダー」「ペイロード」「シグネチャ」の3つから生成されています。それぞれは、Base64でエンコードされており、**.** (ドット)で接続されています。

## ヘッダー
ヘッダー（Header）は、JWTトークンの構造と署名アルゴリズムに関する情報を含む部分です。
```json:header
{
  "alg": "HS256",
  "typ": "JWT"
}
```
### alg
alg（Algorithm）: このフィールドは、JWTの署名アルゴリズムを指定します。JWTを生成する際と検証する際に使用されるアルゴリズムです。一般的な値には "HS256"（HMAC SHA-256）、"RS256"（RSA SHA-256）、"ES256"（ECDSA SHA-256）などがあります。

### typ
typ（Type）: このフィールドは、JWTトークンのタイプを示します。通常は "JWT" と設定されます。

## ペイロード
ペイロード（Payload）は、トークンに含まれる情報を格納する部分です。
```json:payload
{
  "iss": "example.com",
  "sub": "1234567890",
  "aud": "myapp",
  "exp": 1696135807,
  "nbf": 1696132200,
  "iat": 1696132200,
  "jti": "unique-jwt-id"
}
```
上記は、JWTのペイロードの例です。ペイロードはJSON形式で表現されており、RFCに登録済みのクレーム名（下記）もありますが、使用は必須ではありません。カスタムのクレーム（Claims）を使用することもできます。

| クレーム | 説明 |
|:-:|:-|
|  iss |   	JWT発行者 |
|  sub |   JWT発行者から払い出されたユーザ識別子。|
|  aud |  JWTを利用することが想定された主体の識別子一覧 |
|  exp |  JWTの有効期限を示す。 |
|  nbf |  JWTが有効になる日時を示す |
|  iat |  JWTを発行した時刻を示す |
|  jti |  JWTのための一意な識別子。JWTのリプレイを防ぐことに利用する |
|  typ | typヘッダパラメータと同じ値空間および同じ規則が適用される  |

# 署名
署名（Signature）はヘッダとペイロードを含めたデータの署名がこのセクションに含まれます。署名の生成には、秘密鍵を使用し、署名の検証には公開鍵が使用されます。これによって正しい発行者が発行したIDトークンであることを確認できます。

# JWTの認証フロー
1. **ユーザーの認証:** ユーザーは通常、ユーザー名とパスワード、または他の認証手段を使用してアプリケーションにログインします。認証が成功すると、アプリケーションはユーザーに対してJWTを発行します。
2. **JWTの発行:** 認証サーバーまたはバックエンドサービスは、ユーザーを識別する情報（例: ユーザーID、ロール、有効期限など）を含むJWTを生成します。このJWTは、ユーザーのクライアントに返されます。
3. **JWTの保存:** ユーザーのクライアント（通常はブラウザやモバイルアプリ）は、受け取ったJWTを安全に保存します。通常、ブラウザではクッキーまたはローカルストレージ、モバイルアプリではメモリやセキュアストレージが使用されます。
4. **APIへのアクセス:** ユーザーがAPIエンドポイントにアクセスする際、JWTをHTTPヘッダーまたはクエリパラメータとして送信します。一般的に、"Authorization"ヘッダーにBearerトークンとして送信されます。
5. **JWTの検証:** APIサーバーは、受信したJWTを検証します。検証には、JWTの署名を検証し、トークンの有効期限を確認するなどのステップが含まれます。
6. **アクセス許可の確認:** JWT内の情報を使用して、APIサーバーはユーザーが要求した操作を実行できるかどうかを確認します。JWTには、ユーザーのロールや権限情報が含まれていることが一般的です。
7. **リソースの提供:** JWTが検証され、ユーザーがアクセス権を持っている場合、APIサーバーは要求されたリソースまたはサービスを提供します。   

# メリット
1. **シンプルで軽量:** JWTはJSON形式でデータを表現するため、シンプルで軽量なデータ構造を使用します。これにより、データの交換が効率的に行えます。
2. **クロスドメイン通信:** クロスドメイン通信の際に、JWTを使用することで認証を容易に行えます。クッキーを使用せず、ヘッダーにトークンを含めることができます。
3. **権限管理:** JWTのペイロードには権限情報を含めることができ、アクセス制御を簡単に行えます。 

# デメリット
1. **セキュリティリスク:** トークンはクライアント側に保存されるため、クロスサイトスクリプティング（XSS）攻撃やクロスサイトリクエストフォージェリ（CSRF）攻撃などのセキュリティリスクに対処する必要があります。適切なセキュリティ対策が必要です。
2. **情報の暴露:** トークンはデータを含んでおり、ヘッダーとペイロードはBase64エンコードされています。これにより、情報が暴露されるリスクがあるため、機密性の高い情報をトークンに含める際には注意が必要です。
3. **トークンの管理:** トークンは有効期限があるため、期限切れのトークンの管理やリフレッシュトークンの実装が必要です。
4. **秘密鍵の管理:** 非対称鍵を使用する場合、秘密鍵の安全な管理が必要です。秘密鍵が漏洩すると、システムのセキュリティが脆弱になります。

# おまけ
[こちら](https://jwt.io/#debugger)のサイトでjwtの構成を簡単に見ることができるので、気になる方は確認してみてください。
![スクリーンショット 2023-12-23 10.55.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696017/a0ddba4f-ae16-2f36-84d3-e956e137e504.png)

# 最後に
今までなんとなくで理解していたJWTについて学ぶ良い機会となりました。1つ1つの技術について深ぼると、楽しいことに気づいた2年目の冬でした。。(~~おそい~~)
**今日の夜はM1を深ぼろうと思います！！！**
#

明日は@okamoto-shun-uluruさんの投稿です！お楽しみに！！