Open4

RFC 9396 OAuth 2.0 Rich Authorization Requests

yapooyapoo

RFC 9396 - OAuth 2.0 Rich Authorization Requests

概要

OAuth 2.0 [1] では要求する認可を表すのに scope パラメータを定義していた。これは単なる文字列であり、多くの場合にはこれで十分である一方で、表現力が不足しているケースもあると考えられる。

そこで本仕様では認可エンドポイントとトークンエンドポイントに authorization_details パラメータを追加し、これで JSON によって要求する認可を記述する。以下は Section 2.2 に記載の authorization_details の例である。これと同等の内容を scope で記述するのは難しいであろう。

[
   {
      "type": "account_information",
      "actions": [
         "list_accounts",
         "read_balances",
         "read_transactions"
      ],
      "locations": [
         "https://example.com/accounts"
      ]
   },
   {
      "type": "payment_initiation",
      "actions": [
         "initiate",
         "status",
         "cancel"
      ],
      "locations": [
         "https://example.com/payments"
      ],
      "instructedAmount": {
         "currency": "EUR",
         "amount": "123.50"
      },
      "creditorName": "Merchant A",
      "creditorAccount": {
         "iban": "DE02100100109307118603"
      },
      "remittanceInformationUnstructured": "Ref Number Merchant"
   }
]
脚注
  1. RFC 6749 ↩︎

yapooyapoo

authorization_details の構造

authorization_details は JSON オブジェクトの配列である。各オブジェクトは type というキーを必須で持ち、これによってそのオブジェクトの型を示す。加えて以下のフィールドが提案されている。これらは必須のパラメータではないが、authorization_details の設計の際に有用である。

value type description
locations array<string> リソースやリソースサーバーの場所を示す文字列のリストで、典型的には URI のリストである
actions array<string> リスースに対して取れるアクションを示す
datatypes array<string> リソースのうちどのデータへの権限を要求するかを示す
identifier string リソースサーバーの API で用いるリソースの識別子
privileges array<string> リソースに対する権限の種類やレベルを表す

以下は Section 2.2 で示される authorization_details の例である

[
   {
      "type":"photo-api",
      "actions":[
         "read",
         "write"
      ],
      "locations":[
         "https://server.example.net/",
         "https://resource.local/other"
      ],
      "datatypes":[
         "metadata",
         "images"
      ],
      "geolocation":[
         {
            "lat":-32.364,
            "lng":153.207
         },
         {
            "lat":-35.364,
            "lng":158.207
         }
      ]
   },
   {
      "type":"financial-transaction",
      "actions":[
         "withdraw"
      ],
      "identifier":"account-14-32-32-3",
      "currency":"USD"
   }
]
yapooyapoo

認可エンドポイント

認可エンドポイントまたはそれに相当するエンドポイント (デバイス認可エンドポイント[1]やバックチャンネル認証エンドポイント[2])で、リクエストパラメータとして authorization_details を指定する。RFC 6749 の認可エンドポイントの利用にあたっては、PAR [3] や JAR [4] を利用することもできる。

認可サーバーはここで指定された authorization_details に基づいてリソースオーナーに対して許諾を得ることになるが、ここでリソースオーナーは authorization_details のサブセットに対して許諾を出す事もできる [5]

以下は RFC 6749 の認可エンドポイントのリクエストの例である。このように authorization_details を丸ごと application/x-www-form-urlencoded でエンコードする。

GET /authorize?response_type=code
   &client_id=s6BhdRkqt3
   &state=af0ifjsldkj
   &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
   &code_challenge_method=S256
   &code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bwc-uCHaoeK1t8U
   &authorization_details=%5B%7B%22type%22%3A%22account%5Finfo
   rmation%22%2C%22actions%22%3A%5B%22list%5Faccounts%22%2C%22
   read%5Fbalances%22%2C%22read%5Ftransactions%22%5D%2C%22loca
   tions%22%3A%5B%22https%3A%2F%2Fexample%2Ecom%2Faccounts%22%
   5D%7D%2C%7B%22type%22%3A%22payment%5Finitiation%22%2C%22act
   ions%22%3A%5B%22initiate%22%2C%22status%22%2C%22cancel%22%5
   D%2C%22locations%22%3A%5B%22https%3A%2F%2Fexample%2Ecom%2Fp
   ayments%22%5D%2C%22instructedAmount%22%3A%7B%22currency%22%
   3A%22EUR%22%2C%22amount%22%3A%22123%2E50%22%7D%2C%22credito
   rName%22%3A%22Merchant%20A%22%2C%22creditorAccount%22%3A%7B
   %22iban%22%3A%22DE02100100109307118603%22%7D%2C%22remittanc
   eInformationUnstructured%22%3A%22Ref%20Number%20Merchant%22
   %7D%5D HTTP/1.1
Host: server.example.com

