-
Notifications
You must be signed in to change notification settings - Fork 0
MS_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 には、JWS や JWE がある(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)
-
署名により、鍵でペイロード(クレームセット)の改ざんチェックが可能
(=信頼関係のセマンティクス)。
この特徴のため、仲介者を伴う(改ざん・盗聴の危険性がある)情報のやり取りに利用される。- 主に、認証サーバから返されるトークンに使われる。
- 実際、OAuth 2.0 拡張や OpenID Connectなどで使われている。
移行メモ(正誤): 元ページは「暗号化により、鍵でペイロードの 改ざんチェックが可能」としていたが、 改ざんチェック(完全性保護)を担うのは署名/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" }
- JWS の場合、
-
予約済みクレーム(以下すべて、使用は任意 (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 の作成者と利用者の合意のもとで、
予約済みでもパブリック・クレーム名でもない名前を利用可能。 - ただし、衝突の可能性があるため、慎重に使用する必要がある。
- JWT の作成者と利用者の合意のもとで、
サンプル
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}補足(検証の必須項目): JWT を受け取る側は、 署名検証だけでは不十分である。次をすべて確認すること。
項目 確認内容 署名 期待する鍵で検証できるか algサーバ側で期待する値に固定する(後述) iss期待する発行者か aud自分宛てか(漏れると他 API 向けトークンを受理する) exp/nbf有効期間内か(時刻ずれの許容は数分まで)
audの検証漏れは実際に多く、 WebAPIの認証 でも触れた典型的な脆弱性である。
- 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 で最も有名な攻撃の入口である。攻撃者が
algをnoneに書き換え、署名部を空にして送ると、 検証側が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 で示すヘッダ)を そのまま信用して鍵を取りに行く実装も危険である。 取得先は許可リストで縛ること。
- 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 では
Microsoft.IdentityModel.Tokens/System.IdentityModel.Tokens.Jwtが標準的である。 ASP.NET Core で API を保護するなら、Microsoft.AspNetCore.Authentication.JwtBearerを使えば 前述の検証(iss/aud/exp/alg/ 署名鍵の自動取得)が まとめて行われる。自前でパースしないこと。
- トークン
- クレームベース認証
- WebAPIの認証
- .NETの署名・暗号化アルゴリズム
- RFC 7519 - JSON Web Token (JWT)
- RFC 8725 - JSON Web Token Best Current Practices
- [前編] IDトークンが分かれば OpenID Connect が分かる - Qiita
- JWT.io
Tags: IT国際標準, 認証基盤, クレームベース認証, セキュリティ
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。