最近、XでJWTをlocalstorageに入れるなだのセキュリティだのなんだの何を今更言ってるんだとは思いましたが、そもそもJWTとは何?って思う人もいると思うのでこの記事を書いてみます。
JWTとは
まず、JWTは JSON Web Token の略で、署名付きデータをコンパクトに表現するためのトークン形式です。
アクセストークンとして使われることもありますが、JWT自体はあくまで「フォーマット」であり、用途はそれに限りません。
xxxxx.yyyyy.zzzzz
この3つに分かれた文字列がJWTです。
左から順に ヘッダー、ペイロード、署名 という構造になっています。
ヘッダー
最初の部分(x)はヘッダーで、トークンのメタ情報が入っています。
- トークンのタイプ(typ)
- 署名アルゴリズム(alg)
例としては、HS256(共通鍵方式)やRS256(公開鍵方式)などがあります。
ペイロード
真ん中の部分(y)はペイロードで、JWTの中身にあたる部分です。
ここには「クレーム」と呼ばれる情報が入ります。
- ユーザーID(sub)
- 有効期限(exp)
- 発行時刻(iat)
- スコープ情報
- システム固有のユーザー情報
ただし、ここは 暗号化されていません。
Base64URLでエンコードされているだけなので、誰でも中身を読めます。
そのため、パスワードや機密情報を入れてはいけません。
署名
最後の部分(z)は署名で、トークンが改ざんされていないことを確認するためのものです。
署名方式には大きく2種類あります。
- HS256などの共通鍵方式(署名と検証に同じ鍵を使う)
- RS256などの公開鍵方式(署名は秘密鍵、検証は公開鍵)
どちらにせよ、署名のおかげで「途中で書き換えられていない」ことを検証できます。
JWTを使うメリット
JWTのメリットとしてよく挙げられるのは、サーバー側がステートレスで動ける点です。
例えば、ユーザーがログインするとサーバーはJWTを発行します。
以降のリクエストでは、クライアントがJWTをヘッダーに載せて送ることで、サーバーは署名を検証するだけでユーザーを識別できます。
セッションのようにサーバー側で状態を持たなくてよいため、スケールしやすく、API間通信にも向いています。
JWTのデメリット
便利な反面、JWTには注意すべき点もあります。
1. 無効化が難しい
JWTはステートレスであるため、一度発行したトークンを「サーバー側から強制的に無効化する」ことが簡単ではありません。
有効期限が切れるまで基本的に使えてしまいます。
そのため、短い有効期限にしてリフレッシュトークンと組み合わせるなどの工夫が必要になります。
2. 盗まれるとそのまま使われる
JWTは「持っているだけで認証が通る」仕組みなので、盗まれると誰でも使えてしまいます。
特に注意すべきは保存場所で、
- localStorage → XSSで盗まれやすい
- Cookie → CSRF対策が必要
という特徴があります。
3. ペイロードが暗号化されていない
中身は誰でも読めるため、機密情報を入れるべきではありません。
まとめ
JWTは便利で強力な仕組みですが、正しく理解して使わないと危険な面もあります。
- JWTは「トークンの形式」であり、アクセストークン専用ではない
- ペイロードは暗号化されていない
- 無効化が難しいため短い期限が前提
- 保存場所によっては簡単に盗まれる