JWT

2 tools

Webセキュリティの基礎

Webセキュリティは、不正アクセス、データ漏洩、攻撃からWebアプリケーションとAPIを保護する実践です。

JSON Web Token(JWT)は、モダンなWeb開発における主要なステートレス認証メカニズムです。

JSON Web Tokens(JWT)

JWTは、2者間のクレームをコンパクトでURLセーフな方法で表現するものです。ピリオドで区切られた3つのBase64urlエンコードされた部分で構成されます。

JWTの3つの部分

Header

トークンのメタデータ(署名アルゴリズムalg、トークンタイプtyp)を含みます。

エンコード済み
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
デコード済み
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload

クレーム(ユーザーに関する声明)を含みます。ペイロードデータは暗号化されておらず、署名されているだけです。

エンコード済み
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0
デコード済み
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1717200000
}
Signature

エンコードされたヘッダーとペイロードの暗号署名。この署名の検証によりトークンが改ざんされていないことを確認できます。

エンコード済み
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
デコード済み
HMACSHA256(
  base64url(header) + "." +
  base64url(payload),
  secret
)

標準JWTクレーム

JWT仕様は相互運用性を確保するための標準クレーム名を定義しています:

クレーム名前説明
issIssuerトークンを発行したプリンシパルを識別します
subSubjectトークンのサブジェクトを識別します(例:ユーザーID)
audAudienceトークンの対象受信者を識別します
expExpirationこのUnixタイムスタンプ以降はトークンを受け付けてはなりません
nbfNot BeforeこのUnixタイムスタンプ以前はトークンを受け付けてはなりません
iatIssued Atトークンが発行されたUnixタイムスタンプ
jtiJWT IDリプレイ攻撃を防ぐためのトークンの一意識別子

署名アルゴリズム

署名アルゴリズムはJWTヘッダーで宣言されます。ユースケースに適したアルゴリズムの選択がセキュリティに重要です:

HS256 / HS384 / HS512対称(HMAC)

署名と検証に共有秘密鍵を使用します。

使用する場合: すべての当事者を制御する内部サービス。
RS256 / RS384 / RS512非対称(RSA)

秘密鍵で署名し、公開鍵で検証します。秘密鍵は認証サーバーから出ません。

使用する場合: マイクロサービスアーキテクチャ、サードパーティトークン検証、OAuth2、OpenID Connect。
ES256 / ES384 / ES512非対称(ECDSA)

RSAに似ていますが、鍵が小さく署名が速いです。

使用する場合: パフォーマンスが重要なモバイルとIoTアプリケーション。
"alg": "none"署名なし——危険

署名なし。alg:noneのトークンは整合性保証がなく、誰でも偽造できます。

使用する場合: 本番環境では絶対に使用しないでください。

認証フロー

パスワードグラント(直接)
  1. 1.ユーザーがユーザー名とパスワードをログインエンドポイントに送信
  2. 2.サーバーがユーザーデータベースに対して認証情報を検証
  3. 3.サーバーがユーザークレームと有効期限でJWTに署名
  4. 4.クライアントがJWTを保存(localStorage、Cookie、またはメモリ)
  5. 5.クライアントが後続のリクエストのAuthorization: BearerヘッダーでJWTを送信
認証コード + PKCE(OAuth2)
  1. 1.クライアントがコードチャレンジとともにユーザーを認証サーバーにリダイレクト
  2. 2.ユーザーが認証してクライアントアプリケーションを承認
  3. 3.認証サーバーが一回限りの認証コードとともにリダイレクト
  4. 4.クライアントがコード+検証者をアクセストークンとリフレッシュトークンと交換
  5. 5.クライアントがAPIコールにアクセストークンを使用し、更新にリフレッシュトークンを使用

一般的なJWT脆弱性

JWTは正しく実装された場合に安全です。最も一般的な実装ミスを以下に示します:

アルゴリズムの混乱(alg:none)重大

一部のライブラリはalg:noneのトークンを受け付けます。攻撃者はペイロードを変更してalgをnoneに設定し、任意のJWTを偽造できます。

HS256/RS256の混乱重大

RS256を検証するはずのライブラリがHS256を受け入れる場合、攻撃者は公開鍵をHMACシークレットとして使ってトークンに署名できます。

有効期限の検証がない

expクレームのないJWT、またはexpを確認しないコードは、トークンが無期限に使用されることを許可します。

ペイロードの機密データ

JWTペイロードはBase64エンコードされており、暗号化されていません。JWTクレームにパスワードやその他の秘密を保存しないでください。

弱い秘密鍵(HS256)

短いまたは予測可能なシークレットを使用したHMACで署名されたJWTはオフラインでブルートフォース攻撃を受ける可能性があります。

署名検証がない

署名を検証せずにJWTを受け入れることはペイロードを完全に信頼することになります。クレームを信頼する前に常に署名を検証してください。

よくある質問

JWTは暗号化されていますか?

標準のJWT(JWS)は署名されていますが暗号化されていません。ペイロードはBase64urlエンコードされており、簡単に元に戻せます。

JWTの有効期間はどのくらいが適切ですか?

アクセストークンは短命であるべきです:5〜60分が一般的です。新しいアクセストークンを取得するためにリフレッシュトークンを使用してください。

ブラウザでJWTはどこに保存すべきですか?

HttpOnlyクッキーが最も安全なオプションです——JavaScriptからアクセスできないため、XSSによる窃取を防ぎます。

有効期限前にJWTを失効させることはできますか?

サーバー側の状態なしにはできません。解決策:短い有効期限、トークンブロックリスト(Redis)。

JWTとセッションクッキーの違いは何ですか?

セッションクッキーはランダムなセッションIDを保存し、サーバーがセッションデータを検索します。JWTは自己完結型で、サーバーはデータベースクエリなしに署名を検証します。

JWTにどのクレームを含めるべきですか?

最低限:sub(ユーザーID)、exp(有効期限)、iat(発行日時)。ペイロードは小さく保ってください。

RS256はHS256より優れていますか?

RS256(非対称)はほとんどの本番システムに適しています。認証サーバーのみが秘密鍵を必要とするためです。

PKCEとは何ですか?なぜ重要ですか?

PKCEはOAuth2認証コードフローの拡張で、認証コード傍受攻撃を防ぎます。パブリッククライアント(SPA、モバイルアプリ)には必須です。