JWT:あの長い文字列に実際何が入っているか
JSON Web Tokenをデコード。仕組み、内容、よくあるセキュリティミス。
認証システムで eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U のような文字列を見ます。
これは何?それはJWT——ドットで区切られた3つのBase64エンコードされた塊です。そして特別な鍵なしで読めます。
3つの部分
ヘッダー: アルゴリズムとトークンタイプ
{"alg": "HS256", "typ": "JWT"}
ペイロード: 実際のデータ(クレーム)
{"sub": "1234567890", "name": "John", "iat": 1516239022}
署名: 何も改ざんされていないことの検証
JWTは暗号化されていない
これが重要。誰でもJWTをデコードして内容を読めます。Base64はエンコーディングで、暗号化ではありません。
JWTに秘密を入れないでください。ユーザーID、権限、有効期限——OK。パスワード、クレジットカード、プライベートデータ——絶対ダメ。
標準クレーム
iss — 発行者(Issuer)。誰がこのトークンを作ったか。
sub — 主体(Subject)。通常はユーザーID。
exp — 有効期限(Expiration)。トークンが無効になるUnixタイムスタンプ。
iat — 発行時刻(Issued at)。トークンが作られた時。
aud — 対象者(Audience)。誰がこのトークンを受け入れるべきか。
カスタムクレームも機能します。アプリケーションが必要なデータを何でも追加できます。
署名の仕組み
署名はトークンが改変されていないことを証明します。
サーバーがトークン作成 → 秘密鍵で署名 → クライアントに送信。 クライアントがトークンを返送 → サーバーが署名を検証 → 内容を信頼。
誰かがペイロードを変更しても、署名が一致しません。サーバーは拒否します。
でもサーバーは署名を検証しなければなりません。検証なしのJWTはセキュリティシアター(見せかけ)です。
よくあるセキュリティミス
署名を検証しない。 一部のコードは署名をチェックせずJWTをデコード。誰でもトークンを偽造できます。
弱い秘密を使う。 secret123 は秘密ではありません。長いランダムな文字列を使いましょう。
有効期限を無視。 常に exp をチェック。トークンは短い寿命であるべきです。
アルゴリズムの混乱。 alg フィールドは検証方法を示します。攻撃者はこれを none に設定して検証をスキップできます、コードがヘッダーを信頼している場合。
機密データを保存。 トークンを持つ誰でもペイロードを読めます。秘密はサーバー側に保持しましょう。
JWTを使うべき時
ステートレス認証。 サーバーはセッションを保存する必要がない。トークンに必要なすべてが含まれている。
マイクロサービス。 サービスは認証サーバーを呼ばずにトークンを検証できる。
シングルサインオン。 ドメインをまたいで認証を共有。
JWTを使うべきでない時
シンプルなアプリ。 セッションクッキーの方がシンプルで失敗しにくい。
即座に無効化する必要がある。 JWTは有効期限まで有効。取り消しには追加のインフラが必要。
大きなペイロード。 すべてのリクエストが完全なトークンを運びます。大きなトークンはより多くの帯域幅を意味します。
リフレッシュトークン
アクセストークンは短命であるべき(数分~数時間)。リフレッシュトークンは再認証なしで新しいアクセストークンを取得します。
リフレッシュトークンは安全に保存しましょう。長命で強力です。
JWTは便利ですが注意が必要です。内容を理解し、署名を適切に検証し、短い有効期限を設定し、ペイロードに機密データを入れないでください。