CIBA + Rich Authorization Requests (RAR)
🎯 この機能を一言で説明すると
「スマホで認証するときに、もっと細かく『何をどこまで許可するか』を指定できる機能」
従来は「メールを見る権限」のような大雑把な指定しかできませんでしたが、RARを使えば「どのフォルダの、どのメールを、いつまで見られるか」まで細かく指定できます。
💡 なぜこの機能が必要なのか
従来の方法(スコープ)の問題点
アプリ「お客様の口座情報を見る権限をください」
あなた「OK(全口座の全情報が見られる)」← 粗すぎる!
- ❌ 「口座を見る」権限しかなく、どの口座かは指定できない
- ❌ 「読む」権限だけで、何を読むかは制御できない
- ❌ 複数の細かい権限が必要なとき、何度もリクエストが必要
RARで解決できること
アプリ「個人口座12345の残高だけ見る権限をください」
あなた「OK(個人口座の残高だけが見られる)」← 安心!
- ✅ どのリソースに対する権限かを明示
- ✅ 何ができるか(読む、書く、削除など)を細かく指定
- ✅ 複数の異なる権限を1回のリクエストでまとめて要求
👤 こんな人・こんな場面で便利
| 使う人 | 使う場面 | メリット |
|---|---|---|
| 銀行アプリ開発者 | 決済アプリで振込を実行 | 「口座A から 1,000円を口座B に振込」という具体的な権限を要求 |
| 会計ソ フト開発者 | 複数の口座情報を取得 | 「個人口座の残高」と「会社口座の取引履歴」を同時に要求 |
| 医療アプリ開発者 | 患者の医療記録へアクセス | 「2024年の血液検査結果だけ」という限定的なアクセス |
📱 ユーザーから見るとこう見える
スマホに届く認証リクエスト画面のイメージ:
━━━━━━━━━━━━━━━━━━━━━━━━
認可リクエスト
━━━━━━━━━━━━━━━━━━━━━━━━
アプリ名: 家計簿アプリ
📋 要求される権 限の詳細:
【個人口座 (口座番号: ****1234)】
✓ 残高の確認
✓ 過去3ヶ月の取引履歴の閲覧
【会社口座 (口座番号: ****5678)】
✓ 入金履歴の閲覧のみ
━━━━━━━━━━━━━━━━━━━━━━━━
[許可する] [拒否する]
━━━━━━━━━━━━━━━━━━━━━━━━
従来の方法だと: 「すべての口座情報を見る権限」という曖昧な表示だけ
RARを使うと: 上記のように具体的に「何を・どこまで」が表示される
📚 用語集(初めての方向け)
| 用語 | 簡単な説明 | 具体例 |
|---|---|---|
| CIBA | スマホなどの別のデバイスで認証する仕組み | PCで「ログイン」→スマホに通知→スマホで承認→PCでログイン完了 |
| OAuth 2.0 | アプリにパスワードを渡さずに権限を与える標準的な方法 | 「Googleの連絡先を見る権限をXXアプリに渡す」 |
| スコープ | 従来の粗い権限指定方法 | "read:email" = メール読む権限(どのメールかは指定できない) |
| RAR | 細かい権限指定ができる新しい方法 | 「個人フォルダの未読メールだけ」という具体的な指定が可能 |
| authorization_details | RARで権限の詳細を記述するパラメータ | 「何を、どこまで、どうするか」を JSON 形式で記述 |
| Request Object | 認証リクエストをJWT形式で署名付きで送る方法 | セキュリティを高めるための技術(改ざん防止) |
🆚 スコ ープ vs RAR の比較
従来のスコープだけの場合
{
"scope": "read:accounts"
}
結果:
- ❌ 全ての口座が見える
- ❌ 残高も取引履歴も全部見える
- ❌ 個人口座も会社口座も区別なし
RARを使った場合
{
"scope": "openid profile",
"authorization_details": [
{
"type": "account_information",
"account_id": "personal-account-1234",
"actions": ["read_balance"],
"valid_until": "2024-12-31"
}
]
}
結果:
- ✅ 個人口座1234だけが対象
- ✅ 残高の閲覧のみ許可(取引履歴は見えない)
- ✅ 2024年末まで有効
概要(技術者向け)
idp-server は、CIBA (Client Initiated Backchannel Authentication) フローにおいて RFC 9396 - OAuth 2.0 Rich Authorization Requests をサポートしています。
Rich Authorization Requests (RAR) により、従来のスコープベースの認可に加えて、きめ細かい認可要求を authorization_details パラメータで表現できます。
ユースケース(詳細)
- 金融取引: 決済金額・通貨・受取人などの詳細な取引情報の認可
- データアクセス: 特定のリソース(口座・ファイル等)への限定的なアクセス権限
- 複数リソース: 異なる種類の認可を1つのリクエストでまとめて要求
RFC 9396 準拠
サポート機能
| 機能 | RFC 9396 Section | サポート状況 |
|---|---|---|
authorization_details パラメータ | Section 2 | ✅ 完全対応 |
| Request Object統合 | Section 3 | ✅ 完全対応 |
| 無効なtype拒否 | Section 4, 5 | ✅ 完全対応 |
| トークンレスポンス返却 | Section 7 | ✅ 完全対応 |
| 複数authorization_details処理 | Section 2 | ✅ 完全対応 |
検証ロジック
idp-server は RFC 9396 に準拠した以下の検証を実施します:
- type必須チェック: 各authorization_detailには
typeフィールドが必須 - サポート済みtype検証: Authorization Server設定で定義されたtypeのみ許可
- クライアント認可検証: クライアントに認可されたtypeのみ許可
検証に失敗した場合、invalid_authorization_details エラーが返却されます。
シーケンス
authorization_details パラメータ
基本構造
{
"authorization_details": [
{
"type": "account_information",
"actions": ["list_accounts", "read_balances"],
"locations": ["https://example.com/accounts"]
}
]
}
フィールド定義
| フィールド | 必須 | 説明 | 例 |
|---|---|---|---|
type | ✅ | 認可詳細のタイプ識別子 | "account_information" |
actions | ❌ | 実行可能なアクション | ["read", "write"] |
locations | ❌ | リソースのURL | ["https://api.example.com"] |
datatypes | ❌ | データタイプ | ["balance", "transaction"] |
identifier | ❌ | リソース識別子 | "account-123" |
privileges | ❌ | アクセス権限 | ["read-only"] |
Request Object統合
🔐 初めての方向け:Request Objectって何?
簡単に言うと: リクエストパラメータをJWT形式で署名して送る方法です。
なぜ使うの?:
- 🔒 改ざん防止: 署名があるので、途中で書き換えられない
- 🔐 セキュリティ向上: 特に金融系アプリで重要
- 📦 パラメータをまとめて送れる: 1つのJWTに全部入れられる
イメージ:
【普通の方法】
パラメータを個別に送 る
↓
途中で誰かが書き換えられるかも...
【Request Object】
パラメータをJWTで署名して送る
↓
署名があるので改ざんできない!安全!
RFC 9396 Section 3 準拠(技術者向け)
Request Object (JWT) 内で authorization_details を指定可能です。
実装例:
// ライブラリを使ってJWTを作成
const jwt = require('jsonwebtoken');
const fs = require('fs');
// 秘密鍵を読み込む
const privateKey = fs.readFileSync('path/to/private-key.pem');
// Request Objectを作成
const requestObject = jwt.sign(
{
// 通常のパラメータ
client_id: "household-app-123",
scope: "openid profile",
binding_message: "999",
user_code: "userCode001",
login_hint: "sub:user123,idp:idp-server",
// authorization_detailsもここに含められる!
authorization_details: [
{
"type": "payment_initiation",
"actions": ["initiate"],
"instructedAmount": {
"currency": "EUR",
"amount": "123.50"
},
"creditorAccount": {
"iban": "DE02100100109307118603"
}
}
],
// JWTの標準クレーム
aud: "https://idp.example.com",
iss: "household-app-123",
exp: Math.floor(Date.now() / 1000) + 3600, // 1時間後に期限切れ
iat: Math.floor(Date.now() / 1000),
jti: "unique-request-id-12345"
},
privateKey,
{ algorithm: 'ES256' } // 署名アルゴリズム
);
// リクエストに含めて送る
const response = await axios.post(
'https://idp.example.com/backchannel-authentication',
{
client_id: 'household-app-123',
client_secret: 'your-secret',
request: requestObject // ← JWT形式のRequest Object
}
);
パラメータ優先順位
RFC 9396 Section 3 に従い、以下の優先順位が適用されます:
Request Object内のauthorization_details > 通常パラメータのauthorization_details
具体例:
// リクエストの例
{
client_id: "app123",
authorization_details: '[{"type":"A"}]', // 通常パラメータ
request: "eyJ..." // JWT(中身: authorization_details: [{"type":"B"}])
}
// → Request Object内の "type":"B" が優先される!
検証タイミング
Request Objectのパース後、通常パラメータと同じ検証ロジックが自動的に適用されます。
処理の流れ:
1. Request Objectをデコード・検証
2. 通常パラメータとマージ(Request Objectが優先)
3. authorization_detailsを検証
- typeが必須か
- サポートされているtypeか
- クライアントに認可されているtypeか
4. OK → 認証処理へ
NG → invalid_authorization_details エラー