メインコンテンツまでスキップ

RFC 9396: OAuth 2.0 Rich Authorization Requests(RAR)

RFC 9396 は、従来の scope パラメータでは表現できない複雑な認可要求を構造化された JSON で表現するための仕様です。


第1部: 概要編

Rich Authorization Requests とは?

RAR は、認可リクエストで詳細な認可情報を JSON 形式で指定できるようにする拡張です。

従来(scope):
scope=read write

問題:
- 「何を」read するのか不明
- 金額制限などを表現できない
- リソース固有の条件を指定できない

RAR:
authorization_details=[
{
"type": "payment_initiation",
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
},
"creditorAccount": {
"iban": "DE89370400440532013000"
}
}
]

なぜ RAR が必要なのか?

課題scope の限界
詳細な権限read ではなく「100EUR まで」を表現できない
リソース指定どのリソースに対する権限か不明確
条件付き認可時間制限や回数制限を表現できない
複雑なユースケース決済、銀行 API、ヘルスケアなど

典型的なユースケース

1. 決済(PSD2/Open Banking):
「DE89...の口座から 100EUR を送金する権限」

2. データ共有:
「2024年1月から3月の取引履歴を読み取る権限」

3. ヘルスケア:
「患者 ID: 12345 のカルテを参照する権限」

4. ファイルアクセス:
「/documents/contracts/ フォルダの PDF を読み取る権限」

第2部: 詳細編

authorization_details パラメータ

特性説明
形式JSON 配列
場所認可エンドポイント、トークンエンドポイント、PAR
エンコードURL エンコード必須
複数指定配列で複数の認可詳細を指定可能

基本構造

[
{
"type": "payment_initiation",
"locations": ["https://api.bank.example.com"],
"actions": ["initiate", "status"],
"datatypes": ["payment"],
"identifier": "payment-12345",
"privileges": ["execute"],
// type 固有のフィールド
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
}
}
]

共通フィールド

フィールド必須説明
type認可タイプの識別子
locationsリソースサーバーの URI
actions許可されるアクション
datatypesアクセス対象のデータタイプ
identifier特定のリソースの識別子
privileges許可される権限

認可リクエスト

GET リクエスト(エンコード済み)

GET /authorize?
response_type=code
&client_id=s6BhdRkqt3
&redirect_uri=https://client.example.com/callback
&state=xyz
&authorization_details=%5B%7B%22type%22%3A%22payment_initiation%22%2C%22instructedAmount%22%3A%7B%22amount%22%3A%22100.00%22%2C%22currency%22%3A%22EUR%22%7D%7D%5D

PAR(Pushed Authorization Request)と組み合わせ

POST /par HTTP/1.1
Host: auth.example.com
Content-Type: application/json
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

{
"response_type": "code",
"client_id": "s6BhdRkqt3",
"redirect_uri": "https://client.example.com/callback",
"state": "xyz",
"code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
"code_challenge_method": "S256",
"authorization_details": [
{
"type": "payment_initiation",
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
},
"creditorAccount": {
"iban": "DE89370400440532013000"
}
}
]
}

トークンリクエスト

POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://client.example.com/callback
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

トークンレスポンス

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"authorization_details": [
{
"type": "payment_initiation",
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
},
"creditorAccount": {
"iban": "DE89370400440532013000"
}
}
]
}

認可サーバーは、実際に付与された authorization_details をレスポンスに含めます。

JWT アクセストークンの場合

{
"iss": "https://auth.example.com",
"sub": "user-123",
"aud": "https://api.bank.example.com",
"exp": 1704153600,
"iat": 1704150000,
"authorization_details": [
{
"type": "payment_initiation",
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
},
"creditorAccount": {
"iban": "DE89370400440532013000"
}
}
]
}

ユースケース別の例

1. 決済開始(Payment Initiation)

[
{
"type": "payment_initiation",
"actions": ["initiate", "status", "cancel"],
"locations": ["https://api.bank.example.com/payments"],
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
},
"creditorName": "Merchant XYZ",
"creditorAccount": {
"iban": "DE89370400440532013000"
},
"remittanceInformationUnstructured": "Ref: Invoice 12345"
}
]

2. 口座情報アクセス(Account Information)

[
{
"type": "account_information",
"actions": ["read"],
"locations": ["https://api.bank.example.com/accounts"],
"datatypes": ["accounts", "balances", "transactions"],
"accounts": [
{
"iban": "DE89370400440532013000"
}
],
"historicalPeriod": {
"from": "2024-01-01",
"to": "2024-03-31"
}
}
]

3. ヘルスケアデータ

[
{
"type": "health_record_access",
"actions": ["read"],
"locations": ["https://api.hospital.example.com/records"],
"datatypes": ["diagnoses", "medications", "lab_results"],
"patient_id": "P-12345",
"time_period": {
"start": "2023-01-01",
"end": "2024-01-01"
}
}
]

4. ファイルストレージ

[
{
"type": "file_access",
"actions": ["read", "write"],
"locations": ["https://api.storage.example.com"],
"paths": [
"/documents/contracts/*",
"/documents/invoices/*"
],
"file_types": ["pdf", "docx"]
}
]

認可サーバーによる処理

authorization_details の処理フロー:

1. パース・検証
├── JSON 形式の検証
├── 必須フィールド(type)の確認
└── type ごとのスキーマ検証

2. 認可画面の表示
└── authorization_details の内容を
ユーザーに分かりやすく表示

3. 認可の記録
└── 認可コードまたはトークンに
authorization_details を紐付け

4. トークン発行
└── JWT の場合は authorization_details
クレームを含める

5. イントロスペクション
└── authorization_details を返す

認可画面の表示例

┌─────────────────────────────────────────────────────┐
│ 認可リクエスト │
├─────────────────────────────────────────────────────┤
│ │
│ Merchant XYZ があなたのアカウントへの │
│ アクセスを要求しています: │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 決済の開始 │ │
│ │ │ │
│ │ 金額: €100.00 │ │
│ │ 送金先: DE89 3704 0044 0532 0130 00 │ │
│ │ 受取人: Merchant XYZ │ │
│ │ 摘要: Ref: Invoice 12345 │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ [ 許可する ] [ 拒否する ] │
│ │
└─────────────────────────────────────────────────────┘

scope との併用

{
"scope": "openid profile",
"authorization_details": [
{
"type": "payment_initiation",
"instructedAmount": {
"amount": "100.00",
"currency": "EUR"
}
}
]
}
  • scope: 一般的な権限(OpenID Connect など)
  • authorization_details: 詳細な権限(決済など)

リソースサーバーの検証

セキュリティ考慮事項

項目推奨事項
PAR の使用authorization_details は PAR 経由で送信
署名付きリクエストRequest Object で署名
最小権限必要最小限の権限のみ要求
有効期限認可の有効期限を設定
監査ログauthorization_details を含めて記録
ユーザー同意詳細を明確に表示して同意を得る

ディスカバリーメタデータ

{
"issuer": "https://auth.example.com",
"authorization_details_types_supported": [
"payment_initiation",
"account_information"
]
}

参考リンク