JWT
2 tools
Webセキュリティの基礎
Webセキュリティは、不正アクセス、データ漏洩、攻撃からWebアプリケーションとAPIを保護する実践です。
JSON Web Token(JWT)は、モダンなWeb開発における主要なステートレス認証メカニズムです。
JSON Web Tokens(JWT)
JWTは、2者間のクレームをコンパクトでURLセーフな方法で表現するものです。ピリオドで区切られた3つのBase64urlエンコードされた部分で構成されます。
JWTの3つの部分
トークンのメタデータ(署名アルゴリズムalg、トークンタイプtyp)を含みます。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9{
"alg": "HS256",
"typ": "JWT"
}クレーム(ユーザーに関する声明)を含みます。ペイロードデータは暗号化されておらず、署名されているだけです。
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0{
"sub": "user_123",
"role": "admin",
"exp": 1717200000
}エンコードされたヘッダーとペイロードの暗号署名。この署名の検証によりトークンが改ざんされていないことを確認できます。
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cHMACSHA256( base64url(header) + "." + base64url(payload), secret )
標準JWTクレーム
JWT仕様は相互運用性を確保するための標準クレーム名を定義しています:
| クレーム | 名前 | 説明 |
|---|---|---|
| iss | Issuer | トークンを発行したプリンシパルを識別します |
| sub | Subject | トークンのサブジェクトを識別します(例:ユーザーID) |
| aud | Audience | トークンの対象受信者を識別します |
| exp | Expiration | このUnixタイムスタンプ以降はトークンを受け付けてはなりません |
| nbf | Not Before | このUnixタイムスタンプ以前はトークンを受け付けてはなりません |
| iat | Issued At | トークンが発行されたUnixタイムスタンプ |
| jti | JWT ID | リプレイ攻撃を防ぐためのトークンの一意識別子 |
署名アルゴリズム
署名アルゴリズムはJWTヘッダーで宣言されます。ユースケースに適したアルゴリズムの選択がセキュリティに重要です:
HS256 / HS384 / HS512対称(HMAC)署名と検証に共有秘密鍵を使用します。
RS256 / RS384 / RS512非対称(RSA)秘密鍵で署名し、公開鍵で検証します。秘密鍵は認証サーバーから出ません。
ES256 / ES384 / ES512非対称(ECDSA)RSAに似ていますが、鍵が小さく署名が速いです。
"alg": "none"署名なし——危険署名なし。alg:noneのトークンは整合性保証がなく、誰でも偽造できます。
認証フロー
- 1.ユーザーがユーザー名とパスワードをログインエンドポイントに送信
- 2.サーバーがユーザーデータベースに対して認証情報を検証
- 3.サーバーがユーザークレームと有効期限でJWTに署名
- 4.クライアントがJWTを保存(localStorage、Cookie、またはメモリ)
- 5.クライアントが後続のリクエストのAuthorization: BearerヘッダーでJWTを送信
- 1.クライアントがコードチャレンジとともにユーザーを認証サーバーにリダイレクト
- 2.ユーザーが認証してクライアントアプリケーションを承認
- 3.認証サーバーが一回限りの認証コードとともにリダイレクト
- 4.クライアントがコード+検証者をアクセストークンとリフレッシュトークンと交換
- 5.クライアントがAPIコールにアクセストークンを使用し、更新にリフレッシュトークンを使用
一般的なJWT脆弱性
JWTは正しく実装された場合に安全です。最も一般的な実装ミスを以下に示します:
一部のライブラリはalg:noneのトークンを受け付けます。攻撃者はペイロードを変更してalgをnoneに設定し、任意のJWTを偽造できます。
RS256を検証するはずのライブラリがHS256を受け入れる場合、攻撃者は公開鍵をHMACシークレットとして使ってトークンに署名できます。
expクレームのないJWT、またはexpを確認しないコードは、トークンが無期限に使用されることを許可します。
JWTペイロードはBase64エンコードされており、暗号化されていません。JWTクレームにパスワードやその他の秘密を保存しないでください。
短いまたは予測可能なシークレットを使用したHMACで署名されたJWTはオフラインでブルートフォース攻撃を受ける可能性があります。
署名を検証せずにJWTを受け入れることはペイロードを完全に信頼することになります。クレームを信頼する前に常に署名を検証してください。
よくある質問
標準のJWT(JWS)は署名されていますが暗号化されていません。ペイロードはBase64urlエンコードされており、簡単に元に戻せます。
アクセストークンは短命であるべきです:5〜60分が一般的です。新しいアクセストークンを取得するためにリフレッシュトークンを使用してください。
HttpOnlyクッキーが最も安全なオプションです——JavaScriptからアクセスできないため、XSSによる窃取を防ぎます。
サーバー側の状態なしにはできません。解決策:短い有効期限、トークンブロックリスト(Redis)。
セッションクッキーはランダムなセッションIDを保存し、サーバーがセッションデータを検索します。JWTは自己完結型で、サーバーはデータベースクエリなしに署名を検証します。
最低限:sub(ユーザーID)、exp(有効期限)、iat(発行日時)。ペイロードは小さく保ってください。
RS256(非対称)はほとんどの本番システムに適しています。認証サーバーのみが秘密鍵を必要とするためです。
PKCEはOAuth2認証コードフローの拡張で、認証コード傍受攻撃を防ぎます。パブリッククライアント(SPA、モバイルアプリ)には必須です。