認可サーバーは受け取った authorization_details の各オブジェクトを検証し、以下のいずれかに当たるものが含まれる場合にはエラーコード invalid_authorization_details でエラーを通知する。

  • type の値が認可サーバーがサポートしない値、またはそのクライアントにはサポートしない値の場合
  • type で定められた型に含まれないフィールドが含まれる場合
  • type で定められた型で必要なフィールドの値が不正、または存在しない場合

なお、scopeauthorization_details を同時に指定することも可能である。ただしこれは scope から authorization_details への (もしくは逆の) 段階的な移行のための仕様であり、どちらか一方のみを用いることが推奨される。両方指定された場合は、両方で示される権限の和が要求されているものとして処理をしなければならない。同様に resource [6] パラメータを指定することも可能である。

脚注
  1. RFC 8628 OAuth 2.0 Device Authorization Grant ↩︎

  2. OpenID Connect Client-Initiated Backchannel Authentication Flow ↩︎

  3. RFC 9126 OAuth 2.0 Pushed Authorization Requests ↩︎

  4. RFC 9101 The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR) ↩︎

  5. これは scope パラメータの場合も同様である ↩︎

  6. RFC 8707 Resource Indicators for OAuth 2.0 ↩︎

yapooyapoo

トークンエンドポイント

トークンエンドポイントでも authorization_details を指定することでアクセストークンの持つ権限を指定することができる [1]

ここで、トークンエンドポイントで指定する authorization_details はリソースオーナーが許諾を出した範囲内で指定されなければならないが、新しい authorization_details が既存の authorization_details に含まれるかの判定は、双方の各 JSON Object の完全一致による比較のみで行えるとは限らないことに注意する必要がある。

例えば認可エンドポイントで以下の authorization_details が指定されたとし、

[
    {
        "type": "example_api",
        "actions": [
            "write"
        ]
    }
]

その後トークンエンドポイントでは以下が指定されたとする。

[
    {
        "type": "example_api",
        "actions": [
            "read"
        ]
    }
]

一般に書き込み権限は読み取り権限を含むと考えられるから後者は前者の範囲内である。この結論は各オブジェクトの単純な比較によっては得られない。このように認可サーバーは自らが導入する authorization_detailstype に応じた適切な比較の仕様を定義する必要がある。

レスポンス

アクセストークンの持つ権限が authorization_details によって記述されるとき、トークンエンドポイントのレスポンスでは下記のように authorization_details パラメータを持たなければならない。以下は Section 7 に記載のレスポンスの例である。

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
   "access_token": "2YotnFZFEjr1zCsicMWpAA",
   "token_type": "example",
   "expires_in": 3600,
   "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
   "authorization_details": [
      {
         "type": "payment_initiation",
         "actions": [
            "initiate",
            "status",
            "cancel"
         ],
         "locations": [
            "https://example.com/payments"
         ],
         "instructedAmount": {
            "currency": "EUR",
            "amount": "123.50"
         },
         "creditorName": "Merchant A",
         "creditorAccount": {
            "iban": "DE02100100109307118603"
         },
         "remittanceInformationUnstructured": "Ref Number Merchant"
      }
   ]
}

認可サーバーが決めるポリシーによっては、ここで返却される authorization_details はクライアントがはじめ認可エンドポイントで指定した authorization_details とは異なる場合がある。これはリソースオーナーがクライアントが指定した authorization_details の一部に対して許諾を出した場合に加え、リソースオーナーと認可サーバーのやり取りの中で得られる権限の詳細が決定する場合もありえる。

Section 7.1 に記載の例を示す。まず以下がクライアントのリクエストに含まれる authorization_details である。ここで accounts , balances , transactions には具体的な account_information の対象が含まれるが、クライアントが認可リクエストする時点ではここの詳細は決まっておらず、プレースホルダとして記載されているものとする。

[
   {
      "type": "account_information",
      "access": {
         "accounts": [],
         "balances": [],
         "transactions": []
      },
      "recurringIndicator":true
   }
]

その後リソースオーナーと認可サーバーのやり取りの中で詳細が決まり、トークンエンドポイントでは下記の authorization_details が返される

   {
      "type":"account_information",
      "access":{
         "accounts":[
            {
               "iban":"DE2310010010123456789"
            },
            {
               "maskedPan":"123456xxxxxx1234"
            }
         ],
         "balances":[
            {
               "iban":"DE2310010010123456789"
            }
         ],
         "transactions":[
            {
               "iban":"DE2310010010123456789"
            },
            {
               "maskedPan":"123456xxxxxx1234"
            }
         ]
      },
      "recurringIndicator":true
   }
]
脚注
  1. トークンエンドポイントはリクエストパラメータとして scope を受け付けない場合もある (認可コードフローなど)。authorization_details はどの場合に指定できるのかについては仕様に記述は見当たらなかった ↩︎