Skip to content
nishi_74322014 edited this page Aug 4, 2026 · 1 revision

JWT

概要

  • JWT : JSON Web Token は、jot(ジョット)と発音する。
  • JOSE(MS_JOSE.md) : JSON Object Signing and Encryption のサブセット仕様。

仕様

  • URL 中で使用可能な(url-safe な)、JSON のアサーションを生成するための仕様

  • Base64 URL Encode したヘッダ、ペイロード(クレームセット)等を「.」で連結

    • このため url-safe であり、Web での取り扱いが楽。
    • 言語毎のライブラリも整っており、自作も相互運用も容易。
  • JWT には、JWSJWE がある(JWK は違う)。

補足: 用語の関係を整理しておく。

内容
JOSE 署名・暗号化の仕様群の総称(JWS / JWE / JWK / JWA)
JWS 署名付き(RFC 7515)。ヘッダ.ペイロード.署名
JWE 暗号化(RFC 7516)。5 パート構成
JWK 鍵の JSON 表現(RFC 7517)。jwks_uri で公開する
JWA アルゴリズム識別子の定義(RFC 7518)
JWT 上記を使ってクレームセットを運ぶフォーマット(RFC 7519)

実務で「JWT」と言うとき、ほぼ JWS 形式の JWT を指す。

用途

  • 以下を主張する。

    • メッセージ認証コード(MAC)やデジタル署名で完全性保護されていること(JWS)
    • および/または暗号化されていること(JWE)
  • 署名により、鍵でペイロード(クレームセット)の改ざんチェックが可能
    (=信頼関係のセマンティクス)。
    この特徴のため、仲介者を伴う(改ざん・盗聴の危険性がある)情報のやり取りに利用される。

移行メモ(正誤): 元ページは「暗号化により、鍵でペイロードの 改ざんチェックが可能」としていたが、 改ざんチェック(完全性保護)を担うのは署名/MAC(JWS) である。 暗号化(JWE)が担うのは秘匿であり、目的が異なる。

なお重要な点として、JWS は暗号化していない。 ペイロードは Base64URL エンコードされているだけで、 誰でもデコードして読める。 JWT に秘密情報を入れてはならない(JWE を使わない限り)。

構造

ヘッダ

  • JOSE : JSON Object Signing and Encryption ヘッダ

    • 署名・検証のために利用するもの。
    • 電子署名、MAC に関する情報を保持する。
  • ヘッダの内容は、3 種に分けられている。

種別 内容
Registered Header RFC 上で仕様化されているヘッダ内容。署名アルゴリズムを示す alg、公開鍵の在処を示す jku(JWK Set URL)など
Public Header 定義可能だが名前の衝突を避けるために IANA に登録するヘッダ内容
Private Header 衝突するかもしれないから注意が必要なヘッダ内容
  • ヘッダ・パラメタ
    • typ(オプション)を設定するなら、
      • "JWT"
      • "JOSE" : JWS や JWE の Compact Serialization
      • "JOSE+JSON" : JWS や JWE の JSON Serialization
      • "application/" 接頭辞を省略した Media Types
    • cty(オプション)は、構造情報を伝えるために使用される。
      • "JWT" : ネストされた JWT のペイロード
    • ヘッダ・パラメタは、JWS と JWE で異なる。
      • JWS の場合、alg, typ など: { "alg": "HS256", "typ": "JWT" }
      • JWE の場合、alg, enc など: { "alg": "RSA-OAEP", "enc": "A256GCM" }

ペイロード(クレームセット)

予約済みクレーム(以下すべて、使用は任意 (OPTIONAL))。

# キー 説明
1 iss Issuer クレーム(発行者)
2 sub Subject クレーム(主体)
3 aud Audience クレーム(想定利用者)
4 exp Expiration Time クレーム(有効期限)
5 nbf Not Before クレーム
6 iat Issued At クレーム
7 jti JWT ID クレーム
8 typ Type クレーム
  • パブリック・クレーム

    • JWT の利用者によって自由に定義できる。
    • 衝突を避けるために、IANA JSON Web Token Claim Registry に登録するか、
      耐衝突性を持つ名前空間を含むパブリック名にすべき。
  • プライベート・クレーム

    • JWT の作成者と利用者の合意のもとで、
      予約済みでもパブリック・クレーム名でもない名前を利用可能。
    • ただし、衝突の可能性があるため、慎重に使用する必要がある。

サンプル

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

補足(検証の必須項目): JWT を受け取る側は、 署名検証だけでは不十分である。次をすべて確認すること。

項目 確認内容
署名 期待する鍵で検証できるか
alg サーバ側で期待する値に固定する(後述)
iss 期待する発行者か
aud 自分宛てか(漏れると他 API 向けトークンを受理する)
exp / nbf 有効期間内か(時刻ずれの許容は数分まで)

aud の検証漏れは実際に多く、 WebAPIの認証 でも触れた典型的な脆弱性である。

JWTの種類

  • JWS — 署名付き
  • JWE — 暗号化
  • ネストされた JWT
    • ペイロード(若しくは平文)として、JWS や JWE が使用される。
    • 署名と暗号化の両方が必要な場合の順序は、
      プロデューサがメッセージに署名してから結果を暗号化する
      (従って、署名を暗号化する)。
  • 無担保 JWT
    • JWS でも JWE でもない、プレーンな JWT。

    • ヘッダ内の alg は none = {"alg": "none"}

    • フォーマット(JWS Compact Serialization)

      BASE64URL (UTF-8 (Header))
      .
      BASE64URL (UTF-8 (Claim Set))
      .
      

補足(重大な脆弱性): 「無担保 JWT」= alg: none は、 JWT で最も有名な攻撃の入口である。

攻撃者が algnone に書き換え、署名部を空にして送ると、 検証側が alg を鵜呑みにする実装では素通りしてしまう。 同様に、RS256(公開鍵署名)を HS256(共通鍵 MAC)に書き換え、 公開鍵を HMAC の鍵として使わせる攻撃もある。

対策は「受け入れる alg をサーバ側で固定する」ことに尽きる。 ヘッダの alg を見て検証方法を決めてはならない。

var validationParameters = new TokenValidationParameters
{
    ValidAlgorithms = new[] { SecurityAlgorithms.RsaSha256 },
    ValidateIssuer = true,   ValidIssuer = "https://sts.example.com/",
    ValidateAudience = true, ValidAudience = "api://my-api",
    ValidateLifetime = true,
};

なお、jku / x5u(鍵の所在を URL で示すヘッダ)を そのまま信用して鍵を取りに行く実装も危険である。 取得先は許可リストで縛ること。

JWTの作成と検証手順

作成手順

  • JWS や JWE の手順に従って作成する。
  • 入れ子になった JWT の場合にはヘッダの cty の値に "JWT" を指定する。

検証(復号)手順

JWS や JWE の手順に従って検証(復号)する。

アルゴリズム

利用される各アルゴリズムおよびそれらの識別子は JWA(RFC 7518)で定義されている。

用途 代表的な alg
HMAC(共通鍵) HS256 / HS384 / HS512
RSA 署名(PKCS#1 v1.5) RS256 / RS384 / RS512
RSA 署名(PSS) PS256 / PS384 / PS512
ECDSA ES256 / ES384 / ES512
鍵管理(JWE) RSA-OAEP / ECDH-ES / A256KW
コンテンツ暗号(JWE) A128GCM / A256GCM / A128CBC-HS256

補足: HS256(共通鍵)は、 検証できる者が偽造もできるため、 発行者と検証者が同一の場合にしか使えない。 複数の RP にトークンを配る IdP は、必ず公開鍵署名 (RS256 / ES256 / PS256)を使い、 公開鍵は jwks_uri で公開する。

詳細は .NETの署名・暗号化アルゴリズム を参照。

ユースケース

認証用途

  • OpenID Connectの ID トークン
  • OAuth 2.0 のアクセス トークン(JWT 形式のもの)
  • OAuth 2.0 JWT Bearer Token Flow(RFC 7523)による
    クライアント認証・グラント(WebAPIの認証 を参照)

補足(設計上の注意): 「セッションを JWT で置き換える」という 使い方には注意が要る。 署名付きトークンは、発行後に取り消せない(有効期限が切れるまで有効)。

  • アクセス トークンは短命(数分〜1 時間)にする
  • 失効が必要な系ではリフレッシュ トークンを併用し、 そちらをサーバ側で失効管理する
  • どうしても即時失効が要るなら トークン イントロスペクション(RFC 7662)で毎回問い合わせる (=ステートレスの利点は失われる)

また、ブラウザで保持する場合、 localStorage は XSS で盗まれ、Cookie は CSRF(MS_CSRFCountermeasures.md)の考慮が要る。 どちらの脅威を取るかの判断が必要である。

.NETでの実装

補足: .NET では Microsoft.IdentityModel.Tokens / System.IdentityModel.Tokens.Jwt が標準的である。 ASP.NET Core で API を保護するなら、 Microsoft.AspNetCore.Authentication.JwtBearer を使えば 前述の検証(iss / aud / exp / alg / 署名鍵の自動取得)が まとめて行われる。自前でパースしないこと。

参考


Tags: IT国際標準, 認証基盤, クレームベース認証, セキュリティ

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally