Skip to content

MS_JWTBearerGrant

nishi_74322014 edited this page Sep 1, 2026 · 1 revision

JWT bearer token authorizationグラント種別

概要

OAuth 2.0 JWT Bearer Token Flow とも呼ばれる。

  • より高度なClient Credentials グラント種別的仕組み
    (ユーザによる認証・認可手順なしに直接 Access Token を取得する)。

  • OAuth 2.0 / OIDCを拡張するアサーションの仕様で、
    RFC 7521, 7523によって構成されている。

  • OAuth 2.0 では
    「クライアントは 1 回のリクエストにおいて二つ以上の認証方式を利用してはならない (MUST NOT)」
    と言われている。

  • Token エンドポイントで、JWT(JWS) で強化されたクライアント認証を使用して、
    OAuth 2.0 の Access Token を要求する方法を定義。

補足(何が嬉しいのか): client_secret
共有秘密なので、認可サーバ側にも同じ値が保存され、
通信のたびにネットワークに流れる。
JWT アサーションは秘密鍵で署名した短命の JWT を毎回作って送るため、

  • 秘密の値そのものは決して流れない
  • 認可サーバは公開鍵だけを持てばよい
  • exp / jti で再利用を防げる

という利点がある。
Google / Microsoft / Salesforce のサーバ間 API 認証が
いずれもこの方式を採るのはこのためである。

クライアント認証

  • 以下は、既定のクライアント認証が
    有る場合」と
    無い場合」で「場合分け」した概要説明。
  • 前者は既存のグラントタイプ中に組み込み、
    後者は新設された urn:ietf:params:oauth:grant-type:jwt-bearer と言う
    新しいグラントタイプを使用する。
  • 注:「既定のクライアント認証が無い場合 = Public クライアントの場合」と言う事ではない
    (そもそも Public クライアントでの利用は想定されていない)。

(既定の)クライアント認証ありの場合

クライアントの身元も独立して検証したい場合は、既存のグラントタイプ中に組み込む。

移行メモ(衍字): 「クライアントの身元も独立して検証したい場合は前者は、」の
重複を整理した。

クライアント認証ありの概要

クライアント認証ありのフロー

などのユースケースのフローがある。

※ 仕様として定義されているのは、Token エンドポイントに対するリクエスト部のみ。

(既定の)クライアント認証なしの場合

「JWT の発行者の信頼だけで十分」若しくは「クライアント特定が不要・不可」な場合は
新設されたグラントタイプを使用する。

クライアント認証なしの概要

  • (既定の)クライアント認証を使用しない
    (別の信頼できる他システムが発行した JWT(JWS) を使用する。
  • 用例にもある Google や Microsoft、Salesforce などの
    WebAPI 認証の方式として採用されている。

クライアント認証なしのフロー

JWT(JWS) 作成のための証明書を生成 or 取得する。

仕様(7521)

  • 単体では利用できず、RFC 7522, 7523 のサブ仕様の共通部分を抽象化した仕様。
  • Client と Resource Server(Authorization Server)を統合するような状況下での利用が想定されている。
    • Resource Owner としてのエンド・ユーザの介入を必要としない。
    • client_secret を必要としない(Client Credentials グラント種別の)代替メカニズム。

フレームワーク

JWT Secured Authorization Request (JAR)とリンクしている。

Self-Issued Assertion

(既定の)クライアント認証ありの場合
ローカルで Assertion を生成する。

  • フロー
Relying
Party                     Client
  |                          |
  |                          | 1) Create
  |                          |    Assertion
  |                          |--------------+
  |                          |              |
  |                          | 2) Assertion |
  |                          |<-------------+
  |    3) Assertion          |
  |<-------------------------|
  |                          |
  |    4) OK or Failure      |
  |------------------------->|
  |                          |

Assertion Created by Third Party

(既定の)クライアント認証なしの場合で、
用例で紹介されていないが「別の信頼できる他システム」によって Assertion を生成する。

  • フロー
Relying
Party                     Client                   Token Service
  |                          |                         |
  |                          |  1) Request Assertion   |
  |                          |------------------------>|
  |                          |                         |
  |                          |  2) Assertion           |
  |                          |<------------------------|
  |    3) Assertion          |                         |
  |<-------------------------|                         |
  |                          |                         |
  |    4) OK or Failure      |                         |
  |------------------------->|                         |
  |                          |                         |

アサーション

これを使ってアクセストークン・リクエストする。

文脈上のアサーション

この文脈上でのアサーションは、

  • Authorization Server は、

    • 一般的に認可付与の短命表現で、
      アサーションの有効期間を越えるアクセストークンを発行すべきでない。
    • アサーション許可要求に応答して
      • リフレッシュトークンを発行せず、
      • アクセストークンを短い寿命で発行する。
  • Client は、

    • 同じアサーションを使用して新しいアサーションを要求したり、
    • 有効・若しくは新しいアサーションを使用して、
      期限切れのアクセストークンをリフレッシュしたり、

    できる。

補足(リフレッシュ トークンが要らない理由): クライアントは
いつでも自分で新しいアサーションを作れる(秘密鍵を持っているため)ので、
リフレッシュ トークンを預かって管理する必要がない。
後述の Google の例で「refresh_token を返さない」のはこのためである。

アサーションのタイプ

  • Bearer Assertions(持参人切符)

    • 本仕様に適したタイプのアサーション
    • アサーションを所有しているすべてのエンティティは、
      • 関連するリソースへのアクセスを取得するために
        (暗号鍵の所持を証明することなく)アサーションを使用できる。
      • 誤用を防止するために、アサーションは、保管・移送における露見から保護する必要がある。
      • 権限のない当事者にアサーションを漏らさないために、安全な通信チャネルを使用。
  • Holder-of-Key Assertions(記名式切符)

    • 本仕様に適さないタイプのアサーション(確かに仕様名からして ... だったら書くな。と、)

    • アサーションを提示するエンティティは、関連するリソースにアクセスするには、
      追加の暗号資料の所持を証明する必要がある。

    • 従って、

      • Authorization Server(STS) は、アサーションにキー識別子をバインドする。
      • Client は、アサーションを提示するときに、その識別子に対応するキーを
        知っていることを Resource Server(Authorization Server)に示す必要がある。
    • 鍵所有者アサーションシステムのベースラインとして使用することができるが、
      場合によっては、以下が必要になる。

      • (秘密鍵の所有証明をサポートするための)追加のメカニズム
      • セキュリティモデルの変更(例えば、オーディエンスの要件を緩和するため)。

補足(アサーションとアクセス トークンは別物): ここで
「Bearer」「Holder-of-Key」と言っているのは
クライアントが送るアサーションの話であって、
結果として発行されるアクセス トークンの話ではない。
仕様名が「JWT bearer token」なのは前者を指す。
発行されるアクセス トークンを記名式にする話は
OAuth2.0 Proof of Possession」以降の仕様が扱う。

アサーションのクレームセット

以下のクレームが必要。

アサーションの署名

  • 署名またはメッセージ認証コードを生成する
  • アルゴリズムは任意(この仕様の範囲外)

パラメタ

  • TLS(Transport Layer Security)が必須。
  • アサーションの認可付与としての使用を定義。

grant_type

scope

要求された範囲は、OAuth 2.0 [RFC6749]の 3.3 節に記述されているとおり。

client_id

パラメタに依存するクライアント認証の形式が使用されている場合にのみ必要。

client_assertion系

(既定の)クライアント認証ありに対応するパラメタ。

  • client_assertion_type
    urn:ietf:params:oauth:grant-type:*

    • urn:ietf:params:oauth:grant-type:saml2-bearer
    • urn:ietf:params:oauth:grant-type:jwt-bearer
  • client_assertion
    RFC7523のアサーションを参照。

移行メモ(正誤): client_assertion_type の値は
urn:ietf:params:oauth:**client-assertion-type**:jwt-bearer である
grant-type ではない)。
後述のリクエスト例では正しく client-assertion-type と書かれている。

assertion

(既定の)クライアント認証なしに対応するパラメタ。

RFC7523のアサーションを参照。

リクエスト・レスポンス

アクセストークン・リクエスト

  • (既定の)クライアント認証あり

    • grant_type=authorization_code

      • ヘッダ

        POST /token HTTP/1.1
        Host: server.example.com
        Content-Type: application/x-www-form-urlencoded
        
      • ボディ

        grant_type=authorization_code&
        code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
        client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3AX-bearer&
        client_assertion=SAML2 or JWT assertion
        
    • grant_type=client_credentials

      • ヘッダ

        POST /token HTTP/1.1
        Host: server.example.com
        Content-Type: application/x-www-form-urlencoded
        
      • ボディ

        grant_type=client_credentials&
        client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3AX-bearer&
        client_assertion=SAML2 or JWT assertion
        
  • (既定の)クライアント認証なし

    • ヘッダ

      POST /token HTTP/1.1
      Host: server.example.com
      Content-Type: application/x-www-form-urlencoded
      
    • ボディ

      grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3AX-bearer&
      assertion=SAML2 or JWT assertion
      

アクセストークン・レスポンス

仕様中に明記なし。

エラー・レスポンス

  • OAuth 2.0 [RFC6749]で定義されているエラー応答を構成

  • (既定の)クライアント認証あり

    • Authorization Server は、
      アサーションが有効でないか複数のクライアント認証メカニズムが使用されている場合、

      • "error" パラメータの値は "invalid_client" エラーコードでなければならない。
      • "error_description" または "error_uri" パラメータを使用して、
        クライアントのアサーションが無効であると考えられた理由に関する追加情報を含めることができる。
      • ヘッダ

        HTTP/1.1 400 Bad Request
        Content-Type: application/json
        Cache-Control: no-store
        
      • ボディ

        {
         "error":"invalid_client",
         "error_description":"assertion has expired"
        }
  • (既定の)クライアント認証なし
    アサーションが有効でないか期限が切れた場合、

    • Authorization Server は、

      • "error" パラメータの値は "invalid_grant" エラーコードでなければならない。
      • "error_description" または "error_uri" パラメータを使用して、
        アサーションが無効とみなされた理由に関する追加情報を含めることができる。
      • ヘッダ

        HTTP/1.1 400 Bad Request
        Content-Type: application/json
        Cache-Control: no-store
        
      • ボディ

        {
         "error":"invalid_grant",
         "error_description":"Audience validation failed"
        }

移行メモ(例の記述): 1 つ目のエラー例の JSON は、
元ページでは "error":"invalid_client" の行末にカンマが無かったため補った。

7521のセキュリティに関する考慮事項

  • RFC 7522, 7523などを使用すれば、大方問題ない。

  • その他、

    • SSL/TLS を使用する。
    • Assertion ID を実装する。

仕様(7523)

RFC 7521のアサーションにJWT(JWS) アサーションを使用したもの。

JWT(JWS)アサーション

これを使ってアクセストークン・リクエストする。

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

  • アサーションのクレームセットを参考に、

  • 必須(MUST)

    • "iss" (issuer) claim
    • "aud" (audience) claim
    • "sub" (subject) claim
    • "exp" (expiration time) claim
  • してもよい(MAY)

    • "iat" (issued at) claim
    • "jti" (JWT ID) claim
      = Assertion ID
    • "nbf" (not before) claim
      トークンを受け入れてはならない前の時間を識別する。

JWT(JWS)の例

  • 以下、RFC の JWT(JWS)
    よくよく確認すると、URL はなに?(Scheme?)

    • ヘッダ

      {"alg": "ES256", "kid": "16"}
    • ペイロード

      {
       "iss":"https://jwt-idp.example.com",
       "sub":"mailto:mike@example.com",
       "aud":"https://jwt-rp.example.net",
       "nbf":1300815780,
       "exp":1300819380,
       "http://claims.example.com/member":true
      }
  • 以下、Google の JWT(JWS)
    よくよく確認すると、sub が無かったりする。

    • ヘッダ

      {
        "alg": "RS256",
        "typ": "JWT"
      }
    • ペイロード

      {
       "iss":"サービスアカウントのメールアドレス",
       "scope":"利用するAPIのスコープ",
       "aud":"https://www.googleapis.com/oauth2/v3/token",
       "exp":"トークンの有効期限To",
       "iat":"トークンの有効期限From"
      }

補足(上記 2 つの疑問への答え):

  • 「URL はなに?」iss / aud の値は
    URI 形式の識別子であって、実際にアクセスできる必要はない
    mailto: スキームが使われているのもこのため)。
    ただし実装によっては aud に Token エンドポイントの実 URL を要求する。
  • sub が無い」 … Google のサービス アカウントは
    iss 自身に対して権限を要求する(= subiss と同じ)ため、
    省略されている。
    他のユーザになりすまして API を呼ぶ
    ドメイン全体の委任を使う場合は、sub に対象ユーザの
    メール アドレスを入れる。

7523のパラメタ

移行メモ(読み取り): 上記は
client_assertion には JWT を 1 つだけ含めること
(複数含めてはならない)」という意味である。

7523のリクエスト・レスポンス

7523のアクセストークン・リクエスト

  • (既定の)クライアント認証あり

    • ヘッダ

      POST /token.oauth2 HTTP/1.1
      Host: as.example.com
      Content-Type: application/x-www-form-urlencoded
      
    • ボディ

      grant_type=authorization_code&
      code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
      client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
      client_assertion=...JWS...
      
  • (既定の)クライアント認証なし

    • ヘッダ

      POST /token.oauth2 HTTP/1.1
      Host: as.example.com
      Content-Type: application/x-www-form-urlencoded
      
    • ボディ

      grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&
      assertion=...JWS...
      

7523のアクセストークン・レスポンス

仕様中に明記がないが、Google でのレスポンスは以下の通り。

{
  "access_token":"XXXXXXXXXX",
  "token_type":"bearer",
  "expires_in":nnnnn
}

※ ポイント : refresh_token を返さない。

7523のエラー・レスポンス

仕様(7521)のエラー・レスポンスと同じ。

署名アルゴリズム

本仕様中に記載はないが、
OpenID Connect - クライアント認証」を参考にするとイイ。

参考

RFC 7521, 7522, 7523

用例

Googleの例

以下を見ると、

通常の OAuth 2.0 の

以外に、

クライアント証明書(pfx 形式の電子証明書)を使って、
サービスアカウントで認証する方法がある模様。

ちなみに、ここでは、Google.Apis.Analytics Client Library に
処理がラッピングされていたため。詳細が不明だったが、

以下を見ると、この Client Library の中では、JWTが使用されている模様。

これが、

「JWT bearer token authorization グラント種別」

の用例である模様。

上記のサイトには、

Service Accounts = JWT Bearer Token Profile

であることが明記されている。

Microsoft (AzureAD) の例

Microsoft Azure Active Directory

Googleと同様に、以下を見ると、

通常の OAuth 2.0 の

以外に、

「JWT bearer token authorization グラント種別」

をサポートしている模様。

ただし、処理は、
ADAL(Active Directory Authentication Library)
にラップされているため JWT 作成処理の詳細などを見ることは出来ない。

補足(ADAL は廃止): ADAL は 2022 年 12 月にサポート終了し、
後継は **MSAL(Microsoft Authentication Library)**である。
証明書によるクライアント認証(private_key_jwt)は
MSAL でも WithCertificate() として同じ形で提供されている。

Salesforceの例

以下の Qiita 記事を参照すると、Salesforce は、

  • OAuth 2.0 JWT べアラートークンフロー
  • OAuth 2.0 SAML ベアラーアサーションフロー

の 2 つのフローをサポートしている模様。

原理はほぼ同じで、SAMLより JWT のほうが動作環境的な制約は少ないとのこと。

本 Wiki 内


Tags: IT国際標準, 認証基盤, クレームベース認証, OAuth

NetDevInfraWiki

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

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